Как работает виртуальный принтер
- Как виртуальный принтер передает информацию клиенскому приложению.
- Как изменить текущую форму страницы.
- Как добавить новую форму страницы нестандартного размера.
- Как изменить ориентацию страницы и качество печати (разрешение).
Как виртуальный принтер передает информацию клиенскому приложению
Клиентское приложение получает информацию от виртуального принтера через INI файл:
Виртуальный принтер -> EMF файлы + INI файл -> Клиентское приложение
В INI файле сохраняется вся информация о работе виртуального принтера.
Пример INI файла:
[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
Режимы передачи пути к INI файлу от виртуального принтера к заданной клиентской программе:
Командная строка
При передаче с помощью командной строки виртуальный принтер запускает указанную ему клиентскоую программу с путем INI файла в виде параметра командной строки.
Самый простой и предпочтительный способ.WM_COPYDATA
Виртуальный принтер запускает указанную программу или ищет уже запущенный экземпляр, и посылает ей путь INI файла посредством сообщения WM_COPYDATA.Буфер обмена
Виртуальный принтер запускает указанную программу или ищет уже запущенный экземпляр, размещает путь INI файла в буфере обмена и отправляет программе нотификацию.
Устаревший метод, предназначен для старых программ.
Как изменить текущую форму страницы
int _iPaperCount = 0;
WORD* _pPapers = NULL;
char* _pPaperNames = NULL;
POINT* _pPaperSizes = NULL;
// функция для просмотра всех доступных форм страницы:
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;
// доступ к формам принтера
_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
{
// отчет об ошибке
}
}
// функция выбора текущей формы страницы:
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
{
// отчет об ошибке
}
delete [] pPrinterInfo;
}
ClosePrinter(hPrinter);
}
else
{
// отчет об ошибке
}
return bResult;
}
Как добавить новую форму страницы нестандартного размера
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();
// установка нового типа страниц
for (int i=0; i<_iPaperCount; i++)
{
if (lstrcmp(_szNewFormName, &_pPaperNames[i*64]) == 0)
{
SetPrinterPaper(_pPapers[i], _szNewFormName);
FillPapers();
break;
}
}
}
else
{
// отчет об ошибке
}
ClosePrinter(hPrinter);
}
Как изменить ориентацию страницы и качество печати (разрешение)
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];
// получение текущих параметров принтера
if (GetPrinter(hPrinter, 2, pPrinterInfo, dwNeeded, &dwNeeded))
{
DEVMODE* pDevMode = ((PRINTER_INFO_2*) pPrinterInfo)->pDevMode;
pDevMode->dmFields = pDevMode->dmFields|DM_ORIENTATION|DM_PRINTQUALITY|DM_YRESOLUTION;
// изменение параметров
pDevMode->dmOrientation = 1; // ориентация страницы: 1-портретная, 2-пейзажная
pDevMode->dmPrintQuality = 300; // значение разрешения по горизонтали
pDevMode->dmYResoultion = 300; // значение разрешения по вертикали
// сохранение измененных установок
if (!SetPrinter(hPrinter, 2, pPrinterInfo, 0))
{
// отчет об ошибке
}
}
else
{
// отчет об ошибке
}
delete [] pPrinterInfo;
}
ClosePrinter(hPrinter);
}
else
{
// отчет об ошибке
}