Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=10531 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/comctl32/button.c | 103 ++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 26 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c index 56a4730..f9b4368 100644 --- a/dlls/comctl32/button.c +++ b/dlls/comctl32/button.c @@ -237,6 +237,28 @@ static inline WCHAR *get_button_text( const BUTTON_INFO *infoPtr ) return buffer; }
+static void init_custom_draw(NMCUSTOMDRAW *nmcd, const BUTTON_INFO *infoPtr, HDC hdc, const RECT *rc) +{ + nmcd->hdr.hwndFrom = infoPtr->hwnd; + nmcd->hdr.idFrom = GetWindowLongPtrW(infoPtr->hwnd, GWLP_ID); + nmcd->hdr.code = NM_CUSTOMDRAW; + nmcd->hdc = hdc; + nmcd->rc = *rc; + nmcd->dwDrawStage = CDDS_PREERASE; + nmcd->dwItemSpec = 0; + nmcd->lItemlParam = 0; + nmcd->uItemState = IsWindowEnabled(infoPtr->hwnd) ? 0 : CDIS_DISABLED; + if (infoPtr->state & BST_PUSHED) nmcd->uItemState |= CDIS_SELECTED; + if (infoPtr->state & BST_FOCUS) nmcd->uItemState |= CDIS_FOCUS; + if (infoPtr->state & BST_HOT) nmcd->uItemState |= CDIS_HOT; + if (infoPtr->state & BST_INDETERMINATE) + nmcd->uItemState |= CDIS_INDETERMINATE; + + /* Windows doesn't seem to send CDIS_CHECKED (it fails the tests) */ + /* CDIS_SHOWKEYBOARDCUES is misleading, as the meaning is reversed */ + /* FIXME: Handle it properly when we support keyboard cues? */ +} + HRGN set_control_clipping( HDC hdc, const RECT *rect ) { RECT rc = *rect; @@ -1476,7 +1498,9 @@ static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) HBRUSH hOldBrush; INT oldBkMode; COLORREF oldTxtColor; + LRESULT cdrf; HFONT hFont; + NMCUSTOMDRAW nmcd; LONG state = infoPtr->state; LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE ); BOOL pushedState = (state & BST_PUSHED); @@ -1498,6 +1522,12 @@ static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) hOldBrush = SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE)); oldBkMode = SetBkMode(hDC, TRANSPARENT);
+ init_custom_draw(&nmcd, infoPtr, hDC, &rc); + + /* Send erase notifications */ + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup; + if (get_button_type(style) == BS_DEFPUSHBUTTON) { if (action != ODA_FOCUS) @@ -1505,44 +1535,65 @@ static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) InflateRect( &rc, -1, -1 ); }
- /* completely skip the drawing if only focus has changed */ - if (action == ODA_FOCUS) goto draw_focus; + /* Skip the frame drawing if only focus has changed */ + if (action != ODA_FOCUS) + { + uState = DFCS_BUTTONPUSH;
- uState = DFCS_BUTTONPUSH; + if (style & BS_FLAT) + uState |= DFCS_MONO; + else if (pushedState) + { + if (get_button_type(style) == BS_DEFPUSHBUTTON ) + uState |= DFCS_FLAT; + else + uState |= DFCS_PUSHED; + }
- if (style & BS_FLAT) - uState |= DFCS_MONO; - else if (pushedState) - { - if (get_button_type(style) == BS_DEFPUSHBUTTON ) - uState |= DFCS_FLAT; - else - uState |= DFCS_PUSHED; + if (state & (BST_CHECKED | BST_INDETERMINATE)) + uState |= DFCS_CHECKED; + + DrawFrameControl( hDC, &rc, DFC_BUTTON, uState ); }
- if (state & (BST_CHECKED | BST_INDETERMINATE)) - uState |= DFCS_CHECKED; + if (cdrf & CDRF_NOTIFYPOSTERASE) + { + nmcd.dwDrawStage = CDDS_POSTERASE; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + }
- DrawFrameControl( hDC, &rc, DFC_BUTTON, uState ); + /* Send paint notifications */ + nmcd.dwDrawStage = CDDS_PREPAINT; + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup;
- /* draw button label */ - labelRect = rc; - /* Shrink label rect at all sides by 2 so that the content won't touch the surrounding frame */ - InflateRect(&labelRect, -2, -2); - dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect); + if (!(cdrf & CDRF_DOERASE) && action != ODA_FOCUS) + { + /* draw button label */ + labelRect = rc; + /* Shrink label rect at all sides by 2 so that the content won't touch the surrounding frame */ + InflateRect(&labelRect, -2, -2); + dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
- if (dtFlags == (UINT)-1L) - goto cleanup; + if (dtFlags != (UINT)-1L) + { + if (pushedState) OffsetRect(&labelRect, 1, 1);
- if (pushedState) OffsetRect(&labelRect, 1, 1); + oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
- oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) ); + BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
- BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect); + SetTextColor( hDC, oldTxtColor ); + } + }
- SetTextColor( hDC, oldTxtColor ); + if (cdrf & CDRF_NOTIFYPOSTPAINT) + { + nmcd.dwDrawStage = CDDS_POSTPAINT; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + if ((cdrf & CDRF_SKIPPOSTPAINT) || dtFlags == (UINT)-1L) goto cleanup;
-draw_focus: if (action == ODA_FOCUS || (state & BST_FOCUS)) { InflateRect( &rc, -2, -2 );