Problem mit Hintergrundbild in Dialog



  • Hallo, ich habe das folgende Problem:

    Ich möchte hinter meinen Buttons, animierten Gif's usw. ein Bild darstellen. Das funktioniert auch soweit. Das Problem ist, dass ich diese Verknüpfung mit dem Bild nicht in der OnInitDialog()-Funktion aufrufen kann, sondern in der OnPaint()-Funktion. Der Grund dafür ist, dass das entsprechende Bild nach dem Neuzeichnen des Dialoges ja nicht mehr angezeigt wird.

    Nun kommt es aber immer dann zu einem Flackern, wenn beispielsweise ein Hilfetext zu einem Button angezeigt wird.

    Wie kann ich dieses Problem umgehen?
    😕



  • wie machst dus denn,mit CClientDC o mit CPaintDC?



  • Hallo,

    also ich hole mir einen Zeiger auf den Dialog und das entsprechende Handle:

    HWND hWndHintergrundBild = GetSafeHwnd(); // Zeiger auf kompletten Dialog
    HDC hDCHintergrund = ::GetDC(hWndHintergrundBild);
    BildLaden(AktuellesVerzeichnis() + "AutoInstallInfo.jpg"); 
    BildZeichnen(hWndHintergrundBild, hDCHintergrund);
    

    Danach lade ich das Bild dann in den Speicher und zeichne es entsprechend:

    /////////////////////////////////////////////////////////////////////////////
    // Lädt das entsprechende Bild in den Speicher (*.jpg, *.bmp usw.)
    bool BildLaden(LPCTSTR pszFileName)
    {
    	// Datei öffnen
      	HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    
      	if(INVALID_HANDLE_VALUE == hFile) return FALSE;				// Wenn die Datei nicht geöffnet werden konnte, false zurückgeben
    
      	// Dateigröße ermitteln
      	DWORD dwFileSize = GetFileSize(hFile, NULL);
    
      	// Speicher in Größe der Datei allokieren
      	HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);	// Reserviert Speicherplatz auf dem globalen Heap
      	LPVOID  pvData  = GlobalLock(hGlobal);						// Liefert einen Zeiger auf den globalen Speicherblock
    
      	// Datei lesen und im Speicher behalten
      	DWORD dwBytesRead = 0;
      	BOOL  bRead       = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
    
      	if(!bRead) return FALSE;	// Wenn die Datei nicht ausgelesen werden konnte, false zurückgeben
    
      	GlobalUnlock(hGlobal);		// Hebt die Sperre für den angegebenen globalen Speicherblock auf
      	CloseHandle(hFile);			// Schließt das Handle (Verweis) auf das geöffnete Objekt
    
      	// IStream* aus dem Speicher erzeugen
      	LPSTREAM pstm = NULL;
      	HRESULT  hr   = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
    
      	// IPicture vom Bild erzeugen
      	if(Bild) Bild->Release();
    
      	hr = OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)&Bild);
      	pstm->Release();
    
      	// Breite und Höhe vom Bild holen
      	Bild->get_Width(&lLaenge);
      	Bild->get_Height(&lHoehe);
    
      	HDC hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);	// Liefert Informationen über den angegebenen Gerätekontext
    
      	// in Pixel-Einheiten umwandeln
      	iLaenge = (lLaenge  * GetDeviceCaps(hdc, LOGPIXELSX)) / 2540;	// Liefert gerätespezifische Informationen über das angegebene Gerät
      	iHoehe = (lHoehe * GetDeviceCaps(hdc, LOGPIXELSY)) / 2540;
    
      	return TRUE;
    }
    /////////////////////////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////////////////////////
    // Zeigt das entsprechende Bild an
    bool BildZeichnen(HWND hwnd, HDC hdc)
    {
      if(Bild) // Wenn das Bild geladen wurde...
      {
       RECT rc;
       GetClientRect(hwnd, &rc);	// Ermittelt die linke und untere rechte Ecke des Client-Bereichs
    
       // Bild anzeigen mittels Render
       Bild->Render(hdc, 0, 0, iLaenge, iHoehe, 0, lHoehe, lLaenge, -lHoehe, &rc);
    
       return TRUE;
      }
      return FALSE;
    }
    


  • also, ich habs mal so gemacht:

    //in CDlgMain::OnPaint()
    // Hintergrundbitmap setzen:
    //   CClientDC dc2( this ); ...geändert in CPaintDC, weil das Bitmap beim Zurückkehren von anderen Dialogen auf diesen, sich das Bitmap über die Buttons legte
          CPaintDC dc2(this);
          BITMAP bm;
          bgImage.GetObject( sizeof( bm ), &bm );
          CDC SpeicherDC;
          SpeicherDC.CreateCompatibleDC( &dc2 );
          SpeicherDC.SelectObject( &bgImage );
          CRect Rect;
          GetClientRect( &Rect );
          dc2.SetStretchBltMode( HALFTONE );
          dc2.StretchBlt( 0, 0, Rect.right, Rect.bottom, &SpeicherDC,
          0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );
    


  • Na ja, ich habe nicht das Problem, dass die Buttons hinter dem Bild verschwinden, da ich die Button auch in der OnPaint()-Funktion nach dem Bildaufruf immer wieder darstelle und nicht in der OnInitDialog()-Funktion wie mir das lieber wäre.
    Du machst im Prinzip nichts anderes, da du auch die OnPaint()-Funktion nutzt. Jetzt weiß ich nicht, ob ich in der BildLaden- bzw. BildZeichnen-Funktion etwas abändern muss, damit ich dieses Flackern verhindere, wenn der Hilfetext zu dem Button angezeigt wird.

    Es müsste doch eine Möglichkeit existieren, dem Hintergrund des Dialoges das Bild direkt zuzuweisen und nicht bei jedem Neuzeichnen des Bildschirmbereiches immer wieder das Bild und die Buttons neu zu zeichnen, oder?



  • um ehrlich zu sein, hab ich kein problem mit flackernden bildern gehabt, meins war eben das beschriebene.. vielleicht weiss jemand rat, der sich damit schon mal rumgeschlagen hat?



  • Ja trotzdem danke!

    Kann mir echt keiner bei dem Problem helfen? 😕
    Ich denke, es liegt daran dass immer das komplette Bild neu geladen wird. Kann man es nicht irgendwie so ausführen, dass nur der Bereich neu gezeichnet wird, der wirklich neugezeichnet werden muss (beispielsweise, weil ein anderes Fenster über dem Dialog liegt oder der Hilfetext angezeigt wird)?



  • Ich bin's mal wieder...

    Hab jetzt eine andere Klasse genutzt um mein Hintergrundbild direkt auf einem Picture-Object abzubilden. Nun wird das Bild aber immer über den Button dargestellt.

    Wie kann ich den Button über allem anderen darstellen?

    So nach dem Motto "TopButton" bzw. die ZOrder verändern? 😕


Anmelden zum Antworten