• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 437
  • Last Modified:

Hooking System Print Messages

I would like to handle all printer error messages myself, rather than letting the Windows Print Manager handle them.  It would be ideal if the method would work with both NT and 95, but it would be acceptable if there was a separate method for both.

In other words, when the system would normally display a message like "Printer out of paper" or "Printer not found", it would instead call my function.  My function would add some extra functionality, and then maybe call the default message handler.

Is there a way to do this without writing a print driver?  Example code wold be appreciated.
0
jstolan
Asked:
jstolan
  • 2
1 Solution
 
trestanCommented:
Use Win32 function "OpenPrinter" to retrieve a handle identifying the specified printer or print server.
Use "EnumPrinters" function to enumerate available printers, print servers, domains, or print providers.
The "GetPrinter" function retrieves information about a specified printer. The "PRINTER_INFO_2" structure specifies detailed printer information. But the status information is held differentely between NT and 95. In Windows 95, it can be the following values:

PRINTER_STATUS_BUSY
PRINTER_STATUS_DOOR_OPEN
PRINTER_STATUS_ERROR
PRINTER_STATUS_INITIALIZING
PRINTER_STATUS_IO_ACTIVE
PRINTER_STATUS_MANUAL_FEED
PRINTER_STATUS_NO_TONER
PRINTER_STATUS_NOT_AVAILABLE
PRINTER_STATUS_OFFLINE
PRINTER_STATUS_OUT_OF_MEMORY
PRINTER_STATUS_OUTPUT_BIN_FULL
PRINTER_STATUS_PAGE_PUNT
PRINTER_STATUS_PAPER_JAM
PRINTER_STATUS_PAPER_OUT
PRINTER_STATUS_PAPER_PROBLEM
PRINTER_STATUS_PAUSED
PRINTER_STATUS_PENDING_DELETION
PRINTER_STATUS_PRINTING
PRINTER_STATUS_PROCESSING
PRINTER_STATUS_TONER_LOW
PRINTER_STATUS_UNAVAILABLE
PRINTER_STATUS_USER_INTERVENTION
PRINTER_STATUS_WAITING
PRINTER_STATUS_WARMING_UP

You can make your function according to the value.
In Windows NT, the status value is specified in PRINTER_INFO_6 structure. But in VS5, this structure is only used by "SetPrinter". I did not try it, but I think the status can be obtained when set the command parameter to be zero.
I think the implimentation with these API functions would not be difficult. It would be my pleasure to debug your codes if you met any problem in compiling the program.
Good luck.



0
 
trestanCommented:
Hi, I complied a small console program to get the printer status. You can check online help for the difference between 95 and NT. You need permission to set printer status otherwise the setprinter function will fail. You can put your functions under cases matching different status.

#include <afx.h>
#include <winspool.h>
#include <iostream.h>
void main ()
{
      LPTSTR pPrinterName = "\\\\CBS-NT\\FujitsuGrad";
      HANDLE hPrinter;
      PRINTER_INFO_2 * pPrinterInfo;

      //Get the handle of the specified printer.
      if (!OpenPrinter(pPrinterName, &hPrinter, NULL))
            cout<<"error open printer\n";
      
      //Get the buffer size to store information.
      DWORD nSize, cbNeeded;

      if (!GetPrinter(hPrinter, 2, NULL, 0, &nSize))
      {
            if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            {
                  ClosePrinter(hPrinter);
                  cout<<"getptrinter failed.\n";
                  exit(1);
            }
      }
      
      //Allocate memory.
      pPrinterInfo = (PRINTER_INFO_2 *) GlobalAlloc(GMEM_MOVEABLE |GMEM_ZEROINIT, nSize);
      cout<<"buffer size needed: "<<nSize<<"\n";
      if (!pPrinterInfo)
      {
            cout<<"error allocate bytes from the heap.\n";
            exit(1);
      }

      //Get printer status.
      if (!GetPrinter(hPrinter, 2, (LPBYTE) pPrinterInfo, nSize, &cbNeeded))
      {
            cout<<"error get printer: not enough memory.";
            exit(1);
      }

      cout<<pPrinterName<<":"<<"\n"<<"Actual buffer size: "<<cbNeeded<<"\n";
      switch (pPrinterInfo->Status)
      {
      case PRINTER_STATUS_PAUSED:
            {
                  cout<<"PRINTER_STATUS_PAUSED "<<pPrinterInfo->Status<<"\n";
                  break;
            }
            
      case PRINTER_STATUS_PENDING_DELETION:
            {
                  cout<<"PRINTER_STATUS_PENDING_DELETION "<<pPrinterInfo->Status<<"\n";
                  break;
            }
      default:
            cout <<"No listed status\n";
      }

      //Set printer to Pause status.
      if(!SetPrinter(hPrinter, 0, NULL, PRINTER_CONTROL_PAUSE))
      {
            cout<<"setprinter failed.\n";
            exit(1);            
      }      
}
0
 
jstolanAuthor Commented:
Trestan

Thanks for your excellent help.  I'm not going to get a chance to try this as I'll be on vacation this week.  I'm sure you've saved me a ton of work though.

jstolan
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now