Help: check whether a printer is offline or online

Help: check whether a printer is offline or online

Postby anserkk » Wed Nov 05, 2008 11:36 am

Dear Friends,

Is there any way by which I can check whether a printer is offline or online

Regards

Anser
User avatar
anserkk
 
Posts: 1331
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Postby anserkk » Wed Nov 05, 2008 12:21 pm

Freinds,

I got some info from the thread http://www.fivetechsoft.com/forums/view ... hp?t=11418

But unsuccessfull to get the OffLine/OnLine status of a network dot matrix printer

Regards

Anser
User avatar
anserkk
 
Posts: 1331
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Postby anserkk » Thu Nov 06, 2008 5:42 am

Any hint ? or guidline ? to solve the above said problem

I tried Empty(oPrn:hDc) but not gtting the desired result.

Regards

Anser
User avatar
anserkk
 
Posts: 1331
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Postby anserkk » Thu Nov 06, 2008 6:44 am

I got this from the Microsoft Site http://support.microsoft.com/kb/160129

Can anybody here help me to convert this to FWH equivalent or do somebody already have this in FWH


Code: Select all  Expand view
BOOL GetJobs(HANDLE hPrinter,        /* Handle to the printer. */

                JOB_INFO_2 **ppJobInfo, /* Pointer to be filled.  */
                int *pcJobs,            /* Count of jobs filled.  */
                DWORD *pStatus)         /* Print Queue status.    */

   {

   DWORD               cByteNeeded,
                        nReturned,
                        cByteUsed;
    JOB_INFO_2          *pJobStorage = NULL;
    PRINTER_INFO_2       *pPrinterInfo = NULL;

   /* Get the buffer size needed. */
       if (!GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded))
       {
           if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
               return FALSE;
       }

       pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
       if (!(pPrinterInfo))
           /* Failure to allocate memory. */
           return FALSE;

       /* Get the printer information. */
       if (!GetPrinter(hPrinter,
               2,
               (LPSTR)pPrinterInfo,
               cByteNeeded,
               &cByteUsed))
       {
           /* Failure to access the printer. */
           free(pPrinterInfo);
           pPrinterInfo = NULL;
           return FALSE;
       }

       /* Get job storage space. */
       if (!EnumJobs(hPrinter,
               0,
               pPrinterInfo->cJobs,
               2,
               NULL,
               0,
               (LPDWORD)&cByteNeeded,
               (LPDWORD)&nReturned))
       {
           if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
           {
               free(pPrinterInfo);
               pPrinterInfo = NULL;
               return FALSE;
           }
       }

       pJobStorage = (JOB_INFO_2 *)malloc(cByteNeeded);
       if (!pJobStorage)
       {
           /* Failure to allocate Job storage space. */
           free(pPrinterInfo);
           pPrinterInfo = NULL;
           return FALSE;
       }

       ZeroMemory(pJobStorage, cByteNeeded);

       /* Get the list of jobs. */
       if (!EnumJobs(hPrinter,
               0,
               pPrinterInfo->cJobs,
               2,
               (LPBYTE)pJobStorage,
               cByteNeeded,
               (LPDWORD)&cByteUsed,
               (LPDWORD)&nReturned))
       {
           free(pPrinterInfo);
           free(pJobStorage);
           pJobStorage = NULL;
           pPrinterInfo = NULL;
           return FALSE;
       }

       /*
        *  Return the information.
        */
       *pcJobs = nReturned;
       *pStatus = pPrinterInfo->Status;
       *ppJobInfo = pJobStorage;
       free(pPrinterInfo);

       return TRUE;

   }

   BOOL IsPrinterError(HANDLE hPrinter)
   {

       JOB_INFO_2  *pJobs;
       int         cJobs,
                   i;
       DWORD       dwPrinterStatus;

       /*
        *  Get the state information for the Printer Queue and
        *  the jobs in the Printer Queue.
        */
       if (!GetJobs(hPrinter, &pJobs, &cJobs, &dwPrinterStatus))
         return FALSE;

       /*
        *  If the Printer reports an error, believe it.
        */
       if (dwPrinterStatus &
           (PRINTER_STATUS_ERROR |
           PRINTER_STATUS_PAPER_JAM |
           PRINTER_STATUS_PAPER_OUT |
           PRINTER_STATUS_PAPER_PROBLEM |
           PRINTER_STATUS_OUTPUT_BIN_FULL |
           PRINTER_STATUS_NOT_AVAILABLE |
           PRINTER_STATUS_NO_TONER |
           PRINTER_STATUS_OUT_OF_MEMORY |
           PRINTER_STATUS_OFFLINE |
           PRINTER_STATUS_DOOR_OPEN))
       {
           free( pJobs );
           return TRUE;
       }

       /*
        *  Find the Job in the Queue that is printing.
        */
       for (i=0; i < cJobs; i++)
       {
           if (pJobs[i].Status & JOB_STATUS_PRINTING)
           {
               /*
                *  If the job is in an error state,
                *  report an error for the printer.
                *  Code could be inserted here to
                *  attempt an interpretation of the
                *  pStatus member as well.
                */
               if (pJobs[i].Status &
                   (JOB_STATUS_ERROR |
                   JOB_STATUS_OFFLINE |
                   JOB_STATUS_PAPEROUT |
                   JOB_STATUS_BLOCKED_DEVQ))
               {
                   free( pJobs );
                   return TRUE;
               }
           }
       }

       /*
        *  No error condition.
        */
       free( pJobs );
       return FALSE;

   }
      
