Druckproblem: Abbruch mit TPrinter



  • Hallo zusammen,

    ich stehe gerade vor einem kleinen Rätsel...
    Da die Forms ja keine gescheite Druckfunktion haben, bastel ich mir ein Bitmap zusammen, dass ich gerne ausdrucken möchte.
    Mein Druckaufruf sieht so aus:
    (Druckbild ist mein Bitmap)

    if(PrintDialog1->Execute())
    {
       TPrinter* Prntr = Printer(); 
       TRect Rect;
    
       int dpiX = GetDeviceCaps(Prntr->Handle, LOGPIXELSX); // Druckerspez.Aufl.
       int dpiY = GetDeviceCaps(Prntr->Handle, LOGPIXELSY);
    
       Rect.Left = 100;
       Rect.Top = 200;
       Rect.Right = (Rect.Left + Druckbild->Width * dpiX / 105)-100 ;
       Rect.Bottom = (Rect.Top + Druckbild->Height * dpiY / 105)-200 ;
    
       DruckMessageBox->Visible = true;
       DruckMessageBox->SetFocus();
    
       Prntr->BeginDoc();
       Prntr->Canvas->StretchDraw(Rect, Druckbild);//Übergabe BMP an Druckercanvas
       Prntr->EndDoc();
    
       DruckMessageBox->Visible = false;
       SetFocus();
    

    Bei mir funktioniert es auch wunderbar. Auf einigen Produktivrechnern erhält der Drucker zwar Daten schmeisst aber maximal leere Seiten bzw. nur ne Überschrift oder so raus.
    Es sind aber dummerweise überall die gleichen Drucker (es lebe die Monokultur).
    Könnte es evtl. daran liegen, dass EndDoc zu schnell aufgerufen wird und damit versucht den Druck abzuschliessen obwohl der Rechner noch Daten schickt?
    Zur Zeit bin ich echt ratlos. Vielleicht hat einer von euch ne Idee.

    Gruß

    Mike



  • Daran wird es wohl am ehesten liegen, denn du kreierst erst nach dem Aufruf des Druckermenüs deine Datei, aber das sollte man schon vorher machen.



  • lol 😃
    Im PrintDialog stellt man seinen Drucker nebst Auflösung, Papierquali usw ein , wie soll man da vorher was lossenden? Pauschal an alle Drucker die irgenwo im Netzwerk in allen Qualitäten und Formaten sind?

    und @ Mike ich geb dir mal eine alternative Druckfunktion, vieleicht hilft die dir.
    Allerdings hatte ich da genau dasselbe Problem(funktionierte quasi nur auf 3 von 4 Rechnern) und im Forum konnte mir auch nicht so wirklich einer helfen aber vieleicht hast du ja mehr Glück 😛
    Ich hab nachher das Bild in einen CppWebbrowser geladen und dann quasi per IE gedruckt.

    void PRINTER::print_image(Graphics::TBitmap* image)
    {
      TPrinter *p = Printer();
                                          //   ActivXControl   // CreateFile
      // create a memory dc for the image
      HDC h_dc = image->Canvas->Handle;
      int bmp_w = image->Width,
      bmp_h = image->Height;
      HDC h_mem_dc = ::CreateCompatibleDC (h_dc);
      HBITMAP h_mem_bmp = ::CreateCompatibleBitmap (h_dc, bmp_w, bmp_h);
      HBITMAP h_old_bmp = ::SelectObject (h_mem_dc, h_mem_bmp);
    
      // fix up bad video drivers
      bool is_pal_dev = false;
      LOGPALETTE *pal;
      HPALETTE h_pal, h_old_pal;
    
      if (::GetDeviceCaps (image->Canvas->Handle, RASTERCAPS) & RC_PALETTE)
      {
        pal = static_cast<LOGPALETTE*>(malloc (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256)));
        memset (pal, 0, sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256));
        pal->palVersion = 0x300;
        pal->palNumEntries = ::GetSystemPaletteEntries(image->Canvas->Handle, 0, 256, pal->palPalEntry);
        if (pal->palNumEntries != 0)
        {
          h_pal = ::CreatePalette (pal);
          h_old_pal = ::SelectPalette (h_mem_dc, h_pal, false);
          is_pal_dev = true;
        }
        else
        {
          free (pal);
        }
      }
    
        // copy the image on to the memory dc
      ::BitBlt (h_mem_dc, 0, 0, bmp_w, bmp_h, h_dc, 0, 0, SRCCOPY);
    
      if (is_pal_dev)
      {
        ::SelectPalette (h_mem_dc, h_old_pal, false);
        ::DeleteObject (h_pal);
      }
    
        // delete the mem dc
      ::SelectObject (h_mem_dc, h_old_bmp);
      ::DeleteDC (h_mem_dc);
    
        // get memory for a BITMAPIFO Structure
      HANDLE h_bmp_info = ::GlobalAlloc (GHND, sizeof (BITMAPINFO) + (sizeof (RGBQUAD) * 256));
      BITMAPINFO* bmp_info = static_cast<BITMAPINFO*>(::GlobalLock (h_bmp_info));    /*T*/
        //Set up the structure
      memset (bmp_info, NULL, sizeof (BITMAPINFO) + (sizeof (RGBQUAD) * 255));
      bmp_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
      bmp_info->bmiHeader.biPlanes = 1;
      bmp_info->bmiHeader.biBitCount = 8;
      bmp_info->bmiHeader.biWidth = bmp_w;
      bmp_info->bmiHeader.biHeight = bmp_h;
      bmp_info->bmiHeader.biCompression = BI_RGB;
    
      // find out how much memory for the bits
      ::GetDIBits (h_dc, h_mem_bmp, 0, bmp_h, NULL, bmp_info, DIB_RGB_COLORS);
    
      // Allocate memory for the bits
      HANDLE h_bits = GlobalAlloc (GHND, bmp_info->bmiHeader.biSizeImage);
      void *bits = ::GlobalLock (h_bits);
        // this time get the bits
      ::GetDIBits (h_dc, h_mem_bmp, 0, bmp_h, bits, bmp_info, DIB_RGB_COLORS);
    
        // fix up for bad video driver
      if (is_pal_dev)
      {
        for (int i = 0; i < pal->palNumEntries; i++)
        {
          bmp_info->bmiColors[i].rgbRed = pal->palPalEntry[i].peRed;
          bmp_info->bmiColors[i].rgbGreen = pal->palPalEntry[i].peGreen;
          bmp_info->bmiColors[i].rgbBlue = pal->palPalEntry[i].peBlue;
        }
        free (pal);
      }
    
      // begin the printing
      p->BeginDoc ();
             /*
      // scale print size
      int scale_x, scale_y;
      if (p->PageWidth < p->PageHeight)
      {
        scale_x = p->PageWidth;
        scale_y = image->Height * (p->PageWidth / bmp_w);
      }
      else
      {
        scale_x = image->Width * (p->PageHeight / bmp_h);
        scale_y = p->PageHeight;
      }    */
    
      // scale print size
      int scale_x, scale_y;
      if(bmp_w > 0 && bmp_h > 0)
      {
        if (p->PageWidth < p->PageHeight)
        {
          scale_x = p->PageWidth;
          scale_y = image->Height * (p->PageWidth / bmp_w);
        }
        else
        {
          scale_x = image->Width * (p->PageHeight / bmp_h);
          scale_y = p->PageHeight;
        }
      }
      else
      {
         ShowMessage("kein Bild vorhanden");
         return;
      }
    
      // fix up for print with palette
      is_pal_dev = false;
      if (::GetDeviceCaps (h_dc, RASTERCAPS) & RC_PALETTE)
      {
        pal = static_cast<LOGPALETTE*>(malloc (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256)));
        memset (pal, 0, sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256));
        pal->palVersion = 0x300;
        pal->palNumEntries = 256;
        for (int i = 0; pal->palNumEntries; i++)
        {
          pal->palPalEntry[i].peRed = bmp_info->bmiColors[i].rgbRed;
          pal->palPalEntry[i].peGreen = bmp_info->bmiColors[i].rgbGreen;
          pal->palPalEntry[i].peBlue = bmp_info->bmiColors[i].rgbBlue;
        }
        h_pal = CreatePalette(pal);
        free (pal);
        h_old_pal = SelectPalette(p->Canvas->Handle, h_pal, false);
        is_pal_dev = true;
      }
    
        // send the bits to the printer
      StretchDIBits(p->Canvas->Handle, 0, 0, scale_x, scale_y,
      0, 0, bmp_w, bmp_h, bits,bmp_info, DIB_RGB_COLORS, SRCCOPY);
    
        // end the print
      p->EndDoc ();
    
        // clean up
      ::DeleteObject (h_mem_bmp);
      if (is_pal_dev)
      {
        ::SelectObject (p->Canvas->Handle, h_old_pal);
        ::DeleteObject (h_pal);
      }
      ::GlobalUnlock (bits);
      ::GlobalFree (h_bits);
      ::GlobalUnlock (bmp_info);
      ::GlobalFree (h_bmp_info);
    }
    


  • Ach was, sorry, ich meinte nicht die Datei, sondern dein Bild, das kreierst du erst beim Aufruf des Druckermenüs, aber das was zu drucken ist sollte schon vorher festgelegt sein und nicht wärend des Druckmenüs geändert werden.



  • Danke dir dreaddy ich werde mal mein Glück versuchen. 🙂
    Wobei dein Code ja echt übel aussieht für etwas "so normales" wie einen Druck. *hehe*
    Naja mal schaun ob es mit dem IE geht... 🕶

    @Spieleprogrammierer
    Das Bitmap ist bereits vor dem Druckaufruf vorhanden. 🙂
    Aber in das Canvas des Druckers kann ich eben nur im Druckaufruf zeichnen. 😃



  • Über den cppwebbrowser drucken funzt übrigens so:
    (html heisst der webbrowser in den bereits die richtige Seite geladen wurde)

    TVariant vIn, vOut;
      html->ControlInterface->ExecWB(Shdocvw_tlb::OLECMDID_PRINT,
      Shdocvw_tlb::OLECMDEXECOPT_PROMPTUSER, &vIn, &vOut);
    


  • So.. endlich mal registriert....

    *freu*

    Dein Code hat zumindest bei meinen Betatestern gewirkt dreaddy. 🙂
    Beim WebBrowser hab ich leider ein Problem mit den Sicherheitseinstellungen unserer Rechner.... aber wenn es so geht:
    Wunderbar!

    Happy Weekend!



  • Ich glaube das problem liegt woanders. Das bild wärend des druckens zu laden ist schon ok. der drucker druckt sowieso erst wenn er EndDoc() sieht. Vorher sind dann schon ehe alle daten übermittelt. Dein problem könnte an dem Rect liegen. ich glaube er hat manchmal probleme damit. Und weiß nicht wie es weiter gehen soll. Was willst du damit genau bezwecken. Willst du das bild nur auf die richtige größe bringen. wenn ja wieso so kompliziert?



  • So ein ähnliches Problem hatten wir auch mal. Gelöst hatte wir es damit, indem wir nach dem Erzeugen des Quellbitmaps dessen HandleType auf "Device unabhängig" gestellt hatten. Weiss den genauen "Befehl" nicht auswenidg, hab den Builder gerade nicht zur Hand ;). Nach Kopieren des Bitmaps auf den PrinterCanvas kam der Ausdruck wie gewünscht zustande.



  • Das kann auch an den jeweiligen Druckertreibern liegen. Hatte so was mal:

    auf WinNT PC's lief das Drucken 1a.
    Admin macht neuen Service Pack drauf - Aetsch!!!!! :p - nur noch leere Seiten?
    alte Originaltreiber (HP) installiert - geht wieder!

    Laptop mit Win2k und scheinbar gleichem Treiber - KEINE Probleme. 😉

    Die Befehlsfolge ist bei mir gleich! 😉

    PS: der Tip mit "geraeteunabhaengig" klingt gut. Hab' auch schon darauf spekuliert - keine Ahnung wies geht. 😕



  • Konnte gerade nachgucken. Die Eigenschaft ist
    TBitmap::HandleType
    und muß auf
    bmDIB
    gesetzt werden.
    Für weitere Infos -> BCB-Hilfe unter TBitmap



  • @Peter

    Danke! 😉



  • @Blackdragon
    Ich kopiere da einige Form-"Screenshots" zusammen um sie dann auszudrucken.
    Das BMP sieht ja grundsätzlich auch ziemlich gut aus wenn ich es mir mal als Datei wegspeichere. 🙂

    Die Bitmaps geräteunabhängig zu machen ist auch ne ziemlich gute Idee.. nur funktionierte das (zumindest bei zwei meiner internen Betatester) nicht. Die Idee kam mir auch als ich die Hilfefiles durchgesucht habe.

    Wenn es an den Druckertreibern liegt erschiesse ich mich... 😃
    bzw. ich werde von unseren Softwareverteilungs-Admins erschossen..
    Ich glaube ich bau mir noch ein Log ein und zieh die jeweiligen Treiberversionen/SP Vers. in ne DB zum gegenchecken.

    Danke erstmal!


Anmelden zum Antworten