Die Windows GDI+ (Teil 1)



  • Downloads wurden korrigiert.



  • Moin,

    als erklärter Nicht-Fan von .NET versuche ich ein Semi-Transparentes Fenster mit GDI+ zu erzeugen was auch super funktioniert und echt klasse aussieht mit den richtigen PNGs.
    Allein: bei jedem Aufruf alloziert das Programm einige neue kB die nicht wieder freigegeben werden. Man stelle sich den folgenden Ausschnitt als Hintergrund einer Uhr vor, die sekündlich aktualisiert wird, dann ist der Speicher sehr schnell aufgebraucht.

    CRect crWindow;
    	GetWindowRect( crWindow );
    
    	HDC hdc = ::GetDC( this->GetSafeHwnd() );
    	if( hdc != NULL )
    	{
    		Bitmap *pbmClone = m_bmBackground->Clone( 0, 0, m_bmBackground->GetWidth(), m_bmBackground->GetHeight(), PixelFormatDontCare );
    
    		Graphics gr( pbmClone );
    
    		HBITMAP hbmBack;
    		Color	clrBm;
    		pbmClone->GetHBITMAP( clrBm, &hbmBack );
    		HDC dcMem = ::CreateCompatibleDC( hdc );
    		if( dcMem != NULL )
    		{
    			HBITMAP hbmOld = ( HBITMAP )::SelectObject( dcMem, hbmBack );
    			CPoint	ptZero( 0, 0 );
    			CSize	szWnd( crWindow.Size() );
    			CPoint	ptBase( crWindow.TopLeft() );
    			BLENDFUNCTION blendFunc;
    			blendFunc.AlphaFormat = AC_SRC_ALPHA;
    			blendFunc.BlendFlags = 0;
    			blendFunc.BlendOp = AC_SRC_OVER;
    			blendFunc.SourceConstantAlpha = iAlpha;
    			if( !UpdateLayeredWindow(	this,
    										hdc,
    										&ptBase,
    										&szWnd,
    										dcMem,
    										&ptZero,
    										::GetSysColor( COLOR_3DFACE ),
    										&blendFunc,
    										ULW_ALPHA ) )
    			{
    				MessageBeep( -1 );
    			}
    			::SelectObject( dcMem, hbmOld );
    		}
    		::DeleteDC( dcMem );
    		delete pbmClone;
    		::ReleaseDC( this->GetSafeHwnd(), hdc );
    		::DeleteDC( hdc );
    	}
    

    Was mache ich falsch?

    btw. Gute Einführung! Mehr davon!



  • Moin,

    so still hier auf einmal 😉

    Fehler gefunden und hat nichts mit GDI+ zu tun.

    Ich hätte erwartet, dass eine Methode die den Namen GetHBitmap trägt, mir ein Handle auf den Speicher gibt, der ohnehin benutzt wird. Tut es aber nicht. Die Methode legt ein komplett neues HBITMAP-Objekt im Speicher an, der über DeleteObject(), eine GDI-Funktion, wieder freigegeben werden sollte. Steht nur leider so nicht im MSDN. Schade!

    Ist allerdings als Hinweis irgendwo in der .NET Dokumentation zu GetHBitmap, wo ich es gefunden und ausprobiert habe.

    Viel Spaß noch!



  • Ich hab da noch ne Frage:

    da ich auch noch keine Ahnung habe wollte ich mal Fragen (bevor ich mich einarbeite), ob man das ganze auch auf einem Dialogfenster darstellen kann oder geht das nur auf einem SDI-Editier-Hintergrund?
    Wenn es auf einem Dialogfenster geht: muss man da irgendein Hintergrund einstellen oder kann man nach dem positionieren direkt auf dem grauen Bildschirm schreiben?
    Wenn es nicht geht: womit macht man sowas?

    Micha



  • Geht natürlich auch mit Dialogen. Dialoge sind auch nur Fenster.



  • Also das Zeichnen in einer SDI geht ja, aber bei einem Dialogfeld bzw. in einer MFC-Anwendung gibts noch Probleme:
    In welche Funktion schreib ich denn das rein? Wenn ich LineTo verwende hab ich das gleiche Problem.



  • In dem Artikel ist doch ein MFC-Beispiel als Download bei, einfach da abschauen wie es gemacht wurde.



  • Meinst du das Beispiel auf seite 2? das ist nicht mehr erhältlich.

    Ich hatte mich ungenau ausgedrückt: ich wollte auf einem Dialogfeld (einer MFC Anwendung) zeichnen.
    Wo schriebe ich da meine zeichenbefehle rein?

    Micha



  • Nein, in dem GDI+ Tutorial auf Seite 1 im Text ist eine ZIP Datei zum Download. Da sind Beispiel-Projekte drin.



  • Ich habe zum Thema GDI in WinAPI vor einigen Jahren ein kleines Tutorial geschrieben: http://www.henkessoft.de/C++/WinAPI/WinAPI_GDI/WinAPI_7_GDI.htm
    Das passt vielleicht auch zum Thema hier.



  • GDI != GDI+



  • @Mr X: 👎

    @Erhard Hankes: 👍


Anmelden zum Antworten