Reputation: 12516
Windows 8.1 x64
I have installed PdfCreater virtual printer. It is the default printer (and single) on my computer.
Now I want to get its context:
HDC GetPrinterDC(void)
{
PRINTER_INFO_5 pinfo5[3];
ZeroMemory(pinfo5, sizeof(pinfo5));
DWORD dwNeeded, dwReturned;
if (EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5,
(LPBYTE)pinfo5, sizeof(pinfo5),
&dwNeeded, /* I get 0 */
&dwReturned /* I get 0 */)) {
// And I am here...
return CreateDC(NULL, pinfo5[0].pPrinterName, NULL, NULL); // NULL
}
return 0;
}
But I get NULL
. Why does it happen?
Upvotes: 1
Views: 241
Reputation: 31659
Don't do error check on the result of the first EnumPrinters
(Petzold doesn't do it either)
Note also, the amount of required memory could be several hundred bytes for 1 printer. But PRINTER_INFO_5 pinfo5[1];
may allocate less than that. So you have to allocate what the first EnumPrinters
call tells you.
HDC printerDC = NULL;
DWORD flags = PRINTER_ENUM_LOCAL;// | PRINTER_ENUM_CONNECTIONS;
DWORD memsize, printer_count;
//figure out how much memory we need
EnumPrinters(flags, NULL, 5, NULL, 0, &memsize, &printer_count);
if (memsize < 1) return;
//allocate memory
BYTE* bytes = new BYTE[memsize];
if (EnumPrinters(flags, NULL, 5, bytes, memsize, &memsize, &printer_count))
{
if (printer_count > 0)
{
PRINTER_INFO_5* printerInfo = (PRINTER_INFO_5*)bytes;
printerDC = CreateDC(NULL, printerInfo->pPrinterName, NULL, NULL);
//optional, list printer names
for (UINT i = 0; i < printer_count; i++)
{
OutputDebugString(printerInfo->pPrinterName);
OutputDebugString(L"\n");
printerInfo++;
}
}
}
delete[] bytes;
If you want to access default printer, another option is to use PRINTDLG
(without actually showing any print dialog)
PRINTDLG pdlg;
memset(&pdlg, 0, sizeof(PRINTDLG));
pdlg.lStructSize = sizeof(PRINTDLG);
// Set the flag to return printer DC, but don't show dialog
pdlg.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
PrintDlg(&pdlg);
printerDC = pdlg.hDC;
see also
How To Print a Document
How To: Retrieve a Printer Device Context
Upvotes: 3