Ownerdraw Code funktioniert, ist er aber auch richtig?
-
Hallo,
habs nun endlich hinbekommen meinem Button komplett selbst zu zeichnen und augenscheinlich funktioniert auch alles, jedoch kenn ich mich mit den Draw Routinen nur sehr bescheiden aus, deshalb meine Frage ist der Code auch "safe" oder kann es zu irgendwelchen Leaks kommen? Also hier der Code:
case WM_DRAWITEM:{ HDC hDC; HBRUSH hBrush; RECT rc, rc_icon, rc_color; UINT state, flag; LPDRAWITEMSTRUCT di; di = (LPDRAWITEMSTRUCT)lParam; state = di->itemState; hDC = GetDC(di->hwndItem); rc = di->rcItem; rc_color = rc_icon = rc; rc_color.left += 6; rc_color.top += 6; rc_color.right -= 17; rc_color.bottom -= 6; rc_icon.left += 5; rc_icon.top += 5; hBrush = CreateSolidBrush(GetSysColor(CTLCOLOR_DLG)); FillRect(hDC, &rc, hBrush); hBrush = CreateSolidBrush(RGB(0, 0, 255)); if(state & ODS_SELECTED){ rc_color.left++; rc_color.top++; rc_color.right++; rc_color.bottom++; rc_icon.left++; rc_icon.top++; flag = EDGE_SUNKEN; }else{ flag = EDGE_RAISED; } DrawEdge(hDC, &rc, flag, BF_RECT); if(state & ODS_FOCUS){ rc.top += 3; rc.left += 3; rc.right -= 3; rc.bottom -= 3; DrawFocusRect(hDC, &rc); } FillRect(hDC, &rc_color, hBrush); DrawIconEx(hDC, rc_icon.left, rc_icon.top, hIcon, 0, 0, 0, 0, DI_NORMAL); ReleaseDC(di->hwndItem, hDC); return 1; }
-
Was Du mit CreateSolidBrush erstellst musst Du auch mit DeleteObject
wieder frei geben.
-
Soweit ich das sehe ist das OK.
Nur es gibt einfachere Funktionen Buttons zu zeichen:
DrawFrameControl
und
DrawThemeBackground (wenn themeing eingeschaltet ist.
-
Der Aufruf von GetDC/ReleaseDC ist eigentlich unnötig, weil der DC schon fertig in DRAWITEMSTRUCT (di->hDC) daherkommt.
-
sri schrieb:
Der Aufruf von GetDC/ReleaseDC ist eigentlich unnötig, weil der DC schon fertig in DRAWITEMSTRUCT (di->hDC) daherkommt.
Wie wahr!
Gut aufgepasst...
Es kann sogar zu Fehlfunktionen führen, denn das List-Ctrl könnte auf die Idee kommen den DC weiter zu nutzen...
-
Ich hab den hDC, also GetDC(...) und ReleaseDC(..), jetzt entfernt. Weiterhin hab ich nach jedem Aufruf von FillRect(...) den Brush mit DeleteObject(...) gelöscht und DrawFrameControl(..) zum Zeichnen des Buttos verwendet. Erwartungsgmäß funktioniert der Code einwandfrei, danke für die Hinweise. Hier nochmal der überarbeitete Code, ich hoffe der ist nun optimal?
void OwnerDraw_ColorButton(LPARAM lParam, COLORREF mycolor){ HBRUSH hBrush; RECT rc_icon, rc_color; LPDRAWITEMSTRUCT di; di = (LPDRAWITEMSTRUCT)lParam; rc_color = rc_icon = di->rcItem; rc_color.left += 6; rc_color.top += 6; rc_color.right -= 17; rc_color.bottom -= 6; rc_icon.left += 5; rc_icon.top += 5; if(di->itemState & ODS_SELECTED){ rc_color.left++; rc_color.top++; rc_color.right++; rc_color.bottom++; rc_icon.left++; rc_icon.top++; DrawFrameControl(di->hDC, &di->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED); }else{ DrawFrameControl(di->hDC, &di->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH); } if(di->itemState & ODS_FOCUS){ di->rcItem.top += 3; di->rcItem.left += 3; di->rcItem.right -= 3; di->rcItem.bottom -= 3; DrawFocusRect(di->hDC, &di->rcItem); } hBrush = CreateSolidBrush(mycolor); FillRect(di->hDC, &rc_color, hBrush); DeleteObject(hBrush); DrawIconEx(di->hDC, rc_icon.left, rc_icon.top, hIcon, 0, 0, 0, 0, DI_NORMAL); }