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 );
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=10531 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
This also fixes WinXP calc when themes are enabled.
dlls/comctl32/button.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c index f9b4368..9cf95a5 100644 --- a/dlls/comctl32/button.c +++ b/dlls/comctl32/button.c @@ -1904,19 +1904,50 @@ static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in HFONT font = infoPtr->font; HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; WCHAR *text = get_button_text(infoPtr); + NMCUSTOMDRAW nmcd; + LRESULT cdrf; + HWND parent;
GetClientRect(infoPtr->hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &textRect); + init_custom_draw(&nmcd, infoPtr, hDC, &bgRect); + + parent = GetParent(infoPtr->hwnd); + if (!parent) parent = infoPtr->hwnd; + + /* Send erase notifications */ + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup;
if (IsThemeBackgroundPartiallyTransparent(theme, BP_PUSHBUTTON, state)) DrawThemeParentBackground(infoPtr->hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, BP_PUSHBUTTON, state, &bgRect, NULL); + + if (cdrf & CDRF_NOTIFYPOSTERASE) + { + nmcd.dwDrawStage = CDDS_POSTERASE; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + + /* Send paint notifications */ + nmcd.dwDrawStage = CDDS_PREPAINT; + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup; + if (text) { - DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, lstrlenW(text), dtFlags, 0, &textRect); + if (!(cdrf & CDRF_DOERASE)) + DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, lstrlenW(text), dtFlags, 0, &textRect); heap_free(text); }
+ if (cdrf & CDRF_NOTIFYPOSTPAINT) + { + nmcd.dwDrawStage = CDDS_POSTPAINT; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + if (cdrf & CDRF_SKIPPOSTPAINT) goto cleanup; + if (focused) { MARGINS margins; @@ -1932,6 +1963,7 @@ static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in DrawFocusRect( hDC, &focusRect ); }
+cleanup: if (hPrevFont) SelectObject(hDC, hPrevFont); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Most of this is indentation change. I took the liberty of fixing formatting also since it's indented already.
dlls/comctl32/button.c | 129 ++++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 46 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c index 9cf95a5..faf8191 100644 --- a/dlls/comctl32/button.c +++ b/dlls/comctl32/button.c @@ -1619,7 +1619,9 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) HBRUSH hBrush; int delta, text_offset, checkBoxWidth, checkBoxHeight; UINT dtFlags; + LRESULT cdrf; HFONT hFont; + NMCUSTOMDRAW nmcd; LONG state = infoPtr->state; LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE ); LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE ); @@ -1660,9 +1662,20 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) rbox.right = checkBoxWidth; }
+ init_custom_draw(&nmcd, infoPtr, hDC, &client); + + /* Send erase notifications */ + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup; + /* Since WM_ERASEBKGND does nothing, first prepare background */ if (action == ODA_SELECT) FillRect( hDC, &rbox, hBrush ); if (action == ODA_DRAWENTIRE) FillRect( hDC, &client, hBrush ); + if (cdrf & CDRF_NOTIFYPOSTERASE) + { + nmcd.dwDrawStage = CDDS_POSTERASE; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + }
/* Draw label */ client = labelRect; @@ -1675,57 +1688,79 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) rbox.bottom = labelRect.bottom; }
+ /* Send paint notifications */ + nmcd.dwDrawStage = CDDS_PREPAINT; + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup; + /* Draw the check-box bitmap */ - if (action == ODA_DRAWENTIRE || action == ODA_SELECT) + if (!(cdrf & CDRF_DOERASE)) { - UINT flags; - - if ((get_button_type(style) == BS_RADIOBUTTON) || - (get_button_type(style) == BS_AUTORADIOBUTTON)) flags = DFCS_BUTTONRADIO; - else if (state & BST_INDETERMINATE) flags = DFCS_BUTTON3STATE; - else flags = DFCS_BUTTONCHECK; - - if (state & (BST_CHECKED | BST_INDETERMINATE)) flags |= DFCS_CHECKED; - if (state & BST_PUSHED) flags |= DFCS_PUSHED; - - if (style & WS_DISABLED) flags |= DFCS_INACTIVE; - - /* rbox must have the correct height */ - delta = rbox.bottom - rbox.top - checkBoxHeight; - - if ((style & BS_VCENTER) == BS_TOP) { - if (delta > 0) { - rbox.bottom = rbox.top + checkBoxHeight; - } else { - rbox.top -= -delta/2 + 1; - rbox.bottom = rbox.top + checkBoxHeight; - } - } else if ((style & BS_VCENTER) == BS_BOTTOM) { - if (delta > 0) { - rbox.top = rbox.bottom - checkBoxHeight; - } else { - rbox.bottom += -delta/2 + 1; - rbox.top = rbox.bottom - checkBoxHeight; - } - } else { /* Default */ - if (delta > 0) { - int ofs = (delta / 2); - rbox.bottom -= ofs + 1; - rbox.top = rbox.bottom - checkBoxHeight; - } else if (delta < 0) { - int ofs = (-delta / 2); - rbox.top -= ofs + 1; - rbox.bottom = rbox.top + checkBoxHeight; - } - } + if (action == ODA_DRAWENTIRE || action == ODA_SELECT) + { + UINT flags;
- DrawFrameControl( hDC, &rbox, DFC_BUTTON, flags ); - } + if ((get_button_type(style) == BS_RADIOBUTTON) || + (get_button_type(style) == BS_AUTORADIOBUTTON)) flags = DFCS_BUTTONRADIO; + else if (state & BST_INDETERMINATE) flags = DFCS_BUTTON3STATE; + else flags = DFCS_BUTTONCHECK;
- if (dtFlags == (UINT)-1L) /* Noting to draw */ - return; + if (state & (BST_CHECKED | BST_INDETERMINATE)) flags |= DFCS_CHECKED; + if (state & BST_PUSHED) flags |= DFCS_PUSHED; + if (style & WS_DISABLED) flags |= DFCS_INACTIVE;
- if (action == ODA_DRAWENTIRE) BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect); + /* rbox must have the correct height */ + delta = rbox.bottom - rbox.top - checkBoxHeight; + + if ((style & BS_VCENTER) == BS_TOP) + { + if (delta > 0) + rbox.bottom = rbox.top + checkBoxHeight; + else + { + rbox.top -= -delta / 2 + 1; + rbox.bottom = rbox.top + checkBoxHeight; + } + } + else if ((style & BS_VCENTER) == BS_BOTTOM) + { + if (delta > 0) + rbox.top = rbox.bottom - checkBoxHeight; + else + { + rbox.bottom += -delta / 2 + 1; + rbox.top = rbox.bottom - checkBoxHeight; + } + } + else /* Default */ + { + if (delta > 0) + { + int ofs = delta / 2; + rbox.bottom -= ofs + 1; + rbox.top = rbox.bottom - checkBoxHeight; + } + else if (delta < 0) + { + int ofs = -delta / 2; + rbox.top -= ofs + 1; + rbox.bottom = rbox.top + checkBoxHeight; + } + } + + DrawFrameControl(hDC, &rbox, DFC_BUTTON, flags); + } + + if (dtFlags != (UINT)-1L) /* Something to draw */ + if (action == ODA_DRAWENTIRE) BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect); + } + + 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;
/* ... and focus */ if (action == ODA_FOCUS || (state & BST_FOCUS)) @@ -1735,6 +1770,8 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) IntersectRect(&labelRect, &labelRect, &client); DrawFocusRect(hDC, &labelRect); } + +cleanup: SelectClipRgn( hDC, hrgn ); if (hrgn) DeleteObject( hrgn ); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/comctl32/button.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c index faf8191..1637e05 100644 --- a/dlls/comctl32/button.c +++ b/dlls/comctl32/button.c @@ -2013,7 +2013,10 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in UINT btn_type = get_button_type( dwStyle ); int part = (btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON) ? BP_RADIOBUTTON : BP_CHECKBOX; WCHAR *text = get_button_text(infoPtr); + NMCUSTOMDRAW nmcd; + LRESULT cdrf; LOGFONTW lf; + HWND parent; BOOL created_font = FALSE;
HRESULT hr = GetThemeFont(theme, hDC, part, state, TMT_FONT, &lf); @@ -2036,6 +2039,7 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
GetClientRect(infoPtr->hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, part, state, &bgRect, &textRect); + init_custom_draw(&nmcd, infoPtr, hDC, &bgRect);
if (dtFlags & DT_SINGLELINE) /* Center the checkbox / radio button to the text. */ bgRect.top = bgRect.top + (textRect.bottom - textRect.top - sz.cy) / 2; @@ -2045,13 +2049,39 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in bgRect.right = bgRect.left + sz.cx; textRect.left = bgRect.right + 6;
- DrawThemeParentBackground(infoPtr->hwnd, hDC, NULL); + parent = GetParent(infoPtr->hwnd); + if (!parent) parent = infoPtr->hwnd;
+ /* Send erase notifications */ + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup; + + DrawThemeParentBackground(infoPtr->hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, part, state, &bgRect, NULL); - if (text) + + if (cdrf & CDRF_NOTIFYPOSTERASE) { + nmcd.dwDrawStage = CDDS_POSTERASE; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + + /* Send paint notifications */ + nmcd.dwDrawStage = CDDS_PREPAINT; + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto cleanup; + + if (!(cdrf & CDRF_DOERASE) && text) DrawThemeText(theme, hDC, part, state, text, lstrlenW(text), dtFlags, 0, &textRect);
+ if (cdrf & CDRF_NOTIFYPOSTPAINT) + { + nmcd.dwDrawStage = CDDS_POSTPAINT; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + if (cdrf & CDRF_SKIPPOSTPAINT) goto cleanup; + + if (text) + { if (focused) { RECT focusRect; @@ -2069,6 +2099,7 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in heap_free(text); }
+cleanup: if (created_font) DeleteObject(font); if (hPrevFont) SelectObject(hDC, hPrevFont); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
The behavior seems odd but it's needed to pass the tests just like Windows does.
dlls/comctl32/button.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c index 1637e05..16b36d4 100644 --- a/dlls/comctl32/button.c +++ b/dlls/comctl32/button.c @@ -37,7 +37,6 @@ * - BN_PAINT * + BN_SETFOCUS: is it OK? * - BN_UNPUSHED/BN_UNHILITE - * - NM_CUSTOMDRAW * * Structures/Macros/Definitions * - NMBCHOTITEM @@ -1864,7 +1863,9 @@ static void UB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) { RECT rc; HBRUSH hBrush; + LRESULT cdrf; HFONT hFont; + NMCUSTOMDRAW nmcd; LONG state = infoPtr->state; HWND parent;
@@ -1878,10 +1879,39 @@ static void UB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action ) if (!hBrush) /* did the app forget to call defwindowproc ? */ hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
+ if (action == ODA_FOCUS || (state & BST_FOCUS)) + { + 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 notify; + } + FillRect( hDC, &rc, hBrush ); if (action == ODA_FOCUS || (state & BST_FOCUS)) - DrawFocusRect( hDC, &rc ); + { + if (cdrf & CDRF_NOTIFYPOSTERASE) + { + nmcd.dwDrawStage = CDDS_POSTERASE; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + + /* Send paint notifications */ + nmcd.dwDrawStage = CDDS_PREPAINT; + cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + if (cdrf & CDRF_SKIPDEFAULT) goto notify; + if (cdrf & CDRF_NOTIFYPOSTPAINT) + { + nmcd.dwDrawStage = CDDS_POSTPAINT; + SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + } + + if (!(cdrf & CDRF_SKIPPOSTPAINT)) + DrawFocusRect( hDC, &rc ); + }
+notify: switch (action) { case ODA_FOCUS:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
It's already invalidated at the end so there's no reason to draw it before that.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/comctl32/button.c | 1 - dlls/comctl32/tests/button.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c index 16b36d4..f7497a1 100644 --- a/dlls/comctl32/button.c +++ b/dlls/comctl32/button.c @@ -770,7 +770,6 @@ static LRESULT CALLBACK BUTTON_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, L case WM_KILLFOCUS: TRACE("WM_KILLFOCUS %p\n",hWnd); infoPtr->state &= ~BST_FOCUS; - paint_button( infoPtr, btn_type, ODA_FOCUS );
if ((infoPtr->state & BUTTON_BTNPRESSED) && GetCapture() == hWnd) ReleaseCapture(); diff --git a/dlls/comctl32/tests/button.c b/dlls/comctl32/tests/button.c index ce673af..753aa24 100644 --- a/dlls/comctl32/tests/button.c +++ b/dlls/comctl32/tests/button.c @@ -600,11 +600,10 @@ static void test_button_messages(void) while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", todo);
- todo = button[i].style == BS_OWNERDRAW; SetFocus(0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); - ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", todo); + ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", FALSE); ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
v2: Turns out some Windows configurations paint custom draw twice with different DCs, so ignore all except the first batch, should be more robust than marking the messages optional. This isn't necessarily reliant on Windows version, because my local VM did not exhibit the same behavior as the testbot on the same Win version.
dlls/comctl32/tests/button.c | 244 ++++++++++++++++++++++++++++++++--- 1 file changed, 226 insertions(+), 18 deletions(-)
diff --git a/dlls/comctl32/tests/button.c b/dlls/comctl32/tests/button.c index 753aa24..adbf2dd 100644 --- a/dlls/comctl32/tests/button.c +++ b/dlls/comctl32/tests/button.c @@ -39,8 +39,9 @@ static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST); /****************** button message test *************************/ #define ID_BUTTON 0x000e
-#define COMBINED_SEQ_INDEX 0 -#define NUM_MSG_SEQUENCES 1 +#define COMBINED_SEQ_INDEX 0 +#define PARENT_CD_SEQ_INDEX 1 +#define NUM_MSG_SEQUENCES 2
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
@@ -152,11 +153,39 @@ static LRESULT CALLBACK button_subclass_proc(HWND hwnd, UINT message, WPARAM wPa return ret; }
+static struct +{ + DWORD button; + UINT line; + UINT state; + DWORD ret; + BOOL empty; +} test_cd; + +#define set_test_cd_state(s) do { \ + test_cd.state = (s); \ + test_cd.empty = TRUE; \ + test_cd.line = __LINE__; \ +} while (0) + +#define set_test_cd_ret(r) do { \ + test_cd.ret = (r); \ + test_cd.empty = TRUE; \ + test_cd.line = __LINE__; \ +} while (0) + +static void disable_test_cd(void) +{ + test_cd.line = 0; +} + static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; static LONG beginpaint_counter = 0; + static HDC cd_first_hdc; struct message msg = { 0 }; + NMCUSTOMDRAW *cd = (NMCUSTOMDRAW*)lParam; LRESULT ret;
if (ignore_message( message )) return 0; @@ -176,6 +205,53 @@ static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam add_message(sequences, COMBINED_SEQ_INDEX, &msg); }
+ if (message == WM_NOTIFY && cd->hdr.code == NM_CUSTOMDRAW && test_cd.line) + { + /* Ignore an inconsistency across Windows versions */ + UINT state = cd->uItemState & ~CDIS_SHOWKEYBOARDCUES; + + /* Some Windows configurations paint twice with different DC */ + if (test_cd.empty) + { + cd_first_hdc = cd->hdc; + test_cd.empty = FALSE; + } + + ok_(__FILE__,test_cd.line)(!(cd->dwDrawStage & CDDS_ITEM), + "[%u] CDDS_ITEM is set\n", test_cd.button); + + ok_(__FILE__,test_cd.line)(state == test_cd.state, + "[%u] expected uItemState %u, got %u\n", test_cd.button, + test_cd.state, state); + + msg.message = message; + msg.flags = sent|parent|wparam|lparam|id|custdraw; + msg.wParam = wParam; + msg.lParam = lParam; + msg.id = NM_CUSTOMDRAW; + msg.stage = cd->dwDrawStage; + if (cd->hdc == cd_first_hdc) + add_message(sequences, PARENT_CD_SEQ_INDEX, &msg); + + ret = test_cd.ret; + switch (msg.stage) + { + case CDDS_PREERASE: + ret &= ~CDRF_NOTIFYPOSTPAINT; + cd->dwItemSpec = 0xdeadbeef; + break; + case CDDS_PREPAINT: + ret &= ~CDRF_NOTIFYPOSTERASE; + break; + case CDDS_POSTERASE: + case CDDS_POSTPAINT: + ok_(__FILE__,test_cd.line)(cd->dwItemSpec == 0xdeadbeef, + "[%u] NMCUSTOMDRAW was not shared, stage %u\n", test_cd.button, msg.stage); + break; + } + return ret; + } + if (message == WM_PAINT) { PAINTSTRUCT ps; @@ -453,6 +529,46 @@ static const struct message setcheck_radio_redraw_seq[] = { 0 } };
+static const struct message empty_cd_seq[] = { { 0 } }; + +static const struct message pre_cd_seq[] = +{ + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, + { 0 } +}; + +static const struct message pre_pre_cd_seq[] = +{ + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, + { 0 } +}; + +static const struct message pre_post_pre_cd_seq[] = +{ + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTERASE }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, + { 0 } +}; + +static const struct message pre_pre_post_cd_seq[] = +{ + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, + { 0 } +}; + +static const struct message pre_post_pre_post_cd_seq[] = +{ + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTERASE }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, + { 0 } +}; + static HWND create_button(DWORD style, HWND parent) { HMENU menuid = 0; @@ -471,6 +587,13 @@ static HWND create_button(DWORD style, HWND parent)
static void test_button_messages(void) { + enum cd_seq_type + { + cd_seq_empty, + cd_seq_normal, + cd_seq_optional + }; + static const struct { DWORD style; @@ -481,55 +604,74 @@ static void test_button_messages(void) const struct message *setstate; const struct message *clearstate; const struct message *setcheck; + enum cd_seq_type cd_setfocus_type; + enum cd_seq_type cd_setstyle_type; + enum cd_seq_type cd_setstate_type; + enum cd_seq_type cd_setcheck_type; } button[] = { { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_seq, - setstate_seq, setstate_seq, setcheck_ignored_seq }, + setstate_seq, setstate_seq, setcheck_ignored_seq, + cd_seq_normal, cd_seq_normal, cd_seq_normal, cd_seq_optional }, { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_seq, - setstate_seq, setstate_seq, setcheck_ignored_seq }, + setstate_seq, setstate_seq, setcheck_ignored_seq, + cd_seq_normal, cd_seq_normal, cd_seq_normal, cd_seq_optional }, { BS_CHECKBOX, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, + setstate_static_seq, setstate_static_seq, setcheck_static_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, { BS_AUTOCHECKBOX, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, + setstate_static_seq, setstate_static_seq, setcheck_static_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq }, + setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, { BS_3STATE, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, + setstate_static_seq, setstate_static_seq, setcheck_static_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, { BS_AUTO3STATE, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, + setstate_static_seq, setstate_static_seq, setcheck_static_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, { BS_GROUPBOX, DLGC_STATIC, setfocus_groupbox_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_ignored_seq }, + setstate_static_seq, setstate_static_seq, setcheck_ignored_seq, + cd_seq_empty, cd_seq_empty, cd_seq_empty, cd_seq_empty }, { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_user_seq, - setstate_user_seq, clearstate_seq, setcheck_ignored_seq }, + setstate_user_seq, clearstate_seq, setcheck_ignored_seq, + cd_seq_normal, cd_seq_empty, cd_seq_empty, cd_seq_empty }, { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, - setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq }, + setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, { BS_OWNERDRAW, DLGC_BUTTON, setfocus_ownerdraw_seq, killfocus_ownerdraw_seq, setstyle_ownerdraw_seq, - setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq }, + setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq, + cd_seq_empty, cd_seq_empty, cd_seq_empty, cd_seq_empty }, { BS_SPLITBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON | DLGC_WANTARROWS, setfocus_seq, killfocus_seq, setstyle_seq, - setstate_seq, setstate_seq, setcheck_ignored_seq }, + setstate_seq, setstate_seq, setcheck_ignored_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }, { BS_DEFSPLITBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON | DLGC_WANTARROWS, setfocus_seq, killfocus_seq, setstyle_seq, - setstate_seq, setstate_seq, setcheck_ignored_seq }, + setstate_seq, setstate_seq, setcheck_ignored_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }, { BS_COMMANDLINK, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_seq, - setstate_seq, setstate_seq, setcheck_ignored_seq }, + setstate_seq, setstate_seq, setcheck_ignored_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }, { BS_DEFCOMMANDLINK, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_seq, - setstate_seq, setstate_seq, setcheck_ignored_seq }, + setstate_seq, setstate_seq, setcheck_ignored_seq, + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty } }; LOGFONTA logfont = { 0 }; - const struct message *seq; + const struct message *seq, *cd_seq; HFONT zfont, hfont2; unsigned int i; HWND hwnd, parent; @@ -557,6 +699,11 @@ static void test_button_messages(void) hfont2 = CreateFontIndirectA(&logfont); ok(hfont2 != NULL, "Failed to create Tahoma font\n");
+ #define check_cd_seq(type, context) do { \ + if (button[i].type != cd_seq_optional || !test_cd.empty) \ + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, cd_seq, "[CustomDraw] " context, FALSE); \ + } while(0) + for (i = 0; i < ARRAY_SIZE(button); i++) { HFONT prevfont, hfont; @@ -564,6 +711,7 @@ static void test_button_messages(void) DWORD style, state; HDC hdc;
+ test_cd.button = button[i].style; hwnd = create_button(button[i].style, parent); ok(hwnd != NULL, "Failed to create a button.\n");
@@ -591,7 +739,10 @@ static void test_button_messages(void) SetFocus(0); flush_events(); SetFocus(0); + cd_seq = (button[i].cd_setfocus_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; flush_sequences(sequences, NUM_MSG_SEQUENCES); + set_test_cd_ret(CDRF_DODEFAULT); + set_test_cd_state(CDIS_FOCUS);
todo = button[i].style != BS_OWNERDRAW; ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); @@ -599,18 +750,25 @@ static void test_button_messages(void) SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", todo); + check_cd_seq(cd_setfocus_type, "SetFocus(hwnd)");
+ set_test_cd_state(0); SetFocus(0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", FALSE); + check_cd_seq(cd_setfocus_type, "SetFocus(0)"); ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
+ cd_seq = (button[i].cd_setstyle_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; + set_test_cd_state(0); + SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); todo = button[i].style == BS_OWNERDRAW; ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstyle, "BM_SETSTYLE on a button", todo); + check_cd_seq(cd_setstyle_type, "BM_SETSTYLE");
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); @@ -620,12 +778,15 @@ static void test_button_messages(void) state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0, "expected state 0, got %04x\n", state);
+ cd_seq = (button[i].cd_setstate_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; flush_sequences(sequences, NUM_MSG_SEQUENCES); + set_test_cd_state(CDIS_SELECTED);
SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE); + check_cd_seq(cd_setstate_type, "BM_SETSTATE/TRUE");
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == BST_PUSHED, "expected state 0x0004, got %04x\n", state); @@ -635,11 +796,13 @@ static void test_button_messages(void) ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
flush_sequences(sequences, NUM_MSG_SEQUENCES); + set_test_cd_state(0);
SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE); + check_cd_seq(cd_setstate_type, "BM_SETSTATE/FALSE");
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0, "expected state 0, got %04x\n", state); @@ -651,7 +814,9 @@ static void test_button_messages(void) state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
+ cd_seq = (button[i].cd_setcheck_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; flush_sequences(sequences, NUM_MSG_SEQUENCES); + set_test_cd_state(0);
if (button[i].style == BS_RADIOBUTTON || button[i].style == BS_AUTORADIOBUTTON) @@ -665,6 +830,7 @@ static void test_button_messages(void) SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, seq, "BM_SETCHECK on a button", FALSE); + check_cd_seq(cd_setcheck_type, "BM_SETCHECK");
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); @@ -674,11 +840,13 @@ static void test_button_messages(void) ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
flush_sequences(sequences, NUM_MSG_SEQUENCES); + set_test_cd_state(0);
SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setcheck, "BM_SETCHECK on a button", FALSE); + check_cd_seq(cd_setcheck_type, "BM_SETCHECK");
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); if (button[i].style == BS_PUSHBUTTON || @@ -726,9 +894,49 @@ static void test_button_messages(void)
DeleteDC(hdc);
+ /* Test Custom Draw return values */ + if (button[i].cd_setfocus_type != cd_seq_empty && + broken(button[i].style != BS_USERBUTTON) /* WinXP */) + { + static const struct + { + const char *context; + LRESULT val; + const struct message *seq; + } ret[] = { + { "CDRF_DODEFAULT", CDRF_DODEFAULT, pre_pre_cd_seq }, + { "CDRF_DOERASE", CDRF_DOERASE, pre_pre_cd_seq }, + { "CDRF_SKIPDEFAULT", CDRF_SKIPDEFAULT, pre_cd_seq }, + { "CDRF_SKIPDEFAULT | CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT", + CDRF_SKIPDEFAULT | CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT, pre_cd_seq }, + { "CDRF_NOTIFYPOSTERASE", CDRF_NOTIFYPOSTERASE, pre_post_pre_cd_seq }, + { "CDRF_NOTIFYPOSTPAINT", CDRF_NOTIFYPOSTPAINT, pre_pre_post_cd_seq }, + { "CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT", + CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT, pre_post_pre_post_cd_seq }, + }; + UINT k; + + for (k = 0; k < ARRAY_SIZE(ret); k++) + { + disable_test_cd(); + SetFocus(0); + set_test_cd_ret(ret[k].val); + set_test_cd_state(CDIS_FOCUS); + SetFocus(hwnd); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); + if (button[i].cd_setfocus_type != cd_seq_optional || !test_cd.empty) + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, ret[k].seq, ret[k].context, FALSE); + } + } + + disable_test_cd(); DestroyWindow(hwnd); }
+ #undef check_cd_seq + DeleteObject(hfont2); DestroyWindow(parent);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com