2010-03-18 15 views
5

Ich habe seit einiger Zeit nichts mehr mit GDI geschrieben (und nie mit GDI +), und ich arbeite gerade an einem lustigen Projekt, aber für das Leben von mir kann ich nicht verstehen heraus, wie Doppelpuffer GDI +GDI + double buffering in C++

void DrawStuff(HWND hWnd) { 
    HDC   hdc; 
    HDC   hdcBuffer; 
    PAINTSTRUCT ps; 
    hdc = BeginPaint(hWnd, &ps); 
    hdcBuffer = CreateCompatibleDC(hdc); 
    Graphics graphics(hdc); 
    graphics.Clear(Color::Black); 

    // drawing stuff, i.e. bunnies: 

    Image bunny(L"bunny.gif"); 
    graphics.DrawImage(&bunny, 0, 0, bunny.GetWidth(), bunny.GetHeight()); 

    BitBlt(hdc, 0,0, WIDTH , HEIGHT, hdcBuffer, 0,0, SRCCOPY); 
    EndPaint(hWnd, &ps); 
} 

Das obige funktioniert (alles perfekt rendert), aber es flackert. Wenn ich Graphics graphics(hdc); zu Graphics graphics(hdcBuffer); ändere, sehe ich nichts (obwohl ich den Puffer-> hWnd hdc unten bittblingt).

Meine Nachricht Pipeline ordnungsgemäß eingerichtet (WM_PAINT ruft DrawStuff), und ich bin gezwungen eine WM_PAINT-Nachricht von jeder Programmschleife rufen RedrawWindow(window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);

Ich bin wahrscheinlich über den falschen Weg, dies zu tun, irgendwelche Ideen ? Die MSDN-Dokumentation ist bestenfalls kryptisch.

Antwort

6

CreateCompatibleDC(hdc) erstellt einen DC mit einer einfarbigen 1x1-Pixel-Bitmap als Zeichnungsoberfläche. Sie müssen auch CreateCompatibleBitmap und wählen Sie diese Bitmap in den hdcBuffer, wenn Sie eine Zeichnungsfläche größer als das wollen.

Edit:

das Flackern von WM_ERASEBKGND verursacht wird, wenn Sie das tun

hdc = BeginPaint(hWnd, &ps); 

Im Inneren der Aufruf von Beginpaint, sendet Windows Ihr WndProc eine WM_ERASEBKGND Nachricht, wenn es der Hintergrund denkt muss sein neu gezeichnet, wenn Sie diese Nachricht nicht behandeln, dann behandelt DefWindowProc sie, indem sie das Paint-Rechteck mit Ihrem Klassenpinsel füllt. Um also das Flackern zu vermeiden, sollten Sie es behandeln und TRUE zurückgeben.

case WM_ERASEBKGND: 
    return TRUE; // tell Windows that we handled it. (but don't actually draw anything) 

Windows-denkt Ihr Hintergrund gelöscht werden soll, weil Sie ihm sagen, dass es sollte, das ist, was RDW_ERASE Mittel, so dass Sie wahrscheinlich, dass aus Ihrem RedrawWindow Anruf

+0

Dank, habe ich HBMP = CreateCompatibleBitmap (hdc, Breite, Höhe); SelectObject (hdcBuffer, hBmp); an den Code (und der BitBlt funktioniert), aber es flackert immer noch. –

1

gehen Sie mit WM_ERASEBKGND verlassen sollten? Ich glaube, es wird direkt vor WM_PAINT aufgerufen und bloggt normalerweise die Hintergrundfarbe des Fensters, die Sie wahrscheinlich nicht passieren wollen.

2

Sie können folgende Art und Weise versuchen ...

void DrawAll(CDC *pDC) 
{ 
    CRect rect; 
    GetClientRect(&rect); 

    Bitmap *pMemBitmap = new Bitmap(rect.Width(), rect.Height()); 

    Graphics* pMemGraphics = Graphics::FromImage(pMemBitmap); 

    Graphics graphics(pDC->m_hDC); 

    // use pMemGraphics do something.... 

    Status status; 
    if ((status = graphics.DrawImage(pMemBitmap, 0, 0)) !=Ok) 
    { 
     //some error 
    } 

    delete pMemGraphics; 
} 
+1

Bitte fügen Sie Ihrem Code eine Beschreibung hinzu, um Ihre Lösung besser zu erklären. Wir sind hier, um zu lernen, wie wir zu den Antworten kommen, wenn wir das nächste Mal auf dieses Problem treffen und nicht, wie wir sie kopieren sollen. –

+0

Wird dies die pMemBitmap nicht ausliefern? – Pruyque