[C con Clase] WinApi: Evitar parpadeos al redibujar una ventana

Salvador Pozo salvador en conclase.net
Vie Abr 11 09:48:45 CEST 2008


El pasado 2008-04-10 14:14:18, Gabriel escribió:
 
G> He estado trabajando en una aplicación que comencé luego de leer el curso de WinApi, y mi pregunta es si es posible evitar los parpadeos que se producen en algunos casos cuando la operación de pintado de, por ejemplo, un botón ownerdraw pierde o recupera el foco, es seleccionado, etc.
G> Pensé que quizás es posible realizar la operación de pintado en un DC compatible con el de la ventana y luego "copiar" el contenido de este en el DC que me entrega el mensaje WM_DRAWITEM. ¿Es esto factible? ¿Con qué función puedo hacerlo? (No la he encontrado). ¿Alguna otra forma de solucionarlo?

Hola:

Por supuesto, es posible hacer lo que comentas.

El ejemplo del curso es, tal vez, demasiado sencillo. Pero no quería añadir complicaciones innecesarias. Se pueden hacer botones "owner-draw" usando mapas de bits, o pintando en DC de memoria, y después transferirlos al del botón. De hecho, así es como lo hace el ejemplo de la documentación del API:

LRESULT APIENTRY OwnDrawProc(hDlg, message, wParam, lParam)  
HWND hDlg;      // window handle of dialog box 
UINT message;   // type of message 
UINT wParam;    // message-specific information 
LONG lParam; 
{ 
    HDC hdcMem; 
    LPDRAWITEMSTRUCT lpdis; 
 
    switch (message) { 
        case WM_INITDIALOG: 
            // hinst, hbm1 and hbm2 are defined globally. 
            hbm1 = LoadBitmap((HANDLE) hinst, "OwnBit1"); 
            hbm2 = LoadBitmap((HANDLE) hinst, "OwnBit2"); 
            return TRUE; 
 
        case WM_DRAWITEM: 
            lpdis = (LPDRAWITEMSTRUCT) lParam; 
            hdcMem = CreateCompatibleDC(lpdis->hDC); 
 
            if (lpdis->itemState & ODS_SELECTED)  // if selected 
                SelectObject(hdcMem, hbm2); 
            else 
                SelectObject(hdcMem, hbm1); 
 
            // Destination 
            StretchBlt( 
                lpdis->hDC,         // destination DC 
                lpdis->rcItem.left, // x upper left 
                lpdis->rcItem.top,  // y upper left 
 
                // The next two lines specify the width and 
                // height. 
                lpdis->rcItem.right - lpdis->rcItem.left, 
                lpdis->rcItem.bottom - lpdis->rcItem.top, 
                hdcMem,    // source device context 
                0, 0,      // x and y upper left 
                32,        // source bitmap width 
                32,        // source bitmap height 
                SRCCOPY);  // raster operation 
            DeleteDC(hdcMem); 
            return TRUE; 

         case WM_COMMAND: 
            if (wParam == IDOK 
                || wParam == IDCANCEL) { 
                EndDialog(hDlg, TRUE); 
                return TRUE; 
            } 
            if (HIWORD(wParam) == BN_CLICKED) { 
                switch (LOWORD(wParam)) { 
                    case IDB_OWNERDRAW: 
 
                    . 
                    . // application-defined processing 

                    . 
 
                    break; 
                } 
            } 
            break; 
 
        case WM_DESTROY: 
            DeleteObject(hbm1);  // delete bitmaps 
            DeleteObject(hbm2); 
            break; 
 
    } 
    return FALSE; 
} 

-- 
Salvador Pozo (Administrador)
mailto:salvador en conclase.net


Más información sobre la lista de distribución Cconclase