Hello,
I have followed instructions on the msdn to change at runtime a printer paper size configuration in my application. 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
#include
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;
}