2017-02-17 4 views
-1

Je dois ouvrir la boîte de dialogue Imprimante lorsqu'il n'y a pas de configuration par défaut de l'imprimante Windows. Cela fonctionne bien avec le code ci-dessous lorsqu'une imprimante par défaut Windows est configurée.Erreur "Aucune imprimante par défaut sélectionnée" lorsque l'imprimante par défaut de Windows n'est pas configurée

TPrintDialog *dlgPrint = new TPrintDialog(frmDisplayDetail); 
if(dlgPrint->Execute()) { //code here } 

Mais s'il n'y a pas de configuration de l'imprimante par défaut dans Windows, dlgPrint->Execute() déclenche une exception:

Il n'y a aucune imprimante par défaut sélectionnée

Pour vérifier l'index de l'imprimante par défaut, je Printer()->PrinterIndex. Cette valeur devient inaccessible quand il n'y a pas d'installation d'imprimante Windows:

erreur E2122 appel Fonction terminé par une exception non gérée XXX XXX à l'adresse

Est-ce que je fais quelque chose de mal? S'il vous plaît proposer une solution.

+0

Trop large. Veuillez publier un [MVCE] (http://stackoverflow.com/help/mcve). – tambre

+0

@tambre mis à jour. – Santhosh

Répondre

2

L'exception « Il n'y a aucune imprimante par défaut sélectionnée » est lancée que par la méthode TPrinter::SetToDefaultPrinter(), lorsque:

  • l'API Win32 EnumPrinters() fonction échoue avec un code d'erreur ERROR_INVALID_NAME lors de l'énumération avec le (sans papier) PRINTER_ENUM_DEFAULT drapeau. La liste TPrinter::Printers ne contient pas l'imprimante par défaut. Si EnumPrinters() ci-dessus ne signale pas un périphérique par défaut, la valeur par défaut est interrogée à partir de la fonction Win32 API GetDefaultPrinter() (Delphi/C++ Builder 2009 et versions ultérieures) ou device de la section [windows] de %windir%\win.ini (Delphi/C++ Builder 2007 et avant).

TPrinter::SetToDefaultPrinter() est appelé uniquement par:

  • le getter TPrinter::PrinterIndex si le membre FPrinterIndex est actuellement -1.

  • le paramètre TPrinter::PrinterIndex si le membre FPrinterIndex est actuellement -1 ou si la propriété est définie sur -1.

TPrintDialog::Execute() (qui utilise la fonction API Win32 PrintDlg()) premiers appels TPrinter::GetPrinter() pour obtenir une poignée à l'DEVMODE de l'imprimante sélectionnée, qu'il utilise ensuite pour initialiser la boîte de dialogue (via le champ PRINTDLG::hDevMode). TPrinter::GetPrinter() lit la propriété TPrinter::PrinterIndex, donc s'il n'y a aucune imprimante actuellement sélectionnée et aucune imprimante par défaut, l'exception est levée.Si aucune imprimante par défaut n'est configurée, vous n'avez pas de chance, car vous ne pouvez même pas attribuer à la propriété TPrinter::PrinterIndex la valeur> = 0 car elle appellera d'abord SetToDefaultPrinter() avant de vérifier si la nouvelle valeur correspond au courant. valeur.

TPrinter a une longue histoire d'échec/de panne quand il n'y a pas d'imprimante par défaut configurée dans Windows. Pour contourner ce problème, vous devez appeler directement la fonction Win32 API PrintDlg() à la place. Au moins, vous pouvez appeler manuellement le TPrinter::GetPrinter() (pour obtenir le DEVMODE initial) et l'insérer dans un bloc try/catch pour ignorer les exceptions qu'il peut lancer. Si le résultat du dialogue indique le succès, vous pouvez appeler manuellement TPrinter::SetPrinter() pour affecter les options d'imprimante sélectionnées à TPrinter pour l'impression suivante.

0

Je vérifie l'existence d'imprimantes avant l'utilisation de dialogue:

// check printer interface 
TPrinter *prn = Printer(); 
int pxs,pys,i=0; 
if (prn==NULL)i=1; 
if (prn->Printers==NULL) i=1; 
if (prn->Printers->Count<=0) i=1; 
if (i) return; 
// use dialog 
dlg_print->Options.Clear(); 
dlg_print->Options<<poPrintToFile; 
if (!dlg_print->Execute()) return; 
// print 
prn = Printer(); 
pxs=prn->PageWidth; 
pys=prn->PageHeight; 
prn->BeginDoc(); 
for (i=0;i<dlg_print->Copies;i++) 
    { 
    if (i) prn->NewPage(); 
    // here render page into prn->Canvas as image in resolution pxs,pys 
    } 
prn->EndDoc(); 

dlg_print est mon dialogue placé sur le formulaire.

+0

Je vérifie l'imprimante avant d'ouvrir la boîte de dialogue. Dans le code ci-dessus, dlg_print-> Execute() renverra une exception "Il n'y a pas d'imprimante par défaut sélectionnée" lorsqu'il n'y a pas d'imprimante par défaut de Windows sélectionnée. C'est ce que j'ai mentionné. – Santhosh

+0

@Santhosh juste une question idiote mais avez-vous vérifié si 'dlgPrint' n'est pas nul (puisque vous le créez dynamiquement)? où exactement il est dans le code (j'espère pas dans le constructeur de la forme)? – Spektre

+0

Oui, j'ai vérifié. Ce n'est pas nul. Si la propriété Printer() -> PrinterIndex est correctement configurée avec index, dlg-> Execute() fonctionne correctement. Je vérifie les classes d'imprimantes en code PASCAL – Santhosh