comctl32/button: Implement NM_CUSTOMDRAW for Push Buttons.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=10531
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2019-03-05 15:13:23 +02:00 committed by Alexandre Julliard
parent 74b17a353a
commit 4b85740ebf
1 changed files with 78 additions and 27 deletions

View File

@ -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;
uState = DFCS_BUTTONPUSH;
if (style & BS_FLAT)
uState |= DFCS_MONO;
else if (pushedState)
/* Skip the frame drawing if only focus has changed */
if (action != ODA_FOCUS)
{
if (get_button_type(style) == BS_DEFPUSHBUTTON )
uState |= DFCS_FLAT;
else
uState |= DFCS_PUSHED;
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 (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 );