CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Dec 1999
    Location
    Dublin, Ireland
    Posts
    1,173

    How to list printer jobs

    I have been working on code to list the printer jobs for any given printer. This is what I have so far...
    (assumes a form with a listview control and a combo box control on it)


    'Declarations...
    option Explicit

    '\\ API Declarations
    private Declare Function EnumJobs Lib "winspool.drv" Alias "EnumJobsA" _
    (byval hPrinter as Long, _
    byval FirstJob as Long, _
    byval NoJobs as Long, _
    byval Level as Long, _
    pJob as Long, _
    byval cdBuf as Long, _
    pcbNeeded as Long, _
    pcReturned as Long) as Long


    private Type PRINTER_DEFAULTS
    pDatatype as string
    pDevMode as Long
    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

    '\\ Declarations for StringFromPointer
    private Declare Function IsBadStringPtrByLong Lib "kernel32" Alias "IsBadStringPtrA" (byval lpsz as Long, byval ucchMax as Long) as Long

    private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination as Any, _
    Source as Any, _
    byval Length as Long)




    First we need to get a list of all the printers on this system in a combo box (and init the listview as well) in the Form_Load:


    private Sub Form_Load()

    '\\ List all the printers into the combo box...
    Dim prtThis as Printer

    cmbPrinters.Clear
    for Each prtThis In Printers
    cmbPrinters.AddItem prtThis.DeviceName
    next prtThis
    '\\ set printer list to current printer
    cmbPrinters.Text = Printer.DeviceName


    '\\ set the columns of the listview
    With lvwPrintJobs.ColumnHeaders
    .Clear
    .Add , "JOB_ID", "Job Id", 1440
    .Add , "USER", "User", 1440
    .Add , "DOCUMENT", "Document", 1440
    .Add , "DATATYPE", "Data Type", 1440
    End With

    End Sub




    Then whenever the listbox is clicked we need to list the jobs on that printer.


    private Sub cmbPrinters_Click()

    Call RefreshJobList(cmbPrinters.Text)

    End Sub

    '\\ --[RefreshJobList]----------------------------------------------
    '\\ Fills the listview control with information on the currently
    '\\ active print jobs
    '\\ ----------------------------------------------------------------
    public Sub RefreshJobList(byval PrinterName as string)

    Dim mPrintHandle as Long, lRet as Long
    Dim pDEf as PRINTER_DEFAULTS

    Dim pcBytesRequired as Long, pcRecordsReturned as Long
    Dim pBuff() as Long
    Dim nJob as Long, pJobOffset as Long

    '\\ Obtain a handle to the named printer
    lRet = OpenPrinter(PrinterName, mPrintHandle, pDEf)
    If Err.LastDllError = 0 then
    '\\ Clear any existing listed jobs...
    lvwPrintJobs.ListItems.Clear
    If mPrintHandle <> 0 then
    '\\ get size of buffer required to hold printer jobs info
    ReDim Preserve pBuff(0) as Long
    lRet = EnumJobs(mPrintHandle, 0, 255, 1, pBuff(0), UBound(pBuff) * 4, pcBytesRequired, pcRecordsReturned)
    If pcBytesRequired > 0 then
    ReDim Preserve pBuff(0 to (pcBytesRequired / 4) + 3) as Long
    lRet = EnumJobs(mPrintHandle, 0, 255, 1, pBuff(0), UBound(pBuff) * 4, pcBytesRequired, pcRecordsReturned)
    End If
    If pcRecordsReturned > 0 then
    '\\ for each job, decode its records....
    for nJob = 0 to (pcRecordsReturned - 1)
    '\\ Each record is 16 longs...
    pJobOffset = nJob * 16
    '\\ add the current job to the list
    lvwPrintJobs.ListItems.Add , "JOB" & nJob, pBuff(pJobOffset)
    '\\ Username is in Offset+3
    lvwPrintJobs.ListItems.Item(lvwPrintJobs.ListItems.Count).SubItems(1) = StringFromPointer(pBuff(pJobOffset + 3), 1024)
    '\\ Document is in Offset+4
    lvwPrintJobs.ListItems.Item(lvwPrintJobs.ListItems.Count).SubItems(2) = StringFromPointer(pBuff(pJobOffset + 4), 1024)
    '\\ DataType is in Offset+5
    lvwPrintJobs.ListItems.Item(lvwPrintJobs.ListItems.Count).SubItems(3) = StringFromPointer(pBuff(pJobOffset + 5), 1024)
    next nJob
    End If

    '\\ Release the named printer's handle
    lRet = ClosePrinter(mPrintHandle)
    End If
    End If

    End Sub




    Note that because we have passed a buffer of Long values, our string values (user name, document name etc) are returned as pointers so we need to convert them to strings to use them..


    private 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 Not IsBadStringPtrByLong(lpString, lMaxlength) then
    '\\ set aside space to copy string to
    sRet = string$(lMaxlength, 0)
    CopyMemory byval sRet, byval lpString, byval len(sRet)
    If InStr(sRet, Chr$(0)) > 0 then
    sRet = Left$(sRet, InStr(sRet, Chr$(0)) - 1)
    End If
    End If

    StringFromPointer = sRet

    End Function




    HTH,
    Duncan

    (When complete, this functionality will be included in the EventVB Win32API wrapper project to allow syntax like:


    for Each ApiPrintJob In Printer.PrintJobs
    Debug.print ApiPrintJob.Username
    next ApiPrintJob



    )

    -------------------------------------------------
    Ex. Datis: Duncan Jones
    Merrion Computing Ltd
    http://www.merrioncomputing.com
    Check out the new downloads - ImageMap.ocx is the VB control that emulates an HTML image map, EventVB.OCX for adding new events to your VB form and adding System Tray support simply, MCL Hotkey for implemenmting system-wide hotkeys in your application...all with source code included.
    '--8<-----------------------------------------
    NEW -The printer usage monitoring application
    '--8<------------------------------------------

  2. #2
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Re: You're great

    You know.
    ;-)


    Special thanks to Lothar "the Great" Haensler, Tom Archer, Chris Eastwood, TCartwright, Bruno Paris, Dr_Micahel
    and all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

    The Rater
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured