[PATCH v2 1/7] comctl32/button: Implement NM_CUSTOMDRAW for Push Buttons
Gabriel Ivăncescu
gabrielopcode at gmail.com
Tue Mar 5 07:13:23 CST 2019
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=10531
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at 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 );
--
2.20.1
More information about the wine-devel
mailing list