Рассылка закрыта
При закрытии подписчики были переданы в рассылку "О карьере и профессиональном развитии IT-специалистов" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Программирование для начинающих и не только
©Gigabyte 2005
include "../votehdr.html" ?>
Мониторинг принтераСегодня практически в каждом интернет-кафе к доступным услугам входит так же и распечатка текстовых и других документов. Но вот огранизация этого дела все еще остается на этапе минимальной автоматизации. Вот если бы удалось написать програмку, которая бы отслеживала кто, когда и скольо на печатал, и интегрировать ее в систему контроля копмьютерного клуба, то это не только бы избавило наших <бедных> администраторов от лишнего диалога с клиентом, но и придало клубу более современный оттенок.Теоретические основы мониторингаВ теории мониторинг принтера в Windows 98 не является чем-то черезвычайно сложным т.к. те же драйверы принтеров его не просто осуществляют, но также и дают возможность управления работой принтера. Мы же пока будем довольствоваться только слежением за посылаемыми на печать задачами. Для этого в арсенале Windows предусмотрено 2 метода. Первый из них - Использование метода отслеживания сообщения WM_SPOOLERSTATUS, которое система посылает всякий раз при добавлении нового задания в очередь или же удалении оного из нее. Второй способ - использование функций FindFirstPrinterChangeNotification, FindNextPrinterChangeNotification и FindClosePrinterChangeNotification. В этой заметке мы рассмотрим первый из них. Как и большинство сообщений Windows WM_SPOOLERSTATUS возвращает в структуре TMessage некоторую полезную информацию, которую вы можете ипользовать в своих нуждах. Но к сожаление никакой действительно важной и необходимой нам информации (кроме количества оставшихся в очереди заданий) эта структура не несет. Но к счастью в Windows есть дополнительные методы для определения всей жизненно важной для нас информации. Так среди прочих в модуле WinSpool есть функция EnumJobs, которая возвращает количество и характеристики
заданий печати, в которых содержится вся необходимая нам информация; от названия документа, машины и имени ползователя, который откправил этот документ на песать, до времени когда это было сделать и количества страниц, которые были посланы на печать. Эта функция выглядит следующим образом: где hPrinter - идентификатор принтера к которому мы делаем запрос. FirstJob - номер первого запрашиваемого задания NoJobs - количество запрашиваемых заданий Level - тип структуры которая передается в pJob PJob - указатель на массив переменных типа JOB_INFO_1 при Level=1 и JOB_INFO_2 при Level=2. см. Таблицы 1,2 CbBuf - размер буфера данных. PcbNeeded - переменная в которую заносится количество записанных в буфер данных при удачном завершении функции или же необходимый размер буфера в байтах при неудачном завершении функции. PcReturned - Количество записей занесенных в буфер в которых содержится актуальная информация. Для нормальной работы этой функции нам необходимо прежде всего раздобыть идентификатор принтера, который мы должны поместить в параметр hPrinter. Для этого сущеструет функция OpenPrinter, которая открывает соответствующий принтер и выдает необходимый идентификатор: где ppPrinterName - имя принтера, который следует открыть. phPrinter - переменная в которую будет записан идентификатор открытого принтера pDefault - структура содержащая данные необходимай для инициализации принтера. Если в системе присудствует только отдин принтер (подключенный к компьютеру админа), то параметр ppPrinterName может быть строго зафиксирован в самом коде приложения, если же принтеров в сети несколько (подключенный к серверу, к компьютеру администратоа, к компьютеру кассы и т.п.), то лучшим вариантом будет дать возможность ползователю самостоятельно выбирать какой из принтеров следует инспектировать. Для этого можно воспользоваться функцией перечисления доступных принтеров: Здесь Flags - флаги которые дазают особенности перечисления принтеров (см. Таблицу.3) Name - название принт-объекта. Значение этого параметра используется в паре с Level (см.Таблицу 4) Level - индекс уровня используется вместе с Name (см. Таблицу 4) PPrinterEnum - указатель на массив элементов одного из типов TPrinterInfo1, TPrinterInfo2, TPrinterInfo4, TPrinterInfo5. (см. Таблицу 4) CbBuf - размер буфера pPrinterEnum. PcbNeeded - переменная в которой содержится количество байт скопированных при удачноз завершении операции или же размер недостающей памяти если значение cbBuf слишкм мало. PcReturned - количество актуальных записей занесенных в буфер. Практическая реализацияДля пракотческой реализации мы как всегде воспользуемя Delphi и сперва создадим свежее приложение щелкнув на пункте New->Application. Далее для демонстрации работы мы перенесем на форму 2 компонента: TreeView и ListBox.(рис.1). Дале занесем в OnCreate код для перечисления доступных принтеров: Здесь мы сначала создаем родительксий узел в TreeView куда будем записывать все найденные принтеры. Далее запускаем поиск локальных принтеров посредством передачи в EnumPrinters флага PRINTER_ENUM_LOCAL. После этого при успешном завершении функции мы переносим названия всех принтеров в TreeView, или же выводим сообщение об ошибке. Теперь у нас есть список всех доступных принтеров и мы со спокойной душей можем предложить пользователю выбрать и открыть один из них. Для этого в реакцию на событие OnDblClick компонента TreeView1 мы запишем следующий код: Теперь после двойного щелчка на названии принтера мы открываем его и записываем полученный идентификатор в переменную PH, которая объявлена в секции private нашей формы. А для пущей правильности кода мы в OnDestroy нашей формы напишем: Далее нам предстоит реализовать слежение за сообщением WM_SPOOLERSTATUS и для этого я рекомендую выбрать способ предоставляемый Delphi посредством служебного слова message: Здесь метод WMPrinterStatus будет вызываться только при поступлении сообщения WM_SPOOLERSTATUS. В коде реализации этого метода мы с вами напишем вот что: Все. Наш проект готов, и надо его надо только скомпилить. После запуска приложения на экране появляется уже знакомое нам окно, в компоненте TreeView которого присутствует список доступных локальных принтеров (рис.2). Открываем принтер (двойной щелчек на названии) и запускаем любой текстовый редактор. Открываем документ (для пробы можно воспользоваться и графическим радактором). А теперь: <Файл->Печать> и мы видим:.(рис.3). ![]() ![]() ПослесловиеИтак теперь мы приблизительно знаем, как отслеживать состояние очереди на печать. И не просто отслеживать, а автоматически обрабатывать эту информацию в своих корыстных целях. Но так или иначе, этот метод не эдинственный в своём роде. Так, кроме ракции на событие WM_SPOOLERSTATUS можно реализовать обработку очереди посредством функций FindFirstPrinterChangeNotification, FindNextPrinterChangeNotification, FindClosePrinterChangeNotification, которые позволяют не отслеживать не только добавление и удаление заданий в(из) очереди, но также и состояние очереди в процесе печати, и много других возможностей. Кроме того, эти методы дают возможность настроить реакцию программы под более конкретные задачи (Printer, PrinterDriver, Form, Job:), что конечно позитивно сказывается на работоспособности системы вцелом, особенно при больших нагрузках на нее. К негативным же сторонам можно отнести то, что при обработке FindFirstPrinterChangeNotification, FindNextPrinterChangeNotification, FindClosePrinterChangeNotification необходимо реализовывать отдельный поток для отслеживания этих действий, что само по себе непростая задача для человека, который еще ни разу не работал с потоками вплотную. ©Gigabyte 2005
|
В избранное | ||