User avatar
anserkk
 
Posts: 1331
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Postby James Bott » Thu Nov 06, 2008 4:26 pm

Anser,

Maybe this will help.

James

Code: Select all  Expand view
function IsPrint( QuePrinter )
   LOCAL nStatus
   DEFAULT QuePrinter := "LPT1:"
   nStatus := PrnStatus( QuePrinter )
   if     nStatus <        1 ; return "Impressora OK"
   elseif nStatus =        1 ; return "Impressora Pausada"
   elseif nStatus =        2 ; return "Impressora com Erro"
   elseif nStatus =        4 ; return "Impressora Deletando"
   elseif nStatus =        8 ; return "Impressora em Modo Bandeja"
   elseif nStatus =       16 ; return "Impressora Sem Papel"
   elseif nStatus =       32 ; return "Impressora em Modo Manual"
   elseif nStatus =       64 ; return "Impressora com Problema no Papel"
   elseif nStatus =      128 ; return "Impressora OffLine"
   elseif nStatus =      256 ; return "Impressora com IO Ativo"
   elseif nStatus =      512 ; return "Impressora Ocupada"
   elseif nStatus =     1024 ; return "Impressora Imprimindo"
   elseif nStatus =     2048 ; return "Impressora Memoria Lotada"
   elseif nStatus =     4096 ; return "Impressora Nao Instalada"
   elseif nStatus =     8192 ; return "Impressora Aguardando"
   elseif nStatus =    16384 ; return "Impressora Processando"
   elseif nStatus =    32768 ; return "Impressora Inicializando"
   elseif nStatus =    65536 ; return "Impressora em Atencao"
   elseif nStatus =   131072 ; return "Impressora Toner Baixo"
   elseif nStatus =   262144 ; return "Impressora Sem Toner"
   elseif nStatus =   524288 ; return "Impressora PAGE_PUNT"
   elseif nStatus =  1048576 ; return "Impressora Intervencao do Usuario"
   elseif nStatus =  2097152 ; return "Impressora Sem Memoria"
   elseif nStatus =  4194304 ; return "Impressora Tampa Aberta"
   elseif nStatus =  8388608 ; return "Impressora Servidor Desconhecido"
   elseif nStatus = 16777217 ; return "Impressora POWER_SAVE"
   endif
return nil
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby James Bott » Thu Nov 06, 2008 4:28 pm

Here are the original DEFINEs.

James

