Click here to Skip to main content
15,884,472 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I have followed instructions in msdn to change at runtime a printer paper size configuration in my application (http://support.microsoft.com/?scid=kb;en-us;140285&x=12&y=8). I have replaced the dmOrientation option by the dmPaperSize to meet my need.

All seems to execute fine (no error), but my new paper size is not taken into account until I manually validate the paper size from the printer options dialog box opened from the control panel. (Step 4 on the image http://picasaweb.google.com/stephane.rzetelny/DropBox#5497051130735465906).

To try to understand what I have missed, I have spy what's happened in file and registry when I execute the code snippet from msdn and when I validate the printer options dialog box with the incredible procmonitor.exe tool from sysinternal. Result is: there is no difference !!

So I don't understand what I have missed !

Any suggestion would be very appreciated.

Regards.

-------------------------------

Here is the code sample :
// TestPrinterDocSettings.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

int _iPaperCount = 0;
WORD* _pPapers = NULL;
char* _pPaperNames = NULL;
POINT* _pPaperSizes = NULL;

#define PRINTER_NAME "Receipt Printer"

// Function that enumerates all available paper forms:
void ListPapers()
{
	HANDLE hPrinter = NULL;
	if (_pPapers)
	{
		delete [] _pPapers;
		_pPapers = NULL;
	}
	
	if (_pPaperNames)
	{
		delete [] _pPaperNames;
		_pPaperNames = NULL;
	}
	
	if (_pPaperSizes)
	{
		delete [] _pPaperSizes;
		_pPaperSizes = NULL;
	}
	
	if (OpenPrinter(PRINTER_NAME, &hPrinter, NULL))
	{
		DWORD dwNeeded = 0;
		
		// get printer forms
		_iPaperCount = DeviceCapabilities(PRINTER_NAME, NULL, DC_PAPERS, NULL, NULL);
		if (_iPaperCount)
		{
			_pPapers = new WORD[_iPaperCount];
			ZeroMemory(_pPapers, sizeof(WORD)*_iPaperCount);
			DeviceCapabilities(PRINTER_NAME, NULL, DC_PAPERS, (LPSTR) _pPapers, NULL);
			
			_pPaperNames = new char[_iPaperCount*64];
			ZeroMemory(_pPaperNames, sizeof(char)*64*_iPaperCount);
			DeviceCapabilities(PRINTER_NAME, NULL, DC_PAPERNAMES, _pPaperNames, NULL);
			
			for (int i = 0; i < _iPaperCount; i++)
			{
				printf("%d : %s\n", i, _pPaperNames+(i*64));
			}
		}
		
		ClosePrinter(hPrinter);
	}
	else
	{
		// report error
		printf("ListPapers : Unable to open printer %s. Error = %d\n", PRINTER_NAME, GetLastError());
	}
}



// MySetPrinter
// 
// Demonstrates how to use the SetPrinter API.
BOOL MySetPrinter(LPTSTR pPrinterName, short papersizenb, DWORD Level)
{
	HANDLE hPrinter = NULL;
	DWORD dwNeeded = 0;
	BYTE *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, Level, 0, 0, &dwNeeded);
	if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || 
		(dwNeeded == 0))
	{
		ClosePrinter(hPrinter);
		return FALSE;
	}
	
	// Allocate enough space for PRINTER_INFO_2...
	pi2 = (BYTE *)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, Level, pi2, dwNeeded, &dwNeeded);
	if (!bFlag)
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		return FALSE;
	}

	if (Level == 2)
	{
		pDevMode = ((PRINTER_INFO_2*)pi2)->pDevMode;
	}
	else if( Level == 8)
	{
		pDevMode = ((PRINTER_INFO_8*)pi2)->pDevMode;
	}
	else if (Level = 9)
	{
		pDevMode = ((PRINTER_INFO_9*)pi2)->pDevMode;
	}
	else
	{
		pDevMode = NULL;
	}
	
	// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
	// DocumentProperties...
	if (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;
		}
	}
	
	// Driver is reporting that it doesn't support this change...
	if (!(pDevMode->dmFields & DM_PAPERSIZE))
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		if (pDevMode)
			GlobalFree(pDevMode);
		return FALSE;
	}
	
	// Specify exactly what we are attempting to change...
	if(papersizenb <= _iPaperCount)
	{
		pDevMode->dmPaperSize = _pPapers[papersizenb];
	}
	
	if(Level == 2)
	{
		// Do not attempt to set security descriptor...
		((PRINTER_INFO_2*)pi2)->pSecurityDescriptor = NULL;
	}
	
	// Make sure the driver-dependent part of devmode is updated...
	lFlag = DocumentProperties(NULL, hPrinter,
		pPrinterName,
		pDevMode, 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, Level, (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;
}

int main(int argc, char* argv[])
{
	// display all available papers size for the printer
	ListPapers();
	
	int papersizenb = 0;
	printf("Saisir le numero du format de papier a configurer sur l'imprimante : ");
	scanf("%d", &papersizenb);
	
	// change current properties of the printer
	MySetPrinter(PRINTER_NAME, papersizenb, 2);
	
	// change default properties of the printer
	MySetPrinter(PRINTER_NAME, papersizenb, 8);
	
	// change current user properties of the printer
	MySetPrinter(PRINTER_NAME, papersizenb, 9);
	
	printf("Appuyer sur une lettre + \"Entree\" pour continuer");
	scanf("%d", &papersizenb);
	
	return 0;
}</stdio.h></windows.h>
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900