![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Косяк с принтером, а точнее с определением его статуса [D7, WinXP]
ChainikDenis © (2006-05-16 22:02:00)Коллеги, беда!
Коротко:
Чековый принтер на COM2. Типа печатает чеки с номерками клиентов. Задача - определить когда кончается бумага и соответсвенно не печатать.
Засада в том что Винда не обращает внимание на то что в принтере нет бумаги или то что он вообще не подключен. Просто отправляет в COM2 массив байт и считает что на том конце все нормально. Отправку массива определаяю визуально - у меня светодиодики на RxD и TxD сидят.
Принтер достаточно умный и по RS232 может сообщить о своем состоянии все что нужно, НО драйвер принтера занял порт в монопольном режиме и этот порт теперь недоступен!
Хрен бы с ним, сделал так:
var PrnHandle: THandle;
var PrnInfo: TPRINTERINFO2;
var pcbNeeded: DWord;
var PrinterName: string;
PrinterName := 'TPTCM60 Dispenser';
if OpenPrinter(PChar(PrinterName), PrnHandle, nil) then
begin
GetPrinter(PrnHandle, 2 , @PrnInfo, 0, @pcbNeeded); // Получаем размер
SetLastError(0); // Собственно толку от нее ни какого
if GetPrinter(PrnHandle, 2 , @PrnInfo, pcbNeeded, @pcbNeeded) then
Form1.StatusBar1.Panels[3].Text := IntToStr(PrnInfo.Status) // Выводим статус
else
Form1.StatusBar1.Panels[3].Text := 'Статус не известен...';
ClosePrinter(PrnHandle);
end
else Form1.StatusBar1.Panels[3].Text := 'Принтер не доступен';
Но данная конструкция всегда выводит 0 - вне зависимости от состояния принтера, даже если он ваще отключен...
Кстати, если этот кусок втыкаю в обработчик кнопки, то все нормально, а если в обработчик таймера который срабатывает каждые 250 мс, то на этой строке: if GetPrinter(PrnHandle, 2 , @PrnInfo, pcbNeeded, @pcbNeeded) then... в первом же вызове Acces Vialation вылезает... С чего бы это...
Волнует другой вопрос. Для этого принтера есть StatusMonitor - программулина, которая собственно этот статус и показывает. Причем при ее запуске видно что она где-то раз в секунду посылает запрос в COM2 и соответсвенно оттуда ответ получает.. Я б и сам послал_принял, да доступа к порту нет...
Млин..
Что делать-то? Как определить состояние принтера, или как получить доступ к порту?
P.S. Перевел принтер и соответсвенно драйвер принтера на hardware control - стало лучше, но не то. Просто если нет бумаги, то задание висит в очереди печати пока принтер не включишь (или не вставишь бумагу)...
tesseract (2006-05-17 12:10:00) [1]
> Порочный путь.
да как раз наоборот.
погеммороишься с рендерингом пару дней, зато потом лафа.
ChainikDenis (2006-05-17 12:03:00) [2]Порочный путь.
В графическом режиме ручками печатать достаточтно геморойно. Понятно когда собственный контроллер заставляешь печатать, а тут винда с гигабайтами памяти, мышками и клавиатурами.
Отказ от попытки решения теоретически решаемой задачи - путь слабых.
Нашел пока только один способ - GetPrinter выдает количество задач стоящих в очереди на печать. Зная примерное время печати чека можно сделать вывод о работе/неработе принтера.
Отправляем на печать и засекаем время. Если по окончании опеределенного периода задача еще висит в очереди - значит принтер не работает.
Теперь бы понять почему вышепреведенный код нормально работает только в обработчкие IdUDPServer1UDPRead, а в паралельном потоке и в таймере не работает...
Германн (2006-05-17 03:59:00) [3]1. Устройство подключено к Com-порту
2. Спецификация команд известна.
Удалить это устройство, то бишь принтер, из системы. Порт освободится. Работать с принтером как с COM-портом.
ChainikDenis (2006-05-17 00:48:00) [4]Все, млин совсем хана...
Вот это:
procedure TForm1.Button1Click(Sender: TObject);
var PrnHandle: THandle;
var PrnInfo: TPRINTERINFO2;
var pcbNeeded: longword;
var PrinterName : string;
begin
PrinterName := 'TPTCM60 Dispenser';
if OpenPrinter(PChar(PrinterName), PrnHandle, nil) then
begin
GetPrinter(PrnHandle, 2 , nil, 0, @pcbNeeded);
if GetPrinter(PrnHandle, 2 , @PrnInfo, pcbNeeded, @pcbNeeded) then
Form1.Label1.Caption := IntToStr(PrnInfo.Status)
else
Form1.Label1.Caption := Статус не известен...';
// ClosePrinter(PrnHandle);
end
else Form1.Label1.Caption := 'Принтер не доступен!';
end;
нихрена не работает,
А если этот кусок вставить в обработчик от IdUDPServer1UDPRead то все работает. Похоже при втором вызове GetPrinter куда-то теряется содержимое PrnHandle ...
Хана мне. Спать пойду..
Поможите кто чем можете. ...
ChainikDenis (2006-05-17 00:41:00) [5]PortMon от SysInternals? Так этож из другой песни...Я про RS232 расказываю. А для того что б понять что порт занять достаточно попытаться его открыть в Терминал Эмуляторе. Но я для надежности еще и класическим CreateFile проверял - занят нафик.
GanibalLector (2006-05-17 00:27:00) [6]2 ChainikDenis
>Для этого принтера есть StatusMonitor - программулина, которая собственно этот статус и показывает. Причем при ее запуске видно что она где-то раз в секунду посылает запрос в COM2 и соответсвенно оттуда ответ получает
Как так? Программулина имеет доступ к порту, а ты нет. Чудеса какие-то.
В конце концов,запусти PortMon и посмотри что творится.
З.Ы. Как вариант,не использовать тот драйвер,а самому взять брозды правления, написав СОМ-сервер.
ChainikDenis (2006-05-16 22:31:00) [7]
> бумаги, то задание висит в очереди печати пока принтер не
> включишь (или не вставишь бумагу)...
Фиг там - потихоничку "печатается". Примернт по 3 кб в минуту от задания в очереди печати куда-то печатаются. Так что минит через 10 вроде как и напечатал чек... На выключенный принтер...