bitmap ausdrucken?



  • das problem liegt einfach darin, dass ich auch noch nie was in ein fenster gezeichnet habe... bin absoluter winapi anfänger und das einzige was ich bisher gemacht habe ist einen string auszudrucken (und das war scho ein großer erfolg als es endlich so geklappt hat wie ich will 😃 )... und zu diesem string möchte ich jetzt gerne noch ein logo ausdrucken...

    wär also lieb wenn ihr mir bisschen nähere beschreibungen/beispielcode geben könntet, oder vielleicht unter welchem punkt ich das in www.msdn.com nachlesen kann...
    dankää 🙂



  • CreateCompatibleDC - LoadImage - SelectObject - BitBlt bzw. StrechBlt o.ä.



  • moon schrieb:

    bin absoluter winapi anfänger und das einzige was ich bisher gemacht habe ist einen string auszudrucken (und das war scho ein großer erfolg als es endlich so geklappt hat wie ich will 😃 )

    geilo, genau das brauche ich!
    könntest du mir bitte den code dafür geben?



  • hier ist mein code um einen string auszudrucken... hoffe er hilft dir weiter 🙂

    //referenz: www.msdn.com
    //GDI=Graphics Device Interface
    
    #include <windows.h> 
    
    //****************************************************************************** 
    //Gerätekontext ermitteln
    
    HDC GetPrinterDC(void) 
    { 
        DWORD                dwNeeded, dwReturned; 
        HDC                  hdc; 
        PRINTER_INFO_4       * pinfo4; 
    
    	//Aufzählungsfunktion um angeschlossene Drucker zu erfassen
    	//EnumPrinters(Druckerobjekt-Typ, Name des Druckers, Informationslevel, Druckerinformation Buffer, Größe des Druckerinformation Buffer, erhaltene oder benötigte Bytes, Anzahl der gezählten Drucker);
    
        EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,NULL,0,&dwNeeded,&dwReturned); 
        pinfo4=(PRINTER_INFO_4*)malloc(dwNeeded); 
        EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,(PBYTE)pinfo4,dwNeeded,&dwNeeded,&dwReturned); 
    
    	//Gerätekontext anlegen
    	//hdc=CreateDC(Name des Treibers, Name des Druckers, ignorieren-immer NULL, Initialisierungsdaten-meist NULL);
        hdc=CreateDC(NULL,pinfo4->pPrinterName,NULL,NULL);			
        free(pinfo4); 
    
        return hdc; 
    } //end GetPrinterDC
    
    //******************************************************************************  
    //Ausgabe
    //Handle des Druckerkontext + Höhe + Breite der Seite werden übergeben
    
    void PageGDICalls(HDC hdcPrn,int cxPage,int cyPage) 
    { 
    	HFONT hFont;
    
    	static TCHAR ausgabetext[]=TEXT("String"); 
    
    	SaveDC(hdcPrn);
    
    	LOGFONT lf;
    
             lf.lfHeight = 400;					// character height in pixels
             lf.lfWidth = 0;					// character width in pixels
             lf.lfEscapement = 2700;            // orientation of next character
             lf.lfOrientation = 2700;            // orientation of first character
             lf.lfWeight = 0;					// normal thickness
             lf.lfItalic = 0;					// not italic characters
             lf.lfUnderline = 0;				// not underlined characters
             lf.lfStrikeOut = 0;				// not strikeout characters
             lf.lfCharSet = 0;					// OEM character set
             lf.lfOutPrecision = 0;				// default output precision
             lf.lfClipPrecision = 0;			// default clipping precision
             lf.lfQuality = 0;					// default scaling quality
             lf.lfPitchAndFamily = 0;			// default pitch, script font family
             lstrcpy(lf.lfFaceName,"script");	// script typeface
             hFont = CreateFontIndirect(&lf);
    
    	SelectObject(hdcPrn,hFont);
    
    	//TextOut(Zugriff auf Gerätekontext, x-Koordinate Startposition, y-Koordinate Startposition, Zeiger auf String der gezeichnet werden soll, Länge des Strings);
        TextOut(hdcPrn,700,700,ausgabetext,lstrlen(ausgabetext));
    
    }//end PageGDICalls
    
    //****************************************************************************** 
    //main
    
    void main() 
    { 
    	HDC GetPrinterDC(void); 
    	void PageGDICalls(HDC,int,int); 
    
    	//eigentlicher Druckauftrag
    
    	//DOCINFO di={Strukturgröße in Byte, Name des auszudruckenden Dokuments/wird in der Drucker-Wartschlange angezeigt)
    	static	DOCINFO di={sizeof(DOCINFO),TEXT("String druckt")}; 
        BOOL	bSuccess=TRUE; 
        HDC		hdcPrn; 
        int		xPage,yPage; 
    
        if(NULL==(hdcPrn=GetPrinterDC())) 
            bSuccess=FALSE; 
    
    	//Höhe und Breite der Druckseite ermitteln (nicht physikalisch, sondern druckbare Zeichenfläche)
        xPage=GetDeviceCaps(hdcPrn,HORZRES); 
        yPage=GetDeviceCaps(hdcPrn,VERTRES); 
    
    	//wenn StartDoc einen positiven Wert liefert (dh. alles ok) wird StartPage aufgerufen
        if(StartDoc(hdcPrn,&di)>0) 
        { 
    		//neue Seite
            if(StartPage(hdcPrn)>0) 
            { 
                PageGDICalls(hdcPrn,xPage,yPage); 
    
                if(EndPage(hdcPrn)>0) 
                        EndDoc(hdcPrn); 
                else 
                    bSuccess=FALSE; 
            } 
        } 
        else 
            bSuccess=FALSE; 
    
        DeleteDC(hdcPrn); 
    
    }//end main
    


  • ich bekomm das nicht hin 😞 ...
    hauptproblem (von vielen problemen) ist im moment, dass ich nicht weiß was ich in loadimage angeben soll...

    HANDLE LoadImage(
    HINSTANCE hinst,
    LPCTSTR lpszName,
    UINT uType,
    int cxDesired,
    int cyDesired,
    UINT fuLoad
    );

    was muss in die einzelnen teile enthalten? ich weiß, ich muss entweder in lpszName eine ressource angeben oder in kombination mit LR_LOADFROMFILE in fuLoad den pfadnamen der datei die ich verwenden will...
    allerdings hab ich keine ahnung wie ich diesen pfad angeben soll... oder wie ich dem programm sagen soll wie er die ressource findet... 😕

    ......beispielcode??



  • moon schrieb:

    was muss in die einzelnen teile enthalten? ich weiß, ich muss entweder in lpszName eine ressource angeben oder in kombination mit LR_LOADFROMFILE in fuLoad den pfadnamen der datei die ich verwenden will...
    allerdings hab ich keine ahnung wie ich diesen pfad angeben soll... oder wie ich dem programm sagen soll wie er die ressource findet...

    Pfad:

    LoadImage(hInstance, "C:\\Mein\\Pfad\\zum\\Bild.bmp", IMAGE_BITMAP, NULL, NULL, LR_DEFAULTSIZE|LR_LOADFROMFILE);
    

    Resource:

    LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAPx), IMAGE_BITMAP, NULL, NULL, LR_DEFAULTSIZE);
    


  • also wenn ich das richtig verstanden hab benutze ich die bitblt methode um das bitmap auszugeben (so eine art textout für bitmaps?)...
    aber was genau muss ich da als destination dc und source dc angeben? destination müsste der drucker sein, aber was ist source??

    BOOL BitBlt(
      HDC hdcDest, // handle to destination DC
      int nXDest,  // x-coord of destination upper-left corner
      int nYDest,  // y-coord of destination upper-left corner
      int nWidth,  // width of destination rectangle
      int nHeight, // height of destination rectangle
      HDC hdcSrc,  // handle to source DC
      int nXSrc,   // x-coordinate of source upper-left corner
      int nYSrc,   // y-coordinate of source upper-left corner
      DWORD dwRop  // raster operation code
    );
    

    meine aktuelle methode um dieses bitmap auszudrucken sieht im moment so aus (bei den formalen parametern im methodenkopf, das was hier überflüssig ist brauch ich nachher noch für text)...
    ich bin mir nicht so ganz sicher was ich mit hInstance anfangen soll... was genau ist das?

    void PageGDICalls(HDC hdcPrn,int cxPage,int cyPage) 
    { 
    	HINSTANCE hInstance;
    
    	HDC hdcMem = CreateCompatibleDC (hdcPrn);
        HBITMAP hBitmap = (HBITMAP)LoadImage(hInstance,"C:\\Dokumente und Einstellungen\\Administrator\\Desktop\\icann-logo.bmp",IMAGE_BITMAP,NULL,NULL,LR_DEFAULTSIZE|LR_LOADFROMFILE);
    
    	BitBlt(
    		hdcPrn, // handle to destination DC
    		0,		// x-coord of destination upper-left corner
    		0,		// y-coord of destination upper-left corner
    		188,	// width of destination rectangle
    		145,	// height of destination rectangle
    		hdcPrn, // handle to source DC
    		0,		// x-coordinate of source upper-left corner
    		0,		// y-coordinate of source upper-left corner
    		SRCCOPY // raster operation code
    	);
    
     SelectObject (hdcMem,hBitmap);
    
    	SaveDC(hdcPrn);
    
    }//end PageGDICalls
    

    is das so in etwa ok oder hab ich wieder seltsame leichtsinnsfehler gemacht? 😃



  • Du musst das Bitmap in einen Memory-DC selektieren - das ist dann der Source-DC
    Also das SelectObject (hdcMem,hBitmap); vor den BitBlt-Aufruf und dann hdcMem als Source-DC angeben 😉



  • moon schrieb:

    ich bin mir nicht so ganz sicher was ich mit hInstance anfangen soll... was genau ist das?

    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
    

    Fällt Dir da was auf?
    hInstance ist eine Art "Programmzähler", der von Windows erhöht wird, sobald Dein Programm gestartet wird. Es "identifiziert" quasi Dein Programm...

    Wenn Du nun bei LoadImage als ersten Parameter hInstance angibst und z. B. ein Bitmap aus einer Resource DEINES Programmes laden willst, "sagst" Du Windows quasi, das die Resource in DEINEM Programm steckt...

    Deshalb legt man sich für gewöhnlich eine globale HINSTANCE-Variable an, damit man jederzeit drauf zugreifen kann.

    Beispiel:

    #include <windows.h>
    
    HINSTANCE MyInstance;
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
    {
        MyInstance = hInstance;
        ...
    }
    

    Du kannst aber die HINSTANCE Deines Programmes jederzeit mit

    MyInstance = (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE);
    

    erfahren. Dazu allerdings brauchst Du einen HWND auf Dein Fenster...

    In Deinem Beispiel ist der Wert von hInstance nahezu egal, da Du das Bitmap eh von der Festplatte lädst...



  • @flenders:
    ein memory dc erzeuge ich durch CreateCompatibleDC. dann lade ich das bitmap aus einer datei und selektiere mit SelectObject das bitmap ins memory dc. danach führe ich BitBlt mit hdcMem als source und hdcPrn als destination aus, richtig?

    aber dann müsste es doch so stimmen? läuft leider nicht. ich bekomme bloß ein leeres blatt ausgedruckt.

    HDC hdcMem = CreateCompatibleDC (hdcPrn);
        HBITMAP hBitmap = (HBITMAP)LoadImage(hInstance,"C:\\Dokumente und Einstellungen\\Administrator\\Desktop\\icann-logo.bmp",IMAGE_BITMAP,NULL,NULL,LR_DEFAULTSIZE|LR_LOADFROMFILE);
    
    	SelectObject (hdcMem,hBitmap);
    
    	BitBlt(
    		hdcPrn, // handle to destination DC
    		0,		// x-coord of destination upper-left corner
    		0,		// y-coord of destination upper-left corner
    		188,	// width of destination rectangle
    		145,	// height of destination rectangle
    		hdcMem, // handle to source DC
    		0,		// x-coordinate of source upper-left corner
    		0,		// y-coordinate of source upper-left corner
    		SRCCOPY // raster operation code
    	);
    


  • hInstance: Handle to an instance of the module that contains the image to be loaded (steht für LoadImage() in der PSDK-Doku)
    Da du aber das Bild gar nicht aus den Resourcen deines Programms lädst, musst Du da statt hInstance einfach NULL schreiben!

    LR_DEFAULTSIZE
    Uses the width or height specified by the system metric values for cursors or icons, if the cxDesired or cyDesired values are set to zero. If this flag is not specified and cxDesired and cyDesired are set to zero, the function uses the actual resource size. If the resource contains multiple images, the function uses the size of the first image

    Das heisst, du kannst und solltest LR_DEFAULTSIZE weglassen 😃

    Und prüf mal den Rückgabewert:

    HBITMAP bmp;
    bmp=(HBITMAP)LoadImage(NULL,"c:\\pfad\\bla.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
    if (bmp)
    {
       OutputDebugString("Bitmap erfolgreich geladen!\n");
    }
    else
    {
       OutputDebugString("Fehler!!\n");
    }
    


  • habe geekys rat befolgt, die änderungen gemacht und den test mal durchgeführt. das bitmap wird richtig geladen... das ist also nicht der fehler (denk ich)... leider ist das ergebnis immer noch eine schneeweiße seite...
    am besten poste ich hier nochmal meinen gesamten code hin...
    immer her mit den tipps, ihr seid die besten 😃 und ich weiß, ich bin ein schwerer fall 🙄

    #include <windows.h> 
    HINSTANCE hInstance; 
    
    //****************************************************************************** 
    //Gerätekontext ermitteln
    
    HDC GetPrinterDC(void) 
    { 
        DWORD                dwNeeded, dwReturned; 
        HDC                  hdc; 
        PRINTER_INFO_4       * pinfo4; 
    
    	//Aufzählungsfunktion um angeschlossene Drucker zu erfassen
    	//EnumPrinters(Druckerobjekt-Typ, Name des Druckers, Informationslevel, Druckerinformation Buffer, Größe des Druckerinformation Buffer, erhaltene oder benötigte Bytes, Anzahl der gezählten Drucker);
    
        EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,NULL,0,&dwNeeded,&dwReturned); 
        pinfo4=(PRINTER_INFO_4*)malloc(dwNeeded); 
        EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,(PBYTE)pinfo4,dwNeeded,&dwNeeded,&dwReturned); 
    
    	//Gerätekontext anlegen
    	//hdc=CreateDC(Name des Treibers, Name des Druckers, ignorieren-immer NULL, Initialisierungsdaten-meist NULL);
        hdc=CreateDC(NULL,pinfo4->pPrinterName,NULL,NULL);			
        free(pinfo4); 
    
        return hdc; 
    } //end GetPrinterDC
    
    //******************************************************************************  
    //Ausgabe
    //Handle des Druckerkontext + Höhe + Breite der Seite werden übergeben
    
    void PageGDICalls(HDC hdcPrn,int cxPage,int cyPage) 
    { 
    
    	HDC hdcMem = CreateCompatibleDC (hdcPrn);
        HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,"C:\\Dokumente und Einstellungen\\Administrator\\Desktop\\icann-logo.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
    
    	SelectObject (hdcMem,hBitmap);
    
    	BitBlt(
    		hdcPrn, // handle to destination DC
    		0,		// x-coord of destination upper-left corner
    		0,		// y-coord of destination upper-left corner
    		188,	// width of destination rectangle
    		145,	// height of destination rectangle
    		hdcMem, // handle to source DC
    		0,		// x-coordinate of source upper-left corner
    		0,		// y-coordinate of source upper-left corner
    		SRCCOPY // raster operation code
    	);
    
    	SaveDC(hdcPrn);
    
    }//end PageGDICalls
    
    //****************************************************************************** 
    //main
    
    void main() 
    { 
    	HDC GetPrinterDC(void); 
    	void PageGDICalls(HDC,int,int); 
    
    	//eigentlicher Druckauftrag
    
    	//DOCINFO di={Strukturgröße in Byte, Name des auszudruckenden Dokuments/wird in der Drucker-Wartschlange angezeigt)
    	static	DOCINFO di={sizeof(DOCINFO),TEXT("GreenCode druckt")}; 
        BOOL	bSuccess=TRUE; 
        HDC		hdcPrn; 
        int		xPage,yPage; 
    
        if(NULL==(hdcPrn=GetPrinterDC())) 
            bSuccess=FALSE; 
    
    	//Höhe und Breite der Druckseite ermitteln (nicht physikalisch, sondern druckbare Zeichenfläche)
        xPage=GetDeviceCaps(hdcPrn,HORZRES); 
        yPage=GetDeviceCaps(hdcPrn,VERTRES); 
    
    	//wenn StartDoc einen positiven Wert liefert (dh. alles ok) wird StartPage aufgerufen
        if(StartDoc(hdcPrn,&di)>0) 
        { 
    		//neue Seite
            if(StartPage(hdcPrn)>0) 
            { 
                PageGDICalls(hdcPrn,xPage,yPage); 
    
                if(EndPage(hdcPrn)>0) 
                        EndDoc(hdcPrn); 
                else 
                    bSuccess=FALSE; 
            } 
        } 
        else 
            bSuccess=FALSE; 
    
        DeleteDC(hdcPrn); 
    
    }//end main
    


  • Ich habe es bei mir gerade mal auspobiert und festgestellt, dass es funktioniert, wenn du CreateCompatibleDC NULL übergibst (anstatt hdcPrn). Außerdem wirst du wohl StrechBlt brauchen, da das Bild sonst winzig klein gedruckt wird 🙂



  • juhuuu, es läuft 🙂 he jungs, zur feier des tages geb ich ne runde aus, was haltet ihr davon 😃



  • Ich bin strikter Anti-Alkoholiker, aber eine große Apfelschorle würd ich schon nehmen 😉



  • Hi Leute ich versuche verzweifelt, das Drucken von Bildern auch hinzubekommen....

    Bei mir fukntioniert es aber einfach nicht!

    void CADS2Dlg::Logos(CDC* dcPrint)
    {
    HDC hdcMem = CreateCompatibleDC (NULL); 
        HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,"E:\\test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); 
    
        SelectObject (hdcMem,hBitmap); 
    
        BitBlt( 
            hdcMem, // handle to destination DC 
            0,        // x-coord of destination upper-left corner 
            0,        // y-coord of destination upper-left corner 
            188,    // width of destination rectangle 
            145,    // height of destination rectangle 
            hdcMem, // handle to source DC 
            0,        // x-coordinate of source upper-left corner 
            0,        // y-coordinate of source upper-left corner 
            SRCCOPY // raster operation code 
        ); 
    
        SaveDC(hdcMem); 
    
    }
    

    Mein Problem ist, dass ich ein CDC-Obejkt habe....
    Wie kann ich dann den Code auf meine Druckmethode anpassen?
    z.B Text drucke ich so:

    dcPrint->DrawText(...);
    

    Wie kann ich den so Bilder drucken?



  • Dann scheinst du wohl MFC zu verwenden (dafür gibt es ein extra Forum). Ansonsten denke ich, dass du eben bei allen Funktionen, denen hdcMem im ersten Parameter übergeben wird, diese stattdessen über dcPrint-> aufrufst und diesen ersten Parameter weglässt 🙂

    Das war jetzt aber alles nur eine Vermutung - ansonsten solltest du im MFC-Forum mal nachfragen 🕶



  • Hi,
    wie genau ist das gemeint, bzw wo muss man den Sourcecode so abändern das es funktioniert?

    flenders schrieb:

    Ich habe es bei mir gerade mal auspobiert und festgestellt, dass es funktioniert, wenn du CreateCompatibleDC NULL übergibst (anstatt hdcPrn). Außerdem wirst du wohl StrechBlt brauchen, da das Bild sonst winzig klein gedruckt wird 🙂

    Schonmal THX
    Nys


Anmelden zum Antworten