#define PRINTER_STATUS_OK 0
#define PRINTER_STATUS_PAUSED 1
#define PRINTER_STATUS_ERROR 2
#define PRINTER_STATUS_PENDING_DELETION 4
#define PRINTER_STATUS_PAPER_JAM 8
#define PRINTER_STATUS_PAPER_OUT 16
#define PRINTER_STATUS_MANUAL_FEED 32
#define PRINTER_STATUS_PAPER_PROBLEM 64
#define PRINTER_STATUS_OFFLINE 128
#define PRINTER_STATUS_IO_ACTIVE 256
#define PRINTER_STATUS_BUSY 512
#define PRINTER_STATUS_PRINTING 1024
#define PRINTER_STATUS_OUTPUT_BIN_FULL 2048
#define PRINTER_STATUS_NOT_AVAILABLE 4096
#define PRINTER_STATUS_WAITING 8192
#define PRINTER_STATUS_PROCESSING 16384
#define PRINTER_STATUS_INITIALIZING 32768
#define PRINTER_STATUS_WARMING_UP 65536
#define PRINTER_STATUS_TONER_LOW 131072
#define PRINTER_STATUS_NO_TONER 262144
#define PRINTER_STATUS_PAGE_PUNT 524288
#define PRINTER_STATUS_USER_INTERVENTION 1048576
#define PRINTER_STATUS_OUT_OF_MEMORY 2097152
#define PRINTER_STATUS_DOOR_OPEN 4194304
#define PRINTER_STATUS_SERVER_UNKNOWN 8388608
#define PRINTER_STATUS_POWER_SAVE 16777216
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby anserkk » Fri Nov 07, 2008 5:27 am

Dear Mr.James,

Thankyou for the solution, but did not serve the purpose

As per the function I am getting a return Value 0, eventhough the printer is switched off
Code: Select all  Expand view
   nStatus := PrnStatus( QuePrinter )
   if     nStatus <        1 ; return "Printer OK"  // ie Impressora  OK


I expect nStatus value to be 128 when the printer is switched off/offline

Code: Select all  Expand view
elseif nStatus =      128 ; return "Printer OFFLINE"


I even tried to make use of PrintRawFile() to print an empty Txt file and return a value so that I could identify whether the printer is online or not,
but failed, I am getting a return value 1 from PrintRawFile()

Code: Select all  Expand view
*------------------------------------------*
Function TestPrn()
*------------------------------------------*
Local nPrn,cFileName:="D:\WinAcs\MyText.Txt"

MsgInfo(isprint(PrnGetName()) )

nPrn := PrintFileRaw(PrnGetName(),cFileName, "Test for PrintFileRaw()")
MsgInfo("Entered TestPrn, value of nPrn is "+str(nPrn))
IF nPrn  < 0
   DO CASE
   CASE nPrn = -1
      Alert(cMess+"Incorrect parameters passed to function")
   CASE nPrn = -2
      Alert(cMess+"WINAPI OpenPrinter() call failed")
   CASE nPrn = -3
      Alert(cMess+"WINAPI StartDocPrinter() call failed")
   CASE nPrn = -4
      Alert(cMess+"WINAPI StartPagePrinter() call failed")
   CASE nPrn = -5
      Alert(cMess+"WINAPI malloc() of memory failed")
   CASE nPrn = -6
      Alert(cMess+"WINAPI CreateFile() failed - File "+cFileName+" not found??")
   OTHERWISE
      Alert(cFileName+" PRINTED OK!!!?")
   ENDCASE
ENDIF


I have modified the Class TDosPrn and TTxtPreview (adopted from Ralph in spanish forum) so that the class work more intelligently by identifying the type of the printer selected by the user and accordingly print in Graphics mode or Text Mode.

Now the modified class will handle printing to LPT port even without mapping the LPT port. I thought that it would be much more better if I could make the class to check whether the Printer is Offline or Online.

I know that the Printer spooling system will handle the printing later if the printer is offline. Spooler will start printing, the moment printer is switched on.

Regards

