I need to open the Printer Dialog box when there is no Windows default printer setup. It works fine with the below code when a Windows default printer is set up.
TPrintDialog *dlgPrint = new TPrintDialog(frmDisplayDetail);
if( dlgPrint->Execute()) { //code here }
But if there is no default printer setup in Windows, dlgPrint->Execute()
throws an exception:
There is no default printer selected
To check the default printer index, I used Printer()->PrinterIndex
. This value becomes inaccessible when there is no Windows printer setup:
error E2122 Function call terminated by unhandled exception XXX at address XXX
Am I doing something wrong? Please suggest a solution.
The exception "There is no default printer currently selected" is thrown only by the
TPrinter::SetToDefaultPrinter()
method, when either:the Win32 API
EnumPrinters()
function fails with anERROR_INVALID_NAME
error code when enumerating with the (undocumented)PRINTER_ENUM_DEFAULT
flag.the
TPrinter::Printers
list does not contain the default printer. IfEnumPrinters()
above does not report a default device, the default is then queried from the Win32 APIGetDefaultPrinter()
function (Delphi/C++Builder 2009 and later), or thedevice
value of the[windows]
section of%windir%\win.ini
(Delphi/C++Builder 2007 and earlier).TPrinter::SetToDefaultPrinter()
is called only by:the
TPrinter::PrinterIndex
getter if theFPrinterIndex
member is currently -1.the
TPrinter::PrinterIndex
setter if theFPrinterIndex
member is currently -1, or the property is being set to -1.TPrintDialog::Execute()
(which uses the Win32 APIPrintDlg()
function) first callsTPrinter::GetPrinter()
to get a handle to theDEVMODE
of the currently selected printer, which it then uses to initialize the dialog (via thePRINTDLG::hDevMode
field).TPrinter::GetPrinter()
reads theTPrinter::PrinterIndex
property, so if there is no currently selected printer and no default printer, the exception is thrown.If there is no default printer configured, you are basically out of luck, as you can't even set the
TPrinter::PrinterIndex
property to a value >= 0 since it will first callSetToDefaultPrinter()
before checking if the new value matches the current value.TPrinter
has a long history of failing/crashing when there is no default printer configured in Windows. To work around this, you should call the Win32 APIPrintDlg()
function directly instead. At least then, you can manually callTPrinter::GetPrinter()
(to get the initialDEVMODE
) and wrap it in atry/catch
block to discard any exceptions that it may throw.If the dialog result indicates success, you can manually call
TPrinter::SetPrinter()
to assign the selected printer options toTPrinter
for subsequent printing.I am checking existence of printers before the dialog usage:
where
dlg_print
is my dialog placed on the form.