I use the following code to change page height and width for a local printer:
int SetPrintedPageSize(float width, float height)
{
//Code adapted from Microsoft KB article Q230743
HANDLE hPrinter = NULL; //handle for the current printer
PRINTER_DEFAULTS pd;
PRINTER_INFO_2 pinfo;
DEVMODE dm;
char sPrinterName[10];
char* yDevModeData; //Byte array to hold contents
//of DEVMODE structure
char* yPInfoMemory; //Byte array to hold contents
//of PRINTER_INFO_2 structure
unsigned long iBytesNeeded;
int iRet = 0;
unsigned long iJunk;
//int iCount;
pd.pDatatype = 0;
pd.pDevMode = 0;
memset((void*)&pinfo, 0, sizeof(pinfo));
memset((void*)&dm, 0, sizeof(dm));
//Get the name of the current printer
strcpy(sPrinterName, "PDF995");
pd.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
iRet = ::OpenPrinter(sPrinterName, &hPrinter, &pd);
if(iRet == 0 || hPrinter == 0)
{
WriteToWIPFile("Cannot access current printer");
//Can't access current printer. Bail out doing nothing
goto CLEANUP;
}
//Get the size of the DEVMODE structure to be loaded
iRet = :ocumentProperties(0, hPrinter, sPrinterName, 0, 0, 0);
if(iRet < 0)
{
//Can't access printer properties.
WriteToWIPFile("Cannot access printer properties");
goto CLEANUP;
}
//Make sure the byte array is large enough
//Some printer drivers lie about the size of the DEVMODE structure they
//return, so an extra 100 bytes is provided just in case!
yDevModeData = new char[iRet + 100];
//Load the byte array
iRet = :ocumentProperties(0, hPrinter, sPrinterName,
(DEVMODE*)yDevModeData, 0, DM_OUT_BUFFER );
if(iRet < 0)
{
WriteToWIPFile("Cannot get document properties");
goto CLEANUP;
}
//Copy the byte array into a structure so it can be manipulated
::CopyMemory(&dm, yDevModeData, sizeof(dm));
//Set the property to the appropriate value
dm.dmPaperLength = height * 254 / 72;
dm.dmPaperWidth = width * 254 / 72;
dm.dmPaperSize = 0;
dm.dmFields = dm.dmFields | DM_PAPERLENGTH | DM_PAPERWIDTH;
//Load the structure back into the byte array
::CopyMemory(yDevModeData, &dm, sizeof(dm));
//Tell the printer about the new property
iRet = :ocumentProperties(0, hPrinter, sPrinterName,
(DEVMODE*)yDevModeData, (DEVMODE*)yDevModeData, DM_IN_BUFFER | DM_OUT_BUFFER);
dm.dmPaperSize = 0;
if(iRet < 0)
{
WriteToWIPFile("Cannot tell the printer about the new property");
goto CLEANUP;
}
//The code above *ought* to be sufficient to set the property
//correctly. Unfortunately some brands of Postscript printer don't
//seem to respond correctly. The following code is used to make
//sure they also respond correctly.
if(!::GetPrinter(hPrinter, 2, 0, 0, &iBytesNeeded))
{
//long error = GetLastError();
WriteToWIPFile(GetLastErrorMessage());
}
if(iBytesNeeded == 0)
{
//Couldn't access shared printer settings
WriteToWIPFile("Cannot access shared printer settings");
goto CLEANUP;
}
//Set byte array large enough for PRINTER_INFO_2 structure
yPInfoMemory = new char[iBytesNeeded + 100];
//Load the PRINTER_INFO_2 structure into byte array
iRet = ::GetPrinter(hPrinter, 2, (unsigned char*)yPInfoMemory, iBytesNeeded, &iJunk);
if (iRet == 0)
{
WriteToWIPFile("Could not load printer info structure");
//Couldn't access shared printer settings
goto CLEANUP;
}
//Copy byte array into the structured type
::CopyMemory(&pinfo, yPInfoMemory, sizeof(pinfo));
//Load the DEVMODE structure with byte array containing
//the new property value
pinfo.pDevMode = &dm;
//Set security descriptor to null
pinfo.pSecurityDescriptor = 0;
//Copy the PRINTER_INFO_2 structure back into byte array
::CopyMemory(yPInfoMemory, &pinfo, sizeof(pinfo));
//Send the new details to the printer
iRet = ::SetPrinter(hPrinter, 2, (unsigned char*)yPInfoMemory, 0);
if(iRet == 0)
WriteToWIPFile("Could not set the printer");
CLEANUP:
//Release the printer handle
if(hPrinter != 0)
::ClosePrinter(hPrinter);
//Indicate whether it all worked or not!
return iRet > 0;
}
The code works perfectly on Windows 2000 Server, but when I run it on Windows 2003 Server, the code runs without any errors but the page height and width are not applied to the printer. Could anyone please help me?
int SetPrintedPageSize(float width, float height)
{
//Code adapted from Microsoft KB article Q230743
HANDLE hPrinter = NULL; //handle for the current printer
PRINTER_DEFAULTS pd;
PRINTER_INFO_2 pinfo;
DEVMODE dm;
char sPrinterName[10];
char* yDevModeData; //Byte array to hold contents
//of DEVMODE structure
char* yPInfoMemory; //Byte array to hold contents
//of PRINTER_INFO_2 structure
unsigned long iBytesNeeded;
int iRet = 0;
unsigned long iJunk;
//int iCount;
pd.pDatatype = 0;
pd.pDevMode = 0;
memset((void*)&pinfo, 0, sizeof(pinfo));
memset((void*)&dm, 0, sizeof(dm));
//Get the name of the current printer
strcpy(sPrinterName, "PDF995");
pd.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
iRet = ::OpenPrinter(sPrinterName, &hPrinter, &pd);
if(iRet == 0 || hPrinter == 0)
{
WriteToWIPFile("Cannot access current printer");
//Can't access current printer. Bail out doing nothing
goto CLEANUP;
}
//Get the size of the DEVMODE structure to be loaded
iRet = :ocumentProperties(0, hPrinter, sPrinterName, 0, 0, 0);
if(iRet < 0)
{
//Can't access printer properties.
WriteToWIPFile("Cannot access printer properties");
goto CLEANUP;
}
//Make sure the byte array is large enough
//Some printer drivers lie about the size of the DEVMODE structure they
//return, so an extra 100 bytes is provided just in case!
yDevModeData = new char[iRet + 100];
//Load the byte array
iRet = :ocumentProperties(0, hPrinter, sPrinterName,
(DEVMODE*)yDevModeData, 0, DM_OUT_BUFFER );
if(iRet < 0)
{
WriteToWIPFile("Cannot get document properties");
goto CLEANUP;
}
//Copy the byte array into a structure so it can be manipulated
::CopyMemory(&dm, yDevModeData, sizeof(dm));
//Set the property to the appropriate value
dm.dmPaperLength = height * 254 / 72;
dm.dmPaperWidth = width * 254 / 72;
dm.dmPaperSize = 0;
dm.dmFields = dm.dmFields | DM_PAPERLENGTH | DM_PAPERWIDTH;
//Load the structure back into the byte array
::CopyMemory(yDevModeData, &dm, sizeof(dm));
//Tell the printer about the new property
iRet = :ocumentProperties(0, hPrinter, sPrinterName,
(DEVMODE*)yDevModeData, (DEVMODE*)yDevModeData, DM_IN_BUFFER | DM_OUT_BUFFER);
dm.dmPaperSize = 0;
if(iRet < 0)
{
WriteToWIPFile("Cannot tell the printer about the new property");
goto CLEANUP;
}
//The code above *ought* to be sufficient to set the property
//correctly. Unfortunately some brands of Postscript printer don't
//seem to respond correctly. The following code is used to make
//sure they also respond correctly.
if(!::GetPrinter(hPrinter, 2, 0, 0, &iBytesNeeded))
{
//long error = GetLastError();
WriteToWIPFile(GetLastErrorMessage());
}
if(iBytesNeeded == 0)
{
//Couldn't access shared printer settings
WriteToWIPFile("Cannot access shared printer settings");
goto CLEANUP;
}
//Set byte array large enough for PRINTER_INFO_2 structure
yPInfoMemory = new char[iBytesNeeded + 100];
//Load the PRINTER_INFO_2 structure into byte array
iRet = ::GetPrinter(hPrinter, 2, (unsigned char*)yPInfoMemory, iBytesNeeded, &iJunk);
if (iRet == 0)
{
WriteToWIPFile("Could not load printer info structure");
//Couldn't access shared printer settings
goto CLEANUP;
}
//Copy byte array into the structured type
::CopyMemory(&pinfo, yPInfoMemory, sizeof(pinfo));
//Load the DEVMODE structure with byte array containing
//the new property value
pinfo.pDevMode = &dm;
//Set security descriptor to null
pinfo.pSecurityDescriptor = 0;
//Copy the PRINTER_INFO_2 structure back into byte array
::CopyMemory(yPInfoMemory, &pinfo, sizeof(pinfo));
//Send the new details to the printer
iRet = ::SetPrinter(hPrinter, 2, (unsigned char*)yPInfoMemory, 0);
if(iRet == 0)
WriteToWIPFile("Could not set the printer");
CLEANUP:
//Release the printer handle
if(hPrinter != 0)
::ClosePrinter(hPrinter);
//Indicate whether it all worked or not!
return iRet > 0;
}
The code works perfectly on Windows 2000 Server, but when I run it on Windows 2003 Server, the code runs without any errors but the page height and width are not applied to the printer. Could anyone please help me?