Anser
User avatar
anserkk
 
Posts: 1331
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Postby James Bott » Fri Nov 07, 2008 5:58 am

Anser,

I have never used the routines I posted.

I am guessing that the offline/online status is ignored when spooling is enabled. It does seem irrelavent.

Regards,
James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Roger Seiler » Fri Nov 07, 2008 1:46 pm

Here's a code snippet that might be helpful...

Code: Select all  Expand view
// The next few lines automate protection from a GPF if printer not available...
hDC  := GetPrintDefault( GetActiveWindow() )
SysRefresh()

IF hDC = 0 // Handle rare case where computer has no printer.
   cParam := "X"   // (Previously, this param had to be manually entered when
ENDIF              // launching the app.)

IF EMPTY(cParam) .OR. cParam # "X"
                  // The following may cause a crash if the workstation's
                  // default network printer is unavailable...
   cOldPrinter := PrnGetName()
ELSE // cParam = "X"...
   MsgInfo("To correct a problem with default printer, on the "+CRLF+;
           "next dialog box, select the printer you want to use.","Fix printer selection...")
   PrinterSetup()
   SysRefresh()
   cOldPrinter := PrnGetName()
ENDIF


- Roger
User avatar
Roger Seiler
 
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA

Postby Roger Seiler » Fri Nov 07, 2008 2:38 pm

Here is the function noted by James with translations of returned mesages from Portuguese to English...

Code: Select all  Expand view
function IsPrint( QuePrinter )
   LOCAL nStatus
   DEFAULT QuePrinter := "LPT1:"
   nStatus := PrnStatus( QuePrinter )
   if     nStatus <        1 ; return "Impressora OK"                     // "Printer OK"
   elseif nStatus =        1 ; return "Impressora Pausada"                // "Printer Paused"
   elseif nStatus =        2 ; return "Impressora com Erro"               // "Printer Error"
   elseif nStatus =        4 ; return "Impressora Deletando"              // "Printer Deleting"
   elseif nStatus =        8 ; return "Impressora em Modo Bandeja"        // "Printer Tray Mode"
   elseif nStatus =       16 ; return "Impressora Sem Papel"              // "Printer Without Paper"
   elseif nStatus =       32 ; return "Impressora em Modo Manual"         // "Printer In Manual Way"
   elseif nStatus =       64 ; return "Impressora com Problema no Papel"  // "Printer Paper Problem"
   elseif nStatus =      128 ; return "Impressora OffLine"                // "Printer OffLine"
   elseif nStatus =      256 ; return "Impressora com IO Ativo"           // "Printer With Active IO"
   elseif nStatus =      512 ; return "Impressora Ocupada"                // "Printer Occupied"
   elseif nStatus =     1024 ; return "Impressora Imprimindo"             // "Printer Printing"
   elseif nStatus =     2048 ; return "Impressora Memoria Lotada"         // "Printer Memory Full"
   elseif nStatus =     4096 ; return "Impressora Nao Instalada"          // "Printer Not Installed"
   elseif nStatus =     8192 ; return "Impressora Aguardando"             // "Printer Waiting"
   elseif nStatus =    16384 ; return "Impressora Processando"            // "Printer Processing"
   elseif nStatus =    32768 ; return "Impressora Inicializando"          // "Printer Initializing"
   elseif nStatus =    65536 ; return "Impressora em Atencao"             // "Printer ???"
   elseif nStatus =   131072 ; return "Impressora Toner Baixo"            // "Printer Toner Low"
   elseif nStatus =   262144 ; return "Impressora Sem Toner"              // "Printer Without Toner"
   elseif nStatus =   524288 ; return "Impressora PAGE_PUNT"              // "Printer Page Eject"
   elseif nStatus =  1048576 ; return "Impressora Intervencao do Usuario" // "Printer User Intervention"
   elseif nStatus =  2097152 ; return "Impressora Sem Memoria"            // "Printer Without Memory"
   elseif nStatus =  4194304 ; return "Impressora Tampa Aberta"           // "Printer Open Cover"
   elseif nStatus =  8388608 ; return "Impressora Servidor Desconhecido"  // "Printer Server Disconnected"
   elseif nStatus = 16777217 ; return "Impressora POWER_SAVE"             // "Printer Power Saver"
   endif
