"How to" articles for Virtual Printer SDK
How to ...
◊ How to get information from printer into your client application
◊ How to change current paper form
◊ How to add new paper form of custom size
◊ How to change paper orientation and print quality (resolution)
How to get information from printer into your client application
After you send your document to the printer, it prepares several EMF files
and a special INI file:
Virtual Printer -> EMF files + INI file -> Clien application
All information about the printer job is stored inside this INI file.
Here is an example INI file contents:
[Device] DeviceName=Your Virtual Printer Example [Document] Name=Lorem Ipsum - All the facts - Lipsum generator JobID=2 MachineName=\\T23 UserName=Stas SessionID=0 HorizontalResolution=300 VerticalResolution=300 Orientation=1 PaperSize=9 PaperSizeName=A4 PaperWidth=2100 PaperLength=2970 Pages=2 Copies=1 Collate=0 Bin=15 BinName=Automatically Select [EMF] Count=2 File0=C:\DOCUME~1\Stas\LOCALS~1\Temp\00020001.emf File1=C:\DOCUME~1\Stas\LOCALS~1\Temp\00020002.emf
(We will use this INI file for our example).
How does your application access this INI file ? Using the command line. (There are other methods, but we’ll use command line because it’s preferred and simplest.).
So, for example, you have in your C# app this main function:
static void Main(string[] args)
The path to the INI file will be in args[0].
How does the virtual printer know where your client application is located ? From the registry. For example, since we are using a printer named "Your Virtual Printer Example", the registry key is
"HKEY_LOCAL_MACHINE\SOFTWARE\Your Virtual Printer Example". Under this registry key are several values which are described in the "Readme.html" file, which comes with the demo printer distribution. The value which used by the virtual printer as a path to the client application is "Client application". Just put the full path to your application into this value and it will be launched by a virtual printer. The full path to the INI file will bу passed in the command line.
How to change current paper form
int _iPaperCount = 0; WORD* _pPapers = NULL; char* _pPaperNames = NULL; POINT* _pPaperSizes = NULL; // Function that enumerates all available paper forms:
void FillPapers() { 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); _pPaperSizes = new POINT[_iPaperCount]; ZeroMemory(_pPaperSizes, sizeof(POINT)*_iPaperCount); DeviceCapabilities(PRINTER_NAME, NULL, DC_PAPERSIZE, (LPSTR) _pPaperSizes, NULL); } ClosePrinter(hPrinter); } else { // report error } } // Function that sets current paper form: BOOL SetPrinterPaper(short dmPaperSize, const char* pszFormName) { BOOL bResult = FALSE; HANDLE hPrinter = NULL; if (OpenPrinter(PRINTER_NAME, &hPrinter, NULL)) { DWORD dwNeeded = 0; GetPrinter(hPrinter, 2, NULL, 0, &dwNeeded); if (dwNeeded > 0) { BYTE* pPrinterInfo = new BYTE[dwNeeded]; if (GetPrinter(hPrinter, 2, pPrinterInfo, dwNeeded, &dwNeeded)) { DEVMODE* pDevMode = ((PRINTER_INFO_2*) pPrinterInfo)->pDevMode; pDevMode->dmPaperSize = dmPaperSize; lstrcpy((char*) &pDevMode->dmFormName, pszFormName); SetPrinter(hPrinter, 2, pPrinterInfo, 0); bResult = TRUE; } else { // report error } delete [] pPrinterInfo; } ClosePrinter(hPrinter); } else { // report error } return bResult; }
How to add new paper form of custom size
if (OpenPrinter(PRINTER_NAME, &hPrinter, NULL))
{
FORM_INFO_1 FormInfo = {0};
FormInfo.pName = (char*) &_szNewFormName;
FormInfo.Size.cx = FormInfo.ImageableArea.right = _iNewFormWidth*1000;
FormInfo.Size.cy = FormInfo.ImageableArea.bottom = _iNewFormLength*1000;
if (AddForm(hPrinter, 1, (BYTE*) &FormInfo))
{
FillPapers();
// set new paper to the printer
for (int i=0; i<_iPaperCount; i++)
{
if (lstrcmp(_szNewFormName, &_pPaperNames[i*64]) == 0)
{
SetPrinterPaper(_pPapers[i], _szNewFormName);
FillPapers();
break;
}
}
}
else
{
// report error
}
ClosePrinter(hPrinter);
}
How to change paper orientation and print quality (resolution)
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS prnDef = { NULL, NULL, PRINTER_ALL_ACCESS };
if (OpenPrinter(PRINTER_NAME, &hPrinter, &prnDef))
{
DWORD dwNeeded = 0;
GetPrinter(hPrinter, 2, NULL, 0, &dwNeeded);
if (dwNeeded > 0)
{
BYTE* pPrinterInfo = new BYTE[dwNeeded];
// get current printer settings
if (GetPrinter(hPrinter, 2, pPrinterInfo, dwNeeded, &dwNeeded))
{
DEVMODE* pDevMode = ((PRINTER_INFO_2*) pPrinterInfo)->pDevMode;
pDevMode->dmFields = pDevMode->dmFields|DM_ORIENTATION|DM_PRINTQUALITY|DM_YRESOLUTION;
// change parameters
pDevMode->dmOrientation = 1; // Orientation: 1 - portrait; 2 - landscape.
pDevMode->dmPrintQuality = 300; // Horizontal resolution value
pDevMode->dmYResoultion = 300; // Vertical resoultion value
// save changed settings
if (!SetPrinter(hPrinter, 2, pPrinterInfo, 0))
{
// report error
}
}
else
{
// report error
}
delete [] pPrinterInfo;
}
ClosePrinter(hPrinter);
}
else
{
// report error
}