2010-03-18 19 views
5

No he escrito nada con GDI desde hace un tiempo (y nunca con GDI +), y estoy trabajando en un proyecto divertido, pero por mi vida, no me puedo imaginar cómo a doble buffer GDI +GDI + doble búfer en 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); 
} 

El anterior funciona (todo se traduce perfectamente), pero parpadea. Si cambio Graphics graphics(hdc); a Graphics graphics(hdcBuffer);, no veo nada (aunque debería estar bitblting el buffer-> hWnd hdc en la parte inferior).

Mi tubería mensaje está configurado correctamente (WM_PAINT llama DrawStuff), y estoy forzando un mensaje WM_PAINT cada bucle de programa llamando RedrawWindow(window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);

Probablemente voy por el camino equivocado para hacer esto, cualquier idea ? La documentación de MSDN es críptica en el mejor de los casos.

Respuesta

6

CreateCompatibleDC(hdc) crea un DC con un mapa de bits monocromático de 1x1 como superficie de dibujo. También necesita CreateCompatibleBitmap y seleccionar ese mapa de bits en el hdcBuffer si desea una superficie de dibujo más grande que eso.

Editar:

el parpadeo está siendo causado por WM_ERASEBKGND, cuando se hace esto

hdc = BeginPaint(hWnd, &ps); 

Dentro de la llamada a BeginPaint, Windows envía su WndProc un mensaje WM_ERASEBKGND si se piensa que el fondo tiene que ser vuelto a dibujar, si no maneja ese mensaje, DefWindowProc lo maneja llenando el rectángulo de pintura con su cepillo de clase, para evitar el parpadeo, debe manejarlo y devolver VERDADERO.

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

de Windows piensa que su fondo debe ser borrado porque lo cuentas que debe ser, eso es lo que RDW_ERASE medios, por lo que probablemente debería dejar eso de la llamada RedrawWindow

+0

Gracias, he añadido hBMP = CreateCompatibleBitmap (HDC, anchura, altura); SelectObject (hdcBuffer, hBmp); al código (y el BitBlt funciona) pero todavía parpadea. –

1

¿Estás manejando WM_ERASEBKGND? Creo que se llama justo antes de WM_PAINT y generalmente modifica el color de fondo de la ventana que probablemente no desee que suceda.

2

puede probar siguiente manera ...

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

Agregue una descripción a su código para una mejor explicación de su solución. estamos aquí para aprender cómo llegar a las respuestas la próxima vez que nos encontremos con este problema, no cómo copiarlos. –

+0

¿Esto no filtrará el pMemBitmap? – Pruyque