User avatar
Roger Seiler
 
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA

Postby Roger Seiler » Fri Nov 07, 2008 2:51 pm

Whoops. The code got chopped off on the right side so that only the first word of the translations shows. I'll fix that in a few minutes and then will post a correction. - R
User avatar
Roger Seiler
 
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA

Postby anserkk » Fri Nov 07, 2008 2:59 pm

Thank you Mr.Roger,

My problem is to find out whether a network dot matrix printer is online or offline. I think I should leave the problem as it is for the time being.

Regards

Anser
User avatar
anserkk
 
Posts: 1331
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Postby James Bott » Fri Nov 07, 2008 3:06 pm

Roger,

The translations are not chopped off, but just word-wrapped.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Roger Seiler » Fri Nov 07, 2008 4:00 pm

Here it is with both Portuguese and English messages...

Code: Select all  Expand view
function IsPrint( QuePrinter, cLang )
   LOCAL aMsg := {},nStatus
   DEFAULT QuePrinter := "LPT1:"
   DEFAULT cLang := "E"   // "P" = Portuguese; "E" = English
   nStatus := PrnStatus( QuePrinter )
   
   if cLang == "P"  // Portuguese                      nStatus value...
      AADD(aMsg, "Impressora OK")                      // <        1
      AADD(aMsg, "Impressora Pausada")                 // =        1
      AADD(aMsg, "Impressora com Erro")                // =        2
      AADD(aMsg, "Impressora Deletando")               // =        4
      AADD(aMsg, "Impressora em Modo Bandeja")         // =        8
      AADD(aMsg, "Impressora Sem Papel")               // =       16
      AADD(aMsg, "Impressora em Modo Manual")          // =       32
      AADD(aMsg, "Impressora com Problema no Papel")   // =       64
      AADD(aMsg, "Impressora OffLine")                 // =      128
      AADD(aMsg, "Impressora com IO Ativo")            // =      256
      AADD(aMsg, "Impressora Ocupada")                 // =      512
      AADD(aMsg, "Impressora Imprimindo")              // =     1024
      AADD(aMsg, "Impressora Memoria Lotada")          // =     2048
      AADD(aMsg, "Impressora Nao Instalada")           // =     4096
      AADD(aMsg, "Impressora Aguardando")              // =     8192
      AADD(aMsg, "Impressora Processando")             // =    16384
      AADD(aMsg, "Impressora Inicializando")           // =    32768
      AADD(aMsg, "Impressora em Atencao")              // =    65536
      AADD(aMsg, "Impressora Toner Baixo")             // =   131072
      AADD(aMsg, "Impressora Sem Toner")               // =   262144
      AADD(aMsg, "Impressora PAGE_PUNT")               // =   524288
      AADD(aMsg, "Impressora Intervencao do Usuario")  // =  1048576
      AADD(aMsg, "Impressora Sem Memoria")             // =  2097152
      AADD(aMsg, "Impressora Tampa Aberta")            // =  4194304
      AADD(aMsg, "Impressora Servidor Desconhecido")   // =  8388608
      AADD(aMsg, "Impressora POWER_SAVE")              // = 16777217
   else
      AADD(aMsg, "Printer OK")                         // <        1
      AADD(aMsg, "Printer Paused")                     // =        1
      AADD(aMsg, "Printer Error")                      // =        2
      AADD(aMsg, "Printer Deletion Pending")           // =        4
      AADD(aMsg, "Printer Paper Jam")                  // =        8
      AADD(aMsg, "Printer Without Paper")              // =       16
      AADD(aMsg, "Printer Manual Feed")                // =       32
      AADD(aMsg, "Printer Paper Problem")              // =       64
      AADD(aMsg, "Printer OffLine")                    // =      128
      AADD(aMsg, "Printer IO Active")                  // =      256
      AADD(aMsg, "Printer Busy")                       // =      512
      AADD(aMsg, "Printer Printing")                   // =     1024
      AADD(aMsg, "Printer Output Bin Full")            // =     2048
      AADD(aMsg, "Printer Not Available")              // =     4096
      AADD(aMsg, "Printer Waiting")                    // =     8192
      AADD(aMsg, "Printer Processing")                 // =    16384
      AADD(aMsg, "Printer Initializing")               // =    32768
      AADD(aMsg, "Printer Warming Up")                 // =    65536
      AADD(aMsg, "Printer Toner Low")                  // =   131072
      AADD(aMsg, "Printer Without Toner")              // =   262144
      AADD(aMsg, "Printer Page Punt")                  // =   524288
      AADD(aMsg, "Printer User Intervention")          // =  1048576
      AADD(aMsg, "Printer Out Of Memory")              // =  2097152
      AADD(aMsg, "Printer Door Open")                  // =  4194304
      AADD(aMsg, "Printer Server Unknown")             // =  8388608
      AADD(aMsg, "Printer Power Save")                 // = 16777217
   endif

   if     nStatus <        1 ; return aMsg[1]    // "Printer OK"
   elseif nStatus =        1 ; return aMsg[2]    // "Printer Paused"
   elseif nStatus =        2 ; return aMsg[3]    // "Printer Error"
   elseif nStatus =        4 ; return aMsg[4]    // "Printer Deletion Pending"
   elseif nStatus =        8 ; return aMsg[5]    // "Printer Paper Jam"
   elseif nStatus =       16 ; return aMsg[6]    // "Printer Without Paper"
   elseif nStatus =       32 ; return aMsg[7]    // "Printer Manual Feed"
   elseif nStatus =       64 ; return aMsg[8]    // "Printer Paper Problem"
   elseif nStatus =      128 ; return aMsg[9]    // "Printer OffLine"
   elseif nStatus =      256 ; return aMsg[10]   // "Printer IO Active"
   elseif nStatus =      512 ; return aMsg[11]   // "Printer Busy"
   elseif nStatus =     1024 ; return aMsg[12]   // "Printer Printing"
   elseif nStatus =     2048 ; return aMsg[13]   // "Printer Output Bin Full"
   elseif nStatus =     4096 ; return aMsg[14]   // "Printer Not Available"
   elseif nStatus =     8192 ; return aMsg[15]   // "Printer Waiting"
   elseif nStatus =    16384 ; return aMsg[16]   // "Printer Processing"
   elseif nStatus =    32768 ; return aMsg[17]   // "Printer Initializing"
   elseif nStatus =    65536 ; return aMsg[18]   // "Printer Warming Up"
   elseif nStatus =   131072 ; return aMsg[19]   // "Printer Toner Low"
   elseif nStatus =   262144 ; return aMsg[20]   // "Printer Without Toner"
   elseif nStatus =   524288 ; return aMsg[21]   // "Printer Page Punt"
   elseif nStatus =  1048576 ; return aMsg[22]   // "Printer User Intervention"
   elseif nStatus =  2097152 ; return aMsg[23]   // "Printer Out Of Memory"
   elseif nStatus =  4194304 ; return aMsg[24]   // "Printer Door Open"
   elseif nStatus =  8388608 ; return aMsg[25]   // "Printer Server Unknown"
   elseif nStatus = 16777217 ; return aMsg[26]   // "Printer Power Save"
   endif

