views:

17

answers:

0

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;
}