Warum funktioniert Drucken nur ein mal?



  • Habe da einen Fehler den ich nicht finde. Wenn ich meinen Drucken Button betätige, Wird mein Frame ausgedruckt. Wenn ich den Button nochmals betätige, hängt er sich in der if Anweisung auf und bringt eine Speicherverletztung. Aber warum?

    if(pPrintDialog->Execute())
    
    void __fastcall TFormGrundbild::SBDruckenClick(TObject *Sender)
    {
     // Druckdialog dynamisch erzeugen
     TPrintDialog *pPrintDialog1 = new TPrintDialog(this);
    
     // Druckdialog Optionen löschen
     pPrintDialog1->Options.Clear();
    
     // Auf Seite 1 stellen
     pPrintDialog1->FromPage = 1;
    
     // Mindestseiten auf eine stellen
     pPrintDialog1->MinPage = 1;
    
     // Angabe der Bis Seitenzahl aktivieren
     pPrintDialog1->ToPage = 1;
    
     // Drucken bis Maximal Ende Seiten
     pPrintDialog1->MaxPage = 1;
    
     // Printdialog ausgeführt
     if(pPrintDialog1->Execute())   //<<------------------hier hängt er sich beim zweiten mal Drucken auf
        {
         // Drucker dynamisch erzeugen
         TPrinter *pPrinter = Printer();
    
         // Seite festlegen
         TRect r = Rect(0, 0, pPrinter->PageWidth,
                                  pPrinter->PageHeight);
    
         // Druckbereich festlegen
         TRect rSeite = Rect(200, 200, pPrinter->PageWidth - 200,
                                       pPrinter->PageHeight- 200);
    
         // Bitmap erzeugen
         Graphics::TBitmap *Printbmp=new Graphics::TBitmap;
    
         // Breite Frame an Bitmap übergeben
         Printbmp->Width = FormGrundbild->AktuellFrame->Width;
    
         // Höhe Frame an Bitmap übergeben
         Printbmp->Height = FormGrundbild->AktuellFrame->Height;
    
         // Drucktitel
         pPrinter->Title = "Frame";
    
         // Drucker auf Querformat einstellen
         pPrinter->Orientation = poLandscape;
    
         // Druckauftrag beginnen
         pPrinter->BeginDoc();
    
         // Frame in Bitmap zeichnen
         FormGrundbild->AktuellFrame->PaintTo(Printbmp->Canvas,10,10);
    
         // Drucker Rechteck vorgeben
         pPrinter->Canvas->Rectangle(r);
    
         // gestrecktes Bild in Printer übergeben
         pPrinter->Canvas->StretchDraw(rSeite,Printbmp);
    
         // Handle setzen
         pPrinter->Canvas->Handle;
    
         // Dokument beenden
         pPrinter->EndDoc();
    
         // Bitmap löschen
         delete Printbmp;
    
         // Drucker löschen
         delete pPrinter;
        }
    
     // Wenn PrintDialog besteht
     if(pPrintDialog1)
            {
             // Printdialog löschen
             delete pPrintDialog1;
    
             // PrintDialog auf Null setzen
             pPrintDialog1 = NULL;
            }
    }
    


  • Du solltest auch nur das löschen, was dir gehört.

    Und den Drucker zu löschen, ist ganz böse...

    P.S. die letzten Zeilen sind überflüssig, es reicht ein einfaches

    delete pPrintDialog1;
    

    Ich nehme mal an, du fragst demnächst auch mal die Werte aus dem Dialog ab, denn so wäre er ja überflüssig...



  • Jetzt wo du mir das sagst ist das auch einleuchtend, erzeuge ja keinen neuen Drucker, sondern benutze die im System vorhandenen.

    Zur Abfrage des PrintDialogs.
    Ich stelle den PrintDialog auf eine Seite ein. Der Benutzer soll da keine weitere Auswahl haben, außer vielleicht einen anderen Drucker und das Papierfach zu wählen. Alles andere sperre ich.

    Das passt dann schon.

    Danke
    egcactus



  • Wobei du das hier

    // Wenn PrintDialog besteht
     if(pPrintDialog1)
     {
      // Printdialog löschen
      delete pPrintDialog1;
    
      // PrintDialog auf Null setzen
      pPrintDialog1 = NULL;
    }
    

    auch ohne einen Fehler zu machen durch das hier ersetzen kannst

    delete pPrintDialog1;
    

    🙂
    Noch besser wäre es, wenn du dafür einen Smartpointer (hier geht auto_ptr) nimmst. Dann brauchst du gr kein delete.
    Also das hier

    TPrintDialog *pPrintDialog1 = new TPrintDialog(this);
    

    durch das hier ersetzen

    std::auto_ptr<TPrintDialog> pPrintDialog1(new TPrintDialog(0));
    

    und schon ist kein delete mehr nötig.



  • Ok, das funktioniert und nun habe ich eine neue Aufgabe. Erst mal nachlesen, was Autopointer sind und wie und für was man die benutzen kann.

    Danke für die Hilfe.
    Grüße
    egcactus



  • Dann mal was zum Lesen.
    Hier ein Artikel aus dem Magazin über die boost-Smartpointer. auto_ptr wird da kurz erwähnt.
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-134971.html
    über auto_ptr
    http://www.hlrs.de/people/mueller/tutorials/script/scriptse36.html


Anmelden zum Antworten