HOWTO: Modify Printer Settings by Using SetPrinter

Last reviewed: April 24, 1997
Article ID: Q140285
The information in this article applies to:
  • Microsoft Win32 Software Development Kit (SDK) versions 3.5, 3.51, 4.0

SUMMARY

SetPrinter is a new API for Windows 95 and Windows NT that allows applications to change various printer attributes. However, as the code in this article demonstrates, a certain amount of preparation is necessary in order to call SetPrinter correctly.

MORE INFORMATION

The parameters to SetPrinter() are as follows:

hPrinter

The first parameter is a handle to the printer whose settings are to be changed. This should be retrieved from OpenPrinter().

dwLevel

The second parameter specifies the structure of the data being passed to SetPrinter(). For Windows 95, this can be 0, 2, 3, 4, or 5. For Windows NT, this can be 0, 2, or 3. These numbers correspond to the data type (PRINTER_INFO_n) passed via the third parameter.

lpbPrinter

The third parameter is a PRINTER_INFO_n structure where n corresponds to the number in the second parameter. This structure can cause confusion because it isn't simply a buffer of the size of the structure. These structures contain device-independent information but are immediately followed in memory by some variable amount of device-dependent information, which is given by the device driver. Therefore, a little work is involved to determine how big this buffer should be. This is achieved by calling GetPrinter(), which will set pcbNeeded to the total size needed.

Also, the buffer typically has a large amount of device-independent and device-dependent information in it. Your application is not going to know or care about the values in most of these structure members. So, when you make the changes in which you are interested, you must plug in the correct values for all of these other pieces of data. These other pieces of data are set when you call GetPrinter() a second time.

dwCommand

The fourth parameter is used to pause printing, resume printing, or clear all print jobs. This is typically not used at the same time as lpbPrinter is used. This article is not concerned with setting the printer state, so the sample code sets this parameter to zero.

About DEVMODE

Often, an element of the DEVMODE structure pointed to by pDevMode will be modified (instead of an element of PRINTER_INFO_n). When this is the case, the pDevMode->dmFields flags will tell the application which fields can be changed. Because this is given to you by GetPrinter(), you can check the dmFields flag before attempting the change.

Also, because modifying fields in the device-independent part of DEVMODE may also effect changes in the device-dependent part, you need to call DocumentProperties() before calling SetPrinter() in order to make a consistent DEVMODE structure for SetPrinter().

Sample Code

   HGLOBAL hGlobal = NULL;
   HANDLE hPrinter = NULL;
   DWORD dwNeeded = 0;
   PRINTER_INFO_2 *pi2 = NULL;
   PRINTER_DEFAULTS pd;
   BOOL bFlag;
   LONG lFlag;

   /* Open printer handle (in Windows NT, you need full-access because you
      will eventually use SetPrinter) */

   ZeroMemory(&pd, sizeof(pd));
   pd.DesiredAccess = PRINTER_ALL_ACCESS;
   bFlag = OpenPrinter("My Printer", &hPrinter, &pd);
   if (!bFlag || (hPrinter== NULL))
      goto ABORT;

   /* The first GetPrinter() tells you how big the buffer should be in
      order to hold all of PRINTER_INFO_2. Note that this usually returns
      as FALSE, which only means that the buffer (the third parameter) was
      not filled in. You don't want it filled in here. */

   GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
   if (dwNeeded == 0)
      goto ABORT;

   /* Allocate enough space for PRINTER_INFO_2. */

   hGlobal = GlobalAlloc(GHND, dwNeeded);
   if (hGlobal == NULL)
      goto ABORT;
   pi2 = (PRINTER_INFO_2 *)GlobalLock(hGlobal);
   if (pi2 == NULL)
      goto ABORT;

   /* The second GetPrinter() fills in all the current settings, so all you
      need to do is modify what you'r interested in. */

   bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
   if (!bFlag)
      goto ABORT;

   /* Set orientation to Landscape mode if the driver supports it. */

   if ((pi2->pDevMode != NULL) && (pi2->pDevMode->dmFields &
                                   DM_ORIENTATION))
   {
      /* Change the devmode. */
      pi2->pDevMode->dmOrientation = DMORIENT_LANDSCAPE;

      /* Make sure the driver-dependent part of devmode is updated as
         necessary. */
      lFlag = DocumentProperties(hwnd, hPrinter,
               "My Printer",
               pi2->pDevMode, pi2->pDevMode,
               DM_IN_BUFFER | DM_OUT_BUFFER);
      if (lFlag != IDOK)
         goto ABORT;

      /* Update printer information. */
      bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);
      if (!bFlag)
         /* The driver supported the change, but it wasn't allowed due to
            some other reason (probably lack of permission). */
         goto ABORT;
   }
   else
      /* The driver doesn't support changing this. */
      goto ABORT;

   /* Clean up. */
   ABORT:   if (pi2 != NULL)
         GlobalUnlock(hGlobal);
      if (hGlobal != NULL)
         GlobalFree(hGlobal);
      if (hPrinter != NULL)
         ClosePrinter(hPrinter);


Additional query words: print settings
Keywords : GdiPrn kbcode kbgraphic
Version : 3.5 3.51 4.0
Platform : NT WINDOWS
Issue type : kbhowto


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: April 24, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.