[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