User avatar
Roger Seiler
 
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA

Postby Otto » Fri Nov 07, 2008 4:22 pm

I found this VB6 code. Maybe this helps.
Regards,
Otto


http://www.planetsourcecode.com/vb/scri ... phabetical
Code: Select all  Expand view
1. What the Printer object missed

Printing has long been a very problematic part of developing complete and professional applications in Visual Basic. This was redressed to a large degree with the new Printer object introduced in Visual Basic 4.
However, there are shortcomings with this object. The biggest shortcoming is that you cannot find out whether the printer is ready, busy, out of paper etc. from your application.
However, there is an API call, GetPrinter which returns a great deal more information about a printer.

<-- API Declaration -->
Private Declare Function GetPrinterApi Lib "winspool.drv" Alias _
       "GetPrinterA" (ByVal hPrinter As Long, _
         ByVal Level As Long, _
         buffer As Long, _
         ByVal pbSize As Long, _
         pbSizeNeeded As Long) As Long

This takes the handle to a printer in hPrinter and fills the buffer provided to it with information from the printer driver. To get the handle from the Printer object, you need to use the OpenPrinter API call.
This handle must be released using the ClosePrinter API call as soon as you are finished with it.

<-- API Declaration -->
Private Type PRINTER_DEFAULTS
  pDatatype As String
  pDevMode As DEVMODE
  DesiredAccess As Long
End Type

Private Declare Function OpenPrinter Lib "winspool.drv" _
    Alias "OpenPrinterA" (ByVal pPrinterName As String, _
    phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long

Private Declare Function ClosePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long


You pass the Printer.DeviceName to this to get the handle.

<-- Use -->
Dim lret As Long
Dim pDef As PRINTER_DEFAULTS

lret = OpenPrinter(Printer.DeviceName, mhPrinter, pDef)

2. The different statuses

There are a number of standard statuses that can be returned by the printer driver.

<-- Enumerated type -->
Public Enum Printer_Status
   PRINTER_STATUS_READY = &H0
   PRINTER_STATUS_PAUSED = &H1
   PRINTER_STATUS_ERROR = &H2
   PRINTER_STATUS_PENDING_DELETION = &H4
   PRINTER_STATUS_PAPER_JAM = &H8
   PRINTER_STATUS_PAPER_OUT = &H10
   PRINTER_STATUS_MANUAL_FEED = &H20
   PRINTER_STATUS_PAPER_PROBLEM = &H40
   PRINTER_STATUS_OFFLINE = &H80
   PRINTER_STATUS_IO_ACTIVE = &H100
   PRINTER_STATUS_BUSY = &H200
   PRINTER_STATUS_PRINTING = &H400
   PRINTER_STATUS_OUTPUT_BIN_FULL = &H800
   PRINTER_STATUS_NOT_AVAILABLE = &H1000
   PRINTER_STATUS_WAITING = &H2000
   PRINTER_STATUS_PROCESSING = &H4000
   PRINTER_STATUS_INITIALIZING = &H8000
   PRINTER_STATUS_WARMING_UP = &H10000
   PRINTER_STATUS_TONER_LOW = &H20000
   PRINTER_STATUS_NO_TONER = &H40000
   PRINTER_STATUS_PAGE_PUNT = &H80000
   PRINTER_STATUS_USER_INTERVENTION = &H100000
   PRINTER_STATUS_OUT_OF_MEMORY = &H200000
   PRINTER_STATUS_DOOR_OPEN = &H400000
   PRINTER_STATUS_SERVER_UNKNOWN = &H800000
   PRINTER_STATUS_POWER_SAVE = &H1000000
End Enum

3. The data structures

  As each printer driver is responsible for returning this data there has to be a standard to which this returned data conforms in order for one application to be able to query a number of different types of printers. As it happens, there are nine different standard data types that can be returned by the GetPrinter API call in Windows 2000 (only the first two are universal to all current versions of Windows).
Of these, the second is the most interesting - named PRINTER_INFO_2 <-- Data structure -->

Private Type PRINTER_INFO_2
   pServerName As String
   pPrinterName As String
   pShareName As String
   pPortName As String
   pDriverName As String
   pComment As String
   pLocation As String
   pDevMode As Long
   pSepFile As String
   pPrintProcessor As String
   pDatatype As String
   pParameters As String
   pSecurityDescriptor As Long
   Attributes As Long
   Priority As Long
   DefaultPriority As Long
   StartTime As Long
   UntilTime As Long
   Status As Long
   JobsCount As Long
   AveragePPM As Long
End Type

  However, it is not as simple as just passing this structure to the GetPrinter API call as a printer can return more information than is in that structure and if you do not allocate sufficent buffer space for it to do so your application will crash.
Fortunately the API call caters for this - if you pass zero in the pbSize parameter then the API call will tell you how big a buffer you will require in the pbSizeNeeded.
This means that filling the information from the printer driver becomes a two step process:

<-- Using the GetPrinter API call -->
  Dim lret As Long
  Dim SizeNeeded As Long

  Dim buffer() As Long

  ReDim Preserve buffer(0 To 1) As Long
  lret = GetPrinterApi(mhPrinter, Index, buffer(0), UBound(buffer), SizeNeeded)
  ReDim Preserve buffer(0 To (SizeNeeded / 4) + 3) As Long
  lret = GetPrinterApi(mhPrinter, Index, buffer(0), UBound(buffer) * 4, SizeNeeded)


<-- Retrieving the string part -->
  However the buffer is just an array of Long data types. Some of the data within the PRINTER_INFO_2 data structure is String data. This must be collected from the addresses which are stored in the appropriate buffer position.

  To get a string from a pointer the CopyMemory API call is used and there is also an API call, IsBadStringPtr, which can be used to verify that the address pointed to does actually contain a valid string.

<-- Declarations -->
'\\ Memory manipulation routines '
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'\\ Pointer validation in StringFromPointer
Private Declare Function IsBadStringPtrByLong Lib "kernel32" Alias "IsBadStringPtrA" (ByVal lpsz As Long, ByVal ucchMax As Long) As Long


Retrieving the string from a pointer is a common thing to have to do so it is worth having this utility function in your arsenal.

Public Function StringFromPointer(lpString As Long, lMaxLength As Long) As String


  Dim sRet As String
  Dim lret As Long

  If lpString = 0 Then
    StringFromPointer = ""
    Exit Function
  End If

  If IsBadStringPtrByLong(lpString, lMaxLength) Then
    '\\ An error has occured - do not attempt to use this pointer
      StringFromPointer = ""
    Exit Function
  End If

  '\\ Pre-initialise the return string...
  sRet = Space$(lMaxLength)
  CopyMemory ByVal sRet, ByVal lpString, ByVal Len(sRet)
  If Err.LastDllError = 0 Then
    If InStr(sRet, Chr$(0)) > 0 Then
      sRet = Left$(sRet, InStr(sRet, Chr$(0)) - 1)
    End If
  End If

  StringFromPointer = sRet

End Function


So to use this to populate your PRINTER_INFO_2 variable:

With mPRINTER_INFO_2 '\\ This variable is of type PRINTER_INFO_2
   .pServerName = StringFromPointer(buffer(0), 1024)
   .pPrinterName = StringFromPointer(buffer(1), 1024)
   .pShareName = StringFromPointer(buffer(2), 1024)
   .pPortName = StringFromPointer(buffer(3), 1024)
   .pDriverName = StringFromPointer(buffer(4), 1024)
   .pComment = StringFromPointer(buffer(5), 1024)
   .pLocation = StringFromPointer(buffer(6), 1024)
   .pDevMode = buffer(7)
   .pSepFile = StringFromPointer(buffer(8), 1024)
   .pPrintProcessor = StringFromPointer(buffer(9), 1024)
   .pDatatype = StringFromPointer(buffer(10), 1024)
   .pParameters = StringFromPointer(buffer(11), 1024)
   .pSecurityDescriptor = buffer(12)
   .Attributes = buffer(13)
   .Priority = buffer(14)
   .DefaultPriority = buffer(15)
   .StartTime = buffer(16)
   .UntilTime = buffer(17)
   .Status = buffer(18)
   .JobsCount = buffer(19)
   .AveragePPM = buffer(20)
End With



User avatar
Otto
 
Posts: 6107
Joined: Fri Oct 07, 2005 7:07 pm


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 70 guests