 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Bogdan Guest
|
Posted: Fri Feb 10, 2006 7:03 pm Post subject: Printer notification |
|
|
I'm trying to monitor the printer and log each succesfully printed job, but
I
cannot make a difference between a job that is deleted before printing
because
the user chose to abort the print operation, and the job that is deleted
from
the spooler because it finished printing.
Is there a way to differentiate between the two situations?
I'm using the following piece of code :
void __fastcall TPrinterMonitor::Execute()
{
while(!Terminated)
{
WaitForSingleObject(Notifier,INFINITE);
Changes = 0x00000000;
if(FindNextPrinterChangeNotification(Notifier,&Changes,NULL,NULL))
{
if(Changes & PRINTER_CHANGE_ADD_JOB)
{
Line = "Job added";
Synchronize(Update);
};
if(Changes & PRINTER_CHANGE_DELETE_JOB)
{
Line = "Job deleted";
Synchronize(Update);
};
if(Changes & PRINTER_CHANGE_SET_JOB)
{
Line = "Job set";
Synchronize(Update);
};
if(Changes & PRINTER_CHANGE_WRITE_JOB)
{
Line = "Job write";
Synchronize(Update);
};
};
};
FindClosePrinterChangeNotification(Notifier);
};
Bogdan |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Fri Feb 10, 2006 9:03 pm Post subject: Re: Printer notification |
|
|
"Bogdan" <boprea (AT) xnet (DOT) ro> wrote in message
news:43ecd5bb (AT) newsgroups (DOT) borland.com...
| Quote: | I cannot make a difference between a job that is deleted before
printing because the user chose to abort the print operation, and
the job that is deleted from the spooler because it finished printing.
|
You have to keep track of the job information. Currently, you are
completely ignoring the pPrinterNotifyOptions and ppPrinterNotifyInfo
parameters of FindNextPrinterChangeNotification(). The ppPrinterNotifyInfo
parameter provides detailed information about each notification. For
example, you can use it to detect JOB_NOTIFY_FIELD_STATUS,
JOB_NOTIFY_FIELD_PAGES_PRINTED, and/or JOB_NOTIFY_FIELD_BYTES_PRINTED
changes. Also, you should be keeping track of the active jobs as well.
When a job is added, add its information to a list somewhere. When the job
is deleted, remove the job from your list. When the job is written to the
printer, keep track of its printing status. When the job is deleted, you
can check the last known status to know what the job was doing.
| Quote: | while(!Terminated)
{
WaitForSingleObject(Notifier,INFINITE);
|
By doing that, you won't be able to terminate the thread while it is waiting
for a notification. You should use CreateEvent() to create a second event
and then use WaitForMultipleObjects() instead. This way, when the
application wants to shut down the thread, it can signal the event.
| Quote: | Changes = 0x00000000;
if(FindNextPrinterChangeNotification(Notifier,&Changes,NULL,NULL))
{
|
Where are you calling FindFirstPrinterChangeNotification()? Which
notifications are you asking it for?
Gambit |
|
| Back to top |
|
 |
Bogdan Guest
|
Posted: Fri Feb 10, 2006 9:03 pm Post subject: Re: Printer notification |
|
|
| Quote: | Where are you calling FindFirstPrinterChangeNotification()? Which
notifications are you asking it for?
|
Missed some lines when copy-pasted .
Flags = PRINTER_CHANGE_ALL;
Notifier = FindFirstPrinterChangeNotification(printer,Flags,0,NULL);
But the thread still terminates cleanly, even with :
while(!Terminated)
{
WaitForSingleObject(Notifier,INFINITE);
....
}
I've tried using the pPrinterNotifyOptions and ppPrinterNotifyInfo options
in the following code
to look for the number of pages printerd so far, but i'm not sure I'm using
them corectly...
shouldn't a notification be sent when one of the monitored parameters
changes?
void __fastcall TPrinterMonitor::Execute()
{
PRINTER_NOTIFY_OPTIONS pno;
PRINTER_NOTIFY_OPTIONS_TYPE pnot;
PRINTER_NOTIFY_INFO *pni = NULL;
WORD Field = JOB_NOTIFY_FIELD_PAGES_PRINTED;
pno.Version = 2;
pno.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
pno.Count = 1;
pno.pTypes = &pnot;
pnot.Type = JOB_NOTIFY_TYPE;
pnot.Reserved0 = 0;
pnot.Reserved1 = 0;
pnot.Reserved2 = 0;
pnot.Count = 1;
pnot.pFields = &Field;
PPRINTER_NOTIFY_INFO ppni;
Notifier = FindFirstPrinterChangeNotification(printer,MonitorFlags,0,&pno);
while(!Terminated)
{
WaitForSingleObject(Notifier,INFINITE);
Changes = 0x00000000;
if(FindNextPrinterChangeNotification(Notifier,&Changes,&pno,(void**)&pni))
{
if(Changes & PRINTER_CHANGE_ADD_JOB)
{
Line = "Job added";
Synchronize(Update);
//Sleep(100);
//Synchronize(ListJobs);
}
else if(Changes & PRINTER_CHANGE_DELETE_JOB)
{
Line = "Job deleted";
Synchronize(Update);
}
else if(Changes & PRINTER_CHANGE_SET_JOB)
{
Line = "Job set";
Synchronize(Update);
}
else if(Changes & PRINTER_CHANGE_WRITE_JOB)
{
Line = "Job write";
Synchronize(Update);
}
else
{
Line = "some other change";
Synchronize(Update);
};
};
};
FindClosePrinterChangeNotification(Notifier);
}
Bogdan |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sat Feb 11, 2006 12:03 am Post subject: Re: Printer notification |
|
|
"Bogdan" <boprea (AT) xnet (DOT) ro> wrote in message
news:43ecfc34$1 (AT) newsgroups (DOT) borland.com...
| Quote: | But the thread still terminates cleanly, even with :
while(!Terminated)
{
WaitForSingleObject(Notifier,INFINITE);
....
}
|
If there are no pending printer notifications, then your thread is blocked
indefinately. The application will not be able to shut the thread down
until another notification arrives, because the thread will not be able to
check its Terminated property. If you don't want to use a second event
object, then you should not be using an INFINITE timeout on
WaitForSingleObject(). Give it a smaller timeout value instead so that the
thread can properly check its Terminated property periodically.
| Quote: | I've tried using the pPrinterNotifyOptions and ppPrinterNotifyInfo
options in the following code to look for the number of pages printerd
so far, but i'm not sure I'm using them corectly...
|
Try the following code (untested):
#include <map>
struct JobInfo
{
DWORD Status;
DWORD NumPages;
DWORD PagesPrinted;
DWORD NumBytes;
DWORD BytesPrinted;
JobInfo()
{
Status = 0;
NumPages = 0;
PagesPrinted = 0;
NumBytes = 0;
BytesPrinted = 0;
}
};
class TPrinterMonitor : public TThread
{
private:
typedef std::map<DWORD, JobInfo> JobMap;
typedef JobMap::iterator JobMapIter;
HANDLE Printer;
HANDLE Notifier
JobMap Jobs;
void __fastcall ProcessPrinterNotifyInfo(PPRINTER_NOTIFY_INFO pni);
void __fastcall Update();
protected
virtual void __fastcall Execute();
virtual void __fastcall DoTerminate();
public:
__fastcall TPrinterMonitor(HANDLE hPrinter);
};
__fastcall TPrinterMonitor::TPrinterMonitor(HANDLE hPrinter)
: TThread(true)
{
Printer = hPrinter;
Notifier = INVALID_HANDLE_VALUE;
Resume();
}
void __fastcall TPrinterMonitor::Execute()
{
DWORD Changes;
PRINTER_NOTIFY_OPTIONS pno = {0};
pno.Version = 2;
pno.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
PPRINTER_NOTIFY_INFO pni;
Notifier = FindFirstPrinterChangeNotification(Printer,
PRINTER_CHANGE_JOB, 0, NULL);
if( Notifier == INVALID_HANDLE_VALUE )
return;
while( !Terminated )
{
if( WaitForSingleObject(Notifier, 1000) == WAIT_OBJECT_0 )
{
Changes = 0;
if( FindNextPrinterChangeNotification(Notifier, &Changes,
&pno, (void**)&pni) )
{
ProcessPrinterNotifyInfo(pni);
FreePrinterNotifyInfo(pni);
}
}
}
void __fastcall TPrinterMonitor::DoTerminate()
{
if( Notifier != INVALID_HANDLE_VALUE )
FindClosePrinterChangeNotification(Notifier);
}
void __fastcall
TPrinterMonitor::ProcessPrinterNotifyInfo(PPRINTER_NOTIFY_INFO pni)
{
for(DWORD x = 0; x < pni->Count; ++x)
{
PRINTER_NOTIFY_INFO_DATA &Data = pni->nData[x];
if( Data.Type == JOB_NOTIFY_TYPE )
{
switch( Data.Field )
{
case JOB_NOTIFY_FIELD_STATUS:
if( (Data.adwData[0] == JOB_STATUS_DELETED )
Jobs.erase(Data.Id);
else
Jobs[Data.Id].Status = Data.adwData[0];
break;
case JOB_NOTIFY_FIELD_PAGES_PRINTED:
Jobs[Data.Id].PagesPrinted = Data.adwData[0];
break;
case JOB_NOTIFY_FIELD_TOTAL_BYTES:
Jobs[Data.Id].Info.NumBytes = Data.adwData[0];
break;
case JOB_NOTIFY_FIELD_BYTES_PRINTED:
Jobs[Data.Id].Info.BytesPrinted = Data.adwData[0];
break;
}
}
}
Synchronize(Update);
}
void __fastcall TPrinterMonitor::Update()
{
// update the UI with the info of the current Jobs as needed ...
}
Gambit |
|
| Back to top |
|
 |
Bogdan Guest
|
Posted: Sat Feb 11, 2006 7:03 pm Post subject: Re: Printer notification |
|
|
Thanks for the sample code.It worked, but with some little modifications.
You have to specify in an array which printer job fields you want to
monitor for changes :
WORD Types[4] = {JOB_NOTIFY_FIELD_PAGES_PRINTED,
JOB_NOTIFY_FIELD_STATUS,
JOB_NOTIFY_FIELD_TOTAL_BYTES,
JOB_NOTIFY_FIELD_BYTES_PRINTED};
PRINTER_NOTIFY_OPTIONS_TYPE pnot;
pnot.Type = JOB_NOTIFY_TYPE;
pnot.Count = 4;
pnot.pFields = &Types[0];
PRINTER_NOTIFY_OPTIONS pno;
pno.Version = 2;
pno.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
pno.Count = 1;
pno.pTypes = &pnot;
PPRINTER_NOTIFY_INFO pni;
Notifier =
FindFirstPrinterChangeNotification(printer,PRINTER_CHANGE_JOB,0,&pno);
.. . .
if(FindNextPrinterChangeNotification(Notifier,&Changes,&pno,(void**)&pni))
.. . .
However, now I have another big problem.Windows sends the job to the
printer, and reports only
JOB_STATUS_SPOOLING and JOB_STATUS_PRINTING.All of the other errors
(like paper out or printer disconnected) are handled by the printer driver,
without any notification
to the spooler.
Bogdan |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Mon Feb 13, 2006 8:03 am Post subject: Re: Printer notification |
|
|
"Bogdan" <boprea (AT) xnet (DOT) ro> wrote in message
news:43ee2762 (AT) newsgroups (DOT) borland.com...
| Quote: | You have to specify in an array which printer job fields
you want to monitor for changes :
|
According to the documentation, if you specify NULL for the
pPrinterNotifyOptions parameter, then the fdwFlags parameter specifies what
to monitor. In the code I gave you, I do pass NULL in the
pPrinterNotifyOptions parameter, and the fdwFlags parameter is set to
monitor all job-related changes.
Gambit |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|