TCanvas::StretchDraw eine maximale Anzahl an aufrufen?



  • Ich sitze heute seit Stunden an einem Problem, bei dem sowohl ich als auch die Suchfunktion keine Lösung findet.

    void __fastcall TPrinterclass::PAusdruck()
    {
      Printer->Orientation = poLandscape; //Querformat
    
      TDev* dev = Start;  //Datenstruktur, welche Daten enthält, die Ausgedruckt werden soll.
      TRect r;
      r.Top = SEITENABSTAND;  //230 px
      r.Left = SEITENABSTAND;  /230 px
      r.Right = SEITENABSTAND + 1048*6; //Breite der Rect 6288px
      r.Bottom = SEITENABSTAND + 2*15*6; // Höhe der Rect 180px
      Printer->BeginDoc();
      Printer->Canvas->StretchDraw(r,PAusdruckHeader()); //Überschrift des Dokuments
    
      for(int i = 1; i <= Count ; i++) //Count = die Anzahl der eingetragenen Datenstrukturen
      {
        r.Top += 225; //Rect verschieben, damit der nächste Eintrag nicht auf den vorigen gezeichnet wird
        r.Bottom += 225;
        if(r.Bottom > (Printer->PageHeight - 230)) //Wenn das Ende der Seite erreicht ist, dann neue Seite
        {
          Printer->NewPage();
          r.Top = SEITENABSTAND;
          r.Bottom = SEITENABSTAND + 2*15*6;
          Printer->Canvas->StretchDraw(r,PAusdruckHeader());
          r.Top += 225;
          r.Bottom += 225;
        }
        Printer->Canvas->StretchDraw(r,PAusdruckEintrag(dev,i)); // Eintrag zeichnen
        dev = dev->GetPrNach(); //Nächste Datenstruktur
      }
      Printer->EndDoc();
    }
    

    Wenn ich diese Methode aufrufe, dann funktioniert sie für maximal 7 Datenstrukturen perfekt, also für Count < 8;
    Sobald es mehr werden, kommt ein EAccessViolation.

    Wenn ich diese Methode mit dem Debugger durchlaufe, dann wird schon beim ersten Stretchdraw Methodenaufruf ein EAccessViolation erzeugt, egal wie viele Datenstrukturen eingetragen sind.

    Weiß jemand woran das liegt?



  • Hallo

    Der genaue Grund läßt sich für uns gar nicht nachvollziehen, dazu fehlen uns die ganzen Deklarationen (TDev, Start, Count), die Gültigkeit der Instanzen sowie die Auswirkungen der Funktionen (PAusdruckGeader, PAusdruckEintrag, GetPrNach).
    Benutzt weiter den Debugger um vor allem auch die Werte der Zeiger zu überprüfen.

    bis bald
    akari



  • Kann es sein, dass der Debugger die Methode TCanvas::Stretchdraw durcheinander bringt?
    Weil mir fehlt irgendwie noch die Erklärung, warum die Methode mit dem Debugger sofort eine Fehlermeldung gibt, während ohne Debugger diese Methode 8 mal aufgerufen werden kann.

    Das hier ist übrigens die Methode, die für die Überschrift zuständig ist.

    Graphics::TBitmap* __fastcall TPrinterclass::PAusdruckHeader(void)
    {
      Bitmap->Height = 2*6*15;
      Bitmap->Width = 6* 1048;
    
      Bitmap->Canvas->Font->Size = 60;
    
      Bitmap->Canvas->TextOutA(6*Eintrag,-1,"Eintrag");
      Bitmap->Canvas->TextOutA(6*Inventarnummer,-1,"Invnr.");
      Bitmap->Canvas->TextOutA(6*AlteInventarnummer,-1,"Alte Invnr.");
      Bitmap->Canvas->TextOutA(6*Device,-1,"Gerät");
      Bitmap->Canvas->TextOutA(6*Leistung,-1,"Leistung");
      Bitmap->Canvas->TextOutA(6*Spannung,-1,"Spannung");
      Bitmap->Canvas->TextOutA(6*Hersteller,-1,"Hersteller");
      Bitmap->Canvas->TextOutA(0,90,"Barcode:");
      Bitmap->Canvas->TextOutA(6*Barcode1,90,"Barcode1");
      Bitmap->Canvas->TextOutA(6*Barcode2,90,"Barcode2");
      Bitmap->Canvas->TextOutA(6*Barcode3,90,"Barcode3");
      Bitmap->Canvas->TextOutA(6*Barcode4,90,"Barcode4");
    
      return Bitmap;
    }
    

    Dies ist in der Klasse bei privat definiert.

    Graphics::TBitmap* __fastcall PAusdruckEintrag(TDev* ADev, int AID);
    Graphics::TBitmap* __fastcall PAusdruckHeader(void);
    Graphics::TBitmap* Bitmap;
    


  • Tobi3000 schrieb:

    Weil mir fehlt irgendwie noch die Erklärung, warum die Methode mit dem Debugger sofort eine Fehlermeldung gibt, während ohne Debugger diese Methode 8 mal aufgerufen werden kann.

    Möglicherweise verursacht der Debugger im Zuge der Auswertung der lokalen Variablen die AV.

    In welcher Zeile und bei welcher Instruktion (das siehst du in der Disassembler-Ansicht, die du mit Strg+Alt+C öffnen kannst) erhältst du die AV?



  • Ich habe gestern Abend noch herausgefunden, dass der Fehler bei TPrinter liegen muss.
    Ich habe alle TPrinter::TCanvas::Stretchdraw mit TImage::TCanvas::Stretchdraw ersetzt und meine TImage zeigt das Bild korrekt an, egal wie oft ich TCanvas::Stretchdraw aufrufe.(Bis zum Bildende natürlich nur)
    Die TImage hatte ebenfalls die Größe des Druckformulars.

    void __fastcall TPrinterclass::PAusdruck()
    {
      Printer->Orientation = poLandscape;
    
      TRect r,s;
      s.Left = 0;
      s.Top = 0;
      s.Right = 6826;
      s.Bottom = 4800;
      DruckDlg->Image1->Canvas->Brush->Color = clWhite;
      DruckDlg->Image1->Canvas->FillRect(s);
      TDev* dev = Start;
      r.Top = SEITENABSTAND;
      r.Left = SEITENABSTAND;
      r.Right = SEITENABSTAND + 1048*6;
      r.Bottom = SEITENABSTAND + 2*15*6;
    
      //Printer->BeginDoc();
      //Printer->Canvas->StretchDraw(r,PAusdruckHeader());
      DruckDlg->Image1->Canvas->StretchDraw(r,PAusdruckHeader());
    
      for(int i = 1; i <= Count ; i++)
      {
        r.Top += 225;
        r.Bottom += 225;
        if(r.Bottom > (Printer->PageHeight - 230))
        {
          //Printer->NewPage();
          r.Top = SEITENABSTAND;
          r.Bottom = SEITENABSTAND + 2*15*6;
          //Printer->Canvas->StretchDraw(r,PAusdruckHeader());
          r.Top += 225;
          r.Bottom += 225;
        }
        //Printer->Canvas->StretchDraw(r,PAusdruckEintrag(dev,i));
        DruckDlg->Image1->Canvas->StretchDraw(r,PAusdruckEintrag(dev,i));
        dev = dev->GetPrNach();
      }
      //Printer->EndDoc();
      DruckDlg->Show();
    }
    

    Kann man daraus schließen, dass der Fehler bei TPrinter liegt?

    @Audacia: Ich habe jetzt mal geguckt, wo dieser Fehler kommt.
    Einmal mit Draw und einmal mit Stretchdraw.

    http://home.arcor.de/ricetigers/TCanvas-Draw.jpg
    http://home.arcor.de/ricetigers/TCanvas-Stretchdraw.jpg

    Ich komme bis maximal der markierten Zeile, danach kommt die Fehlermeldung.



  • Bietet die VCL denn wenigstens eine andere Möglichkeit Grafiken auszudrucken?

    Wenn ich bei google nach weiteren libs suche, dann finde ich nur Eier legende Vollmilch Säue für 200 Euro.



  • Tobi3000 schrieb:

    Dies ist in der Klasse bei privat definiert.

    Graphics::TBitmap* __fastcall PAusdruckEintrag(TDev* ADev, int AID);
    Graphics::TBitmap* __fastcall PAusdruckHeader(void);
    Graphics::TBitmap* Bitmap;
    

    Und das Objekt Bitmap ist ganz sicher richtig konstruiert? Was sagt CodeGuard, wenn du ihn aktivierst?

    Ansonsten wäre zur weiteren Diagnose das Einzelschritt-Debugging in der Implementation von StretchDraw hilfreich. Dazu sollte es ab C++Builder 2006 ausreichen, die Laufzeit-Packages zu deaktivieren (in C++Builder <=6 mußt du zusätzlich unter Projekt|Optionen...|Linker die Option "Mit Debug-Bibliotheken" aktivieren.



  • Na da gehe ich mal von aus.

    Bitmap = new Graphics::TBitmap();
    Printer = new TPrinter();
    

    TPrinter gibt auch völlig unabhängig von Bitmap die Fehlermeldung.
    Ist ja nicht nur StretchDraw, sondern FillRect, Draw, Textout, also das sämtliche TPrinter::TCanvas Spektrum scheint verbuggt zu sein.

    Wenn ich die Debug-Libs aktiviere, dann zeigt mir der Debugger an dieser Stelle die Fehlermeldung.

    function AbortProc(Prn: HDC; Error: Integer): Bool; stdcall;
    begin
      Application.ProcessMessages;
      Result := not FPrinter.Aborted;
    end;
    

    Oder was meinst du jetzt mit Einzelschritt-Debugging?



  • Schau dir mal das Beispiel zur Verwendung von TPrinter in der BCB-Hilfe an, da steht irgendwie nichts von "new TPrinter()". Aus der BCB-Hilfe zum Construktor von TPrinter:

    BCB-Hilfe schrieb:

    Die Methode TPrinter erstellt eine Instanz von TPrinter.

    __fastcall TPrinter(void);

    Beschreibung

    Rufen Sie TPrinter nicht direkt auf. Die Methode wird automatisch von der Funktion Printer aufgerufen. TPrinter reserviert Speicherplatz für den Drucker und ruft den Konstruktor der übergeordneten Klasse auf, bevor der korrekte Treiber, der Drucker und die Schnittstelle eingestellt wird.



  • Genau das ist die Lösung!
    Wenn ich diese Funktion aus der Borland-Hilfe benutze, dann funktioniert das Drucken perfekt.
    Ich bedanke mich dann für eure Hilfe. 🙂


Anmelden zum Antworten