You are currently offline, waiting for your internet to reconnect

How To Modify Printer Settings by Using SetPrinter

SetPrinter is a new API for Windows 95, Windows NT, Windows 2000, and Windows XP 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:


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


The second parameter specifies the structure of the data being passed toSetPrinter(). 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.


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 immediatelyfollowed in memory by some variable amount of device-dependent information,which is given by the device driver. Therefore, a little work is involvedto determine how big this buffer should be. This is achieved by callingGetPrinter(), which will set pcbNeeded to the total size needed.

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


The fourth parameter is used to pause printing, resume printing, orclear all print jobs. This is typically not used at the same time aslpbPrinter is used. This article is not concerned with setting the printerstate, so the sample code sets this parameter to zero.


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 DEVMODEmay also effect changes in the device-dependent part, you need to callDocumentProperties() before calling SetPrinter() in order to make a consistent DEVMODE structure for SetPrinter().

Sample Code

// MySetPrinter// // Demonstrates how to use the SetPrinter API.  This particular function changes the orienation// for the printer specified in pPrinterName to the orientation specified in dmOrientation.// // Valid values for dmOrientation are:// DMORIENT_PORTRAIT (1)// or// DMORIENT_LANDSCAPE (2)BOOL MySetPrinter(LPTSTR pPrinterName, short dmOrientation){	HANDLE hPrinter = NULL;	DWORD dwNeeded = 0;	PRINTER_INFO_2 *pi2 = NULL;	DEVMODE *pDevMode = NULL;	PRINTER_DEFAULTS pd;	BOOL bFlag;	LONG lFlag;	// Open printer handle (on Windows NT, you need full-access because you	// will eventually use SetPrinter)...	ZeroMemory(&pd, sizeof(pd));	pd.DesiredAccess = PRINTER_ALL_ACCESS;	bFlag = OpenPrinter(pPrinterName, &hPrinter, &pd);	if (!bFlag || (hPrinter == NULL))		return FALSE;	// The first GetPrinter tells you how big the buffer should be in 	// order to hold all of PRINTER_INFO_2. Note that this should fail with 	// ERROR_INSUFFICIENT_BUFFER.  If GetPrinter fails for any other reason 	// or dwNeeded isn't set for some reason, then there is a problem...	SetLastError(0);	bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);         if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) ||          (dwNeeded == 0))	{		ClosePrinter(hPrinter);		return FALSE;	}	// Allocate enough space for PRINTER_INFO_2...	pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);	if (pi2 == NULL)	{		ClosePrinter(hPrinter);		return FALSE;	}	// The second GetPrinter fills in all the current settings, so all you	// need to do is modify what you're interested in...	bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);	if (!bFlag)	{		GlobalFree(pi2);		ClosePrinter(hPrinter);		return FALSE;	}	// If GetPrinter didn't fill in the DEVMODE, try to get it by calling	// DocumentProperties...	if (pi2->pDevMode == NULL)	{		dwNeeded = DocumentProperties(NULL, hPrinter,						pPrinterName,						NULL, NULL, 0);		if (dwNeeded <= 0)		{			GlobalFree(pi2);			ClosePrinter(hPrinter);			return FALSE;		}		pDevMode = (DEVMODE *)GlobalAlloc(GPTR, dwNeeded);		if (pDevMode == NULL)		{			GlobalFree(pi2);			ClosePrinter(hPrinter);			return FALSE;		}		lFlag = DocumentProperties(NULL, hPrinter,						pPrinterName,						pDevMode, NULL,						DM_OUT_BUFFER);		if (lFlag != IDOK || pDevMode == NULL)		{			GlobalFree(pDevMode);			GlobalFree(pi2);			ClosePrinter(hPrinter);			return FALSE;		}		pi2->pDevMode = pDevMode;	}	// Driver is reporting that it doesn't support this change...	if (!(pi2->pDevMode->dmFields & DM_ORIENTATION))	{		GlobalFree(pi2);		ClosePrinter(hPrinter);		if (pDevMode)			GlobalFree(pDevMode);		return FALSE;	}	// Specify exactly what we are attempting to change...	pi2->pDevMode->dmFields = DM_ORIENTATION;	pi2->pDevMode->dmOrientation = dmOrientation;	// Do not attempt to set security descriptor...	pi2->pSecurityDescriptor = NULL;	// Make sure the driver-dependent part of devmode is updated...	lFlag = DocumentProperties(NULL, hPrinter,		  pPrinterName,		  pi2->pDevMode, pi2->pDevMode,		  DM_IN_BUFFER | DM_OUT_BUFFER);	if (lFlag != IDOK)	{		GlobalFree(pi2);		ClosePrinter(hPrinter);		if (pDevMode)			GlobalFree(pDevMode);		return FALSE;	}	// Update printer information...	bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);	if (!bFlag)	// The driver doesn't support, or it is unable to make the change...	{		GlobalFree(pi2);		ClosePrinter(hPrinter);		if (pDevMode)			GlobalFree(pDevMode);		return FALSE;	}	// Tell other apps that there was a change...	SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0L,			  (LPARAM)(LPCSTR)pPrinterName,			  SMTO_NORMAL, 1000, NULL);	// Clean up...	if (pi2)		GlobalFree(pi2);	if (hPrinter)		ClosePrinter(hPrinter);	if (pDevMode)		GlobalFree(pDevMode);	return TRUE;}				
print settings

Article ID: 140285 - Last Review: 06/22/2014 17:59:00 - Revision: 4.0

  • kbcode kbgdi kbhowto kbprint KB140285
t("meta"); m.content = guid; = "ms.dqid"; document.getElementsByTagName("head")[0].appendChild(m);