Bildanzeige mit OnPaint funktioniert nur begrenzt oft



  • Zunächst schonmal vielen Dank für die schnelle Antwort!
    Ich habe das direkt mal ausprobiert, nur leider ist es mir nicht klar, an welcher Stelle ich das Bitmap-Handle freigeben kann. Eigentlich dachte ich, dass nachdem die Daten mittels BitBlt-Methode an den Bildschirm gegeben wurde, das Handle gelöscht werden kann. Füge ich jedoch als letzte Zeile

    DeleteObject(hBild);
    

    ein, so funktioniert die Darstellung überhaupt nicht mehr. Das bringt mich zu folgenden Fragen:

    1. Kann ich nachdem ich das Handle mit DeleteObject() gelöscht habe, überhaupt nochmal ein Bitmap-Handle mit diesem Namen erstellen, bzw. würde das mit dem Aufruf
    hBild = CreateBitmap( 1024, 768, nPlanes, nBitsPerPixel, Bildarray);
    

    auch gemacht werden?

    1. Kann ich DeleteObject() auch aus einer anderen Methode der entsprechenden Klasse aufrufen?

    2. Kann ich 2) gegebenenfalls ausführen, bevor es überhaupt ein solches Handle gibt, d.h. ich würde das Handle "provisorisch" in einer anderen Methode freigeben, ohne zu wissen, ob das Handle schon erzeugt wurde?

    😕

    Nochmals vielen Dank und beste Grüße!



  • Das Bitmap-Handle mußt zumindest so lange gültig sein, wie es verwendet wird. Ich würde (als erstes) darauf verzichten, in jedem Durchlauf einen neuen CDC anzulegen - und dann jeweils das Handle freigeben, das du beim SelectObject() Aufruf zurückbekommen hast:

    //ungetestet - und ohne Gewähr
    hBild = CreateBitmap( 1024, 768, nPlanes, nBitsPerPixel, Bildarray);
    HANDLE hOld = m_point->SelectObject(pCBitmap);
    dc.BitBlt(0,0,1024,768,m_point, 0,0,SRCCOPY);
    DeleteObject(hOld);
    

    Zu deinen Fragen:

    1. ja
    2. ja
    3. bin ich nicht sicher


  • Habe deinen Vorschlag ausprobiert - funktioniert generell, löst aber leider das Problem nicht. Außerdem hab ich im Konstruktor m_point = NULL gesetzt und dann in der OnPaint-Methode folgenden Aufruf gemacht:

    if(m_point==NULL){
    		m_point = new CDC;
    	}
    

    Dies führt zu einem Runtime-Error, ich verstehe aber nicht, wieso...
    Außerdem schlug mir ein Kollege vor, die gesamte Bilddarstellung folgendermaßen zu machen:

    [cpp]void PopUp::OnPaint() 
    {
    	if(m_point==NULL){
    		m_point = new CDC;
    	}
    	m_point->CreateCompatibleDC(pDC);
    
    	if (!bitmapInitialized) {
    		int nBitsPerPixel = dc.GetDeviceCaps(BITSPIXEL);
    		int nPlanes = dc.GetDeviceCaps(PLANES);
    		bitmap.CreateBitmap( 1024, 768, nPlanes, nBitsPerPixel, Bildarray);
    		bitmapInitialized = TRUE;
    		HANDLE hOld = m_point->SelectObject(&bitmap);
    	}
    
    	dc.BitBlt(0,0,1024,768,m_point, 0,0,SRCCOPY);
    
    }[/cpp]
    

    wobei bitmapInitialized als bool im Konstruktor mit FALSE initialisiert wurde. Auch da scheint es an der Abfrage, ob m_point == NULL ist, zu scheitern. bitmap stellt hier ein CBitmap-Objekt dar.

    Ich bitte um Nachsicht mit meiner Unfähigkeit das wahrscheinlich nicht besonders anspruchsvolle Problem zu lösen.
    Dankeschön!


  • Mod

    Der DC wird auch nicht freigegeben.

    Warum erzeugst Du keinen CPaintDC?
    Ohne CPaintDC wird Dein Programm in eine Endlosschleife gehen und nie aufhören das Control zu zeichnen!



  • Danke auch für den letzten Beitrag,
    wie gesagt bin ich leider recht unerfahren, was die Programmierung mit MFC angeht. Könntest du mir vielleicht zeigen, wie das konkret aussähe? Ich habe jetzt wirklich schon viel ausprobiert ohne das Problem zu lösen. Mittlerweile bin ich doch wieder bei der Version angelangt, die ich in meinem ersten Post angegeben habe:

    [cpp]void PopUp::OnPaint() 
    {
    
        CPaintDC dc(this); // device context for painting
    	CDC *pDC = GetDC();
    
    	m_point = new CDC;
    	m_point->CreateCompatibleDC(pDC);
    	CBitmap* pCBitmap = CBitmap::FromHandle(hBild);
    
    	int nBitsPerPixel = dc.GetDeviceCaps(BITSPIXEL);
    	int nPlanes = dc.GetDeviceCaps(PLANES);
    
    	hBild = CreateBitmap( 1024, 768, nPlanes, nBitsPerPixel, Bildarray);
    
    	m_point->SelectObject(pCBitmap);
    
    	dc.BitBlt(0,0,1024,768,m_point, 0,0,SRCCOPY);
    	ReleaseDC(pDC);
    
        ReleaseDC(m_point);
    
    	m_point->DeleteDC();
    
    }[/cpp]
    

    Nun habe ich, wie zu sehen ist, versucht mit:

    ReleaseDC(pDC);
    
    ReleaseDC(m_point);
    
    m_point->DeleteDC();
    

    alles freizugeben, was ich irgendwo reserviere. Außerdem benutze ich nach jeder Anzeige eine Methode, welche

    DeleteObject(hBild)
    

    ausführt. Trotzdem wird nach einigen Durchläufen nur noch der Hintergrund und nicht mehr das richtige Bild angezeigt. Hab ich irgendwo was vergessen, oder mach ich grundsätzlich was falsch? Falls ja, wie geht es richtig, bzw. wo kann ich das genau nachlesen ohne besondere Programmierkenntnisse zu benötigen?
    Besten Dank!



  • Was passiert wenn du

    void PopUp::OnPaint() 
    {
    
        CPaintDC dc(this); // device context for painting
    	CDC *pDC = GetDC();
    
    	CDC m_point;
    	m_point.CreateCompatibleDC(pDC);
    	CBitmap* pCBitmap = CBitmap::FromHandle(hBild);
    
    	int nBitsPerPixel = dc.GetDeviceCaps(BITSPIXEL);
    	int nPlanes = dc.GetDeviceCaps(PLANES);
    
    	hBild = CreateBitmap( 1024, 768, nPlanes, nBitsPerPixel, Bildarray);
    
    	m_point.SelectObject(pCBitmap);
    
    	dc.BitBlt(0,0,1024,768,m_point, 0,0,SRCCOPY);
    	ReleaseDC(pDC);
    
    }
    

    machst?



  • Ich würde es so schreiben (aber nicht im Compiler getestet):

    void PopUp::OnPaint() 
    { 
        CPaintDC dc(this); // device context for painting 
    
        CDC memDC;
        memDC.CreateCompatibleDC(&dc);
    
        int nBitsPerPixel = dc.GetDeviceCaps(BITSPIXEL); 
        int nPlanes = dc.GetDeviceCaps(PLANES); 
    
        CBitmap bitmap;
        bitmap.CreateBitmap( 1024, 768, nPlanes, nBitsPerPixel, Bildarray); 
    
        CBitmap* pOldBitmap = memDC.SelectObject(&bitmap); 
    
        dc.BitBlt(0,0,1024,768, &memDC, 0,0,SRCCOPY); 
    
        memDC.SelectObject(pOldBitmap);
    }
    


  • genau :xmas2:



  • Yippie!

    Tausend Dank! AndyDD, dein Vorschlag lief, behob aber das Problem nicht, trotzdem danke. sri, du bist für heute (bzw. diese Woche) mein persönlicher Held, deine Version funktioniert astrein! 👍

    Vielen Dank an dieser Stelle nochmal an alle, die geholfen haben!
    Eine schöne Woche euch allen.



  • so wie sri hatte ich das auch gemeint. CreateCompatibleDC ist natürlich auf den PaintDC anzuwenden; das hab ich wohl da übersehen 😞


Anmelden zum Antworten