Signed-off-by: Jeff Smith whydoubt@gmail.com --- v2: - Moved tests in with existing static tests. - Quit using macro for shortening CLR_INVALID. - Added const char *'s for common class names in tests. - Created struct for style tests.
dlls/user32/tests/static.c | 191 ++++++++++++++++++++++++++++++++++++- 1 file changed, 189 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/static.c b/dlls/user32/tests/static.c index 0c453d08a67..d42fc757c5d 100644 --- a/dlls/user32/tests/static.c +++ b/dlls/user32/tests/static.c @@ -52,9 +52,14 @@ static void flush_events(void) } }
-static HWND build_static(DWORD style) +static const char *CLS_STATIC = "static"; +static const char *CLS_BUTTON = "button"; + +#define build_static(style) build_child(CLS_STATIC, style) +static HWND build_child(const char *class, DWORD style) { - return CreateWindowA("static", "Test", WS_VISIBLE|WS_CHILD|style, 5, 5, 100, 100, hMainWnd, (HMENU)CTRL_ID, NULL, 0); + return CreateWindowA(class, "Test", WS_VISIBLE|WS_CHILD|style, 5, 5, 100, 100, hMainWnd, + (HMENU)CTRL_ID, NULL, 0); }
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) @@ -189,6 +194,187 @@ static void test_set_image(void) DeleteObject(image); }
+struct color_values +{ + HBRUSH brush; + COLORREF brushcolor; + COLORREF altbrushcolor; + COLORREF pencolor; + COLORREF textcolor; + COLORREF bkcolor; + int bkmode; +}; + +struct user_data +{ + UINT msg_expect; + struct color_values *color_test; +}; + +static LRESULT CALLBACK styles_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + struct user_data *ud = (struct user_data *)GetWindowLongPtrA(hwnd, GWLP_USERDATA); + + if (!ud || !ud->color_test) + return DefWindowProcA(hwnd, msg, wparam, lparam); + + switch (msg) + { + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + ok(msg == ud->msg_expect, "Expected message %#x got %#x\n", msg, ud->msg_expect); + if (msg == ud->msg_expect) + { + HDC hdc = (HDC)wparam; + if (ud->color_test->bkmode) + SetBkMode(hdc, ud->color_test->bkmode); + if (ud->color_test->altbrushcolor != CLR_INVALID) + SetDCBrushColor(hdc, ud->color_test->altbrushcolor); + if (ud->color_test->pencolor != CLR_INVALID) + SetDCPenColor(hdc, ud->color_test->pencolor); + if (ud->color_test->textcolor != CLR_INVALID) + SetTextColor(hdc, ud->color_test->textcolor); + if (ud->color_test->bkcolor != CLR_INVALID) + SetBkColor(hdc, ud->color_test->bkcolor); + + return (LRESULT)ud->color_test->brush; + } + } + + return DefWindowProcA(hwnd, msg, wparam, lparam); +} + +static void test_style_colors(const char *class, int style, POINT *inside, POINT *outside) +{ + struct color_values color_tests[] = + { + /* wndproc will return NULL */ + {NULL, CLR_INVALID, CLR_INVALID, CLR_INVALID, CLR_INVALID, CLR_INVALID}, + /* wndproc will return non-object */ + {(HBRUSH)(COLOR_HIGHLIGHT+1), CLR_INVALID, CLR_INVALID, CLR_INVALID, CLR_INVALID, CLR_INVALID}, + /* wndproc will return object */ + {NULL, RGB(255,0,0), CLR_INVALID, CLR_INVALID, CLR_INVALID, CLR_INVALID}, + {NULL, RGB(255,0,0), CLR_INVALID, CLR_INVALID, CLR_INVALID, CLR_INVALID, TRANSPARENT}, + {NULL, RGB(255,0,0), RGB(0,255,0), RGB(0,0,255), RGB(255,255,0), RGB(255,0,255)}, + {NULL, RGB(255,0,0), RGB(0,255,0), RGB(0,0,255), RGB(255,255,0), RGB(255,0,255), TRANSPARENT}, + }; + struct user_data ud; + COLORREF icolor0, ocolor0; + COLORREF icolor, ocolor; + COLORREF icolor_exp, ocolor_exp; + HWND hChild; + HDC hdc; + int i; + + int is_simple = (class == CLS_STATIC) && (style == SS_SIMPLE); + int is_groupbox = (class == CLS_BUTTON) && (style == BS_GROUPBOX); + int is_pushbutton = (class == CLS_BUTTON) && + (style == BS_PUSHBUTTON || style == BS_DEFPUSHBUTTON || style == BS_USERBUTTON); + + /* Setup child window */ + hChild = build_child(class, style); + SetWindowTextA(hChild, "____"); + ud.msg_expect = is_pushbutton ? WM_CTLCOLORBTN : WM_CTLCOLORSTATIC; + ud.color_test = NULL; + SetWindowLongPtrA(hMainWnd, GWLP_USERDATA, (LONG_PTR)&ud); + + /* Get system colors for child window */ + InvalidateRect(hChild, NULL, FALSE); + UpdateWindow(hChild); + hdc = GetDC(hChild); + icolor0 = GetPixel(hdc, inside->x, inside->y); + ocolor0 = GetPixel(hdc, outside->x, outside->y); + ReleaseDC(hChild, hdc); + + ocolor_exp = (is_simple || is_groupbox) ? RGB(255, 255, 255) : icolor0; + ok(ocolor0 == ocolor_exp, "(%s,%#x) Expected color %#x outside text area, got %#x\n", + class, style, ocolor_exp, ocolor0); + + for (i = 0; i < ARRAY_SIZE(color_tests); i++) + { + /* Update child window with default colors */ + InvalidateRect(hChild, NULL, FALSE); + UpdateWindow(hChild); + + /* Update child window to exercise control color message */ + if (color_tests[i].brushcolor != CLR_INVALID) + color_tests[i].brush = CreateSolidBrush(color_tests[i].brushcolor); + ud.color_test = &color_tests[i]; + InvalidateRect(hChild, NULL, FALSE); + UpdateWindow(hChild); + ud.color_test = NULL; + if (color_tests[i].brushcolor != CLR_INVALID) + DeleteObject(color_tests[i].brush); + + /* Get updated colors for child window */ + hdc = GetDC(hChild); + icolor = GetPixel(hdc, inside->x, inside->y); + ocolor = GetPixel(hdc, outside->x, outside->y); + ReleaseDC(hChild, hdc); + + icolor_exp = + (color_tests[i].brushcolor == CLR_INVALID || is_pushbutton) ? icolor0 : + (is_simple && color_tests[i].bkmode == TRANSPARENT) ? icolor0 : + (color_tests[i].bkmode == TRANSPARENT) ? color_tests[i].brushcolor : + (color_tests[i].bkcolor != CLR_INVALID) ? color_tests[i].bkcolor : + RGB(255, 255, 255); + ocolor_exp = + (color_tests[i].brushcolor == CLR_INVALID || is_pushbutton) ? ocolor0 : + (is_simple || is_groupbox) ? ocolor0 : + color_tests[i].brushcolor; + todo_wine_if(color_tests[i].brush != NULL && color_tests[i].brushcolor == CLR_INVALID && !is_pushbutton) + ok(icolor == icolor_exp, "(%s,%#x,%d) Expected color %#x inside text area, got %#x\n", + class, style, i, icolor_exp, icolor); + todo_wine_if(color_tests[i].brush != NULL && color_tests[i].brushcolor == CLR_INVALID && !is_pushbutton && + !is_simple && !is_groupbox) + ok(ocolor == ocolor_exp, "(%s,%#x,%d) Expected color %#x outside text area, got %#x\n", + class, style, i, ocolor_exp, ocolor); + } + + DestroyWindow(hChild); +} + +static void test_styles(void) +{ + struct { + const char *class; + int style; + /* A point that should always land inside the text area */ + POINT test_point_inside; + /* A point that should always land outside the text area */ + POINT test_point_outside; + } style_tests[] = { + /* Test basic static styles */ + {CLS_STATIC, SS_SIMPLE, {5, 5}, {90, 90}}, + {CLS_STATIC, SS_LEFT, {5, 5}, {90, 90}}, + {CLS_STATIC, SS_RIGHT, {95, 5}, {90, 90}}, + {CLS_STATIC, SS_CENTER, {50, 5}, {90, 90}}, + {CLS_STATIC, SS_LEFTNOWORDWRAP, {5, 5}, {90, 90}}, + /* Test the static area inside push-buttons */ + {CLS_BUTTON, BS_PUSHBUTTON, {50, 50}, {90, 90}}, + {CLS_BUTTON, BS_DEFPUSHBUTTON, {50, 50}, {90, 90}}, + {CLS_BUTTON, BS_USERBUTTON, {50, 50}, {90, 90}}, + /* Test the static area beside checkbox and radio buttons */ + {CLS_BUTTON, BS_CHECKBOX, {25, 50}, {90, 90}}, + {CLS_BUTTON, BS_AUTOCHECKBOX, {25, 50}, {90, 90}}, + {CLS_BUTTON, BS_RADIOBUTTON, {25, 50}, {90, 90}}, + {CLS_BUTTON, BS_AUTORADIOBUTTON, {25, 50}, {90, 90}}, + {CLS_BUTTON, BS_3STATE, {25, 50}, {90, 90}}, + {CLS_BUTTON, BS_AUTO3STATE, {25, 50}, {90, 90}}, + {CLS_BUTTON, BS_GROUPBOX, {20, 5}, {90, 90}}, + }; + int i; + WNDPROC oldwndproc; + + oldwndproc = (WNDPROC)SetWindowLongPtrA(hMainWnd, GWLP_WNDPROC, (LONG_PTR)styles_wndproc); + for (i = 0; i < ARRAY_SIZE(style_tests); i++) + { + test_style_colors(style_tests[i].class, style_tests[i].style, + &style_tests[i].test_point_inside, &style_tests[i].test_point_outside); + } + SetWindowLongPtrA(hMainWnd, GWLP_WNDPROC, (LONG_PTR)oldwndproc); +} + START_TEST(static) { static const char szClassName[] = "testclass"; @@ -222,6 +408,7 @@ START_TEST(static) test_updates(SS_ETCHEDVERT, TODO_COUNT); test_set_text(); test_set_image(); + test_styles();
DestroyWindow(hMainWnd); }
Signed-off-by: Jeff Smith whydoubt@gmail.com --- dlls/user32/button.c | 68 +++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 45 deletions(-)
diff --git a/dlls/user32/button.c b/dlls/user32/button.c index e3af68e0e54..4ff33624a43 100644 --- a/dlls/user32/button.c +++ b/dlls/user32/button.c @@ -177,6 +177,22 @@ static inline WCHAR *get_button_text( HWND hwnd ) return buffer; }
+static HBRUSH BUTTON_BrushSendMessage( HWND hwnd, HDC hDC, UINT message ) +{ + HBRUSH hBrush; + HWND parent; + + parent = GetParent( hwnd ); + if (!parent) + parent = hwnd; + + hBrush = (HBRUSH)SendMessageW( parent, message, (WPARAM)hDC, (LPARAM)hwnd ); + /* Did the app forget to call DefWindowProc ? */ + if (!hBrush) + hBrush = (HBRUSH)DefWindowProcW( parent, message, (WPARAM)hDC, (LPARAM)hwnd ); + return hBrush; +} + /*********************************************************************** * ButtonWndProc_common */ @@ -230,13 +246,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, { HDC hdc = (HDC)wParam; RECT rc; - HBRUSH hBrush; - HWND parent = GetParent(hWnd); - if (!parent) parent = hWnd; - hBrush = (HBRUSH)SendMessageW(parent, WM_CTLCOLORBTN, (WPARAM)hdc, (LPARAM)hWnd); - if (!hBrush) /* did the app forget to call defwindowproc ? */ - hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORBTN, - (WPARAM)hdc, (LPARAM)hWnd); + HBRUSH hBrush = BUTTON_BrushSendMessage( hWnd, hdc, WM_CTLCOLORBTN ); GetClientRect(hWnd, &rc); FillRect(hdc, &rc, hBrush); } @@ -350,21 +360,14 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, if (IsWindowVisible(hWnd)) { HDC hdc = GetDC(hWnd); - HBRUSH hbrush; RECT client, rc; - HWND parent = GetParent(hWnd); UINT message = (btn_type == BS_PUSHBUTTON || btn_type == BS_DEFPUSHBUTTON || btn_type == BS_USERBUTTON || btn_type == BS_OWNERDRAW) ? WM_CTLCOLORBTN : WM_CTLCOLORSTATIC;
- if (!parent) parent = hWnd; - hbrush = (HBRUSH)SendMessageW(parent, message, - (WPARAM)hdc, (LPARAM)hWnd); - if (!hbrush) /* did the app forget to call DefWindowProc ? */ - hbrush = (HBRUSH)DefWindowProcW(parent, message, - (WPARAM)hdc, (LPARAM)hWnd); + HBRUSH hbrush = BUTTON_BrushSendMessage( hWnd, hdc, message );
GetClientRect(hWnd, &client); rc = client; @@ -738,16 +741,13 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) LONG state = get_button_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); BOOL pushedState = (state & BST_PUSHED); - HWND parent; HRGN hrgn;
GetClientRect( hwnd, &rc );
/* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */ if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); - parent = GetParent(hwnd); - if (!parent) parent = hwnd; - SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); + BUTTON_BrushSendMessage( hwnd, hDC, WM_CTLCOLORBTN );
hrgn = set_control_clipping( hDC, &rc );
@@ -827,7 +827,6 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) LONG state = get_button_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); LONG ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); - HWND parent; HRGN hrgn;
if (style & BS_PUSHLIKE) @@ -846,13 +845,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) GetCharWidthW( hDC, '0', '0', &text_offset ); text_offset /= 2;
- parent = GetParent(hwnd); - if (!parent) parent = hwnd; - hBrush = (HBRUSH)SendMessageW(parent, WM_CTLCOLORSTATIC, - (WPARAM)hDC, (LPARAM)hwnd); - if (!hBrush) /* did the app forget to call defwindowproc ? */ - hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, - (WPARAM)hDC, (LPARAM)hwnd ); + hBrush = BUTTON_BrushSendMessage( hwnd, hDC, WM_CTLCOLORSTATIC ); hrgn = set_control_clipping( hDC, &client );
if (style & BS_LEFTTEXT || ex_style & WS_EX_RIGHT) @@ -981,17 +974,11 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action ) UINT dtFlags; TEXTMETRICW tm; LONG style = GetWindowLongW( hwnd, GWL_STYLE ); - HWND parent; HRGN hrgn;
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); /* GroupBox acts like static control, so it sends CTLCOLORSTATIC */ - parent = GetParent(hwnd); - if (!parent) parent = hwnd; - hbr = (HBRUSH)SendMessageW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)hwnd); - if (!hbr) /* did the app forget to call defwindowproc ? */ - hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, - (WPARAM)hDC, (LPARAM)hwnd); + hbr = BUTTON_BrushSendMessage( hwnd, hDC, WM_CTLCOLORSTATIC ); GetClientRect( hwnd, &rc); rcFrame = rc; hrgn = set_control_clipping( hDC, &rc ); @@ -1032,18 +1019,12 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action ) HBRUSH hBrush; HFONT hFont; LONG state = get_button_state( hwnd ); - HWND parent;
GetClientRect( hwnd, &rc);
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
- parent = GetParent(hwnd); - if (!parent) parent = hwnd; - hBrush = (HBRUSH)SendMessageW(parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd); - if (!hBrush) /* did the app forget to call defwindowproc ? */ - hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORBTN, - (WPARAM)hDC, (LPARAM)hwnd); + hBrush = BUTTON_BrushSendMessage( hwnd, hDC, WM_CTLCOLORBTN );
FillRect( hDC, &rc, hBrush ); if (action == ODA_FOCUS || (state & BST_FOCUS)) @@ -1075,7 +1056,6 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) LONG state = get_button_state( hwnd ); DRAWITEMSTRUCT dis; LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID ); - HWND parent; HFONT hFont; HRGN hrgn;
@@ -1092,9 +1072,7 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) GetClientRect( hwnd, &dis.rcItem );
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); - parent = GetParent(hwnd); - if (!parent) parent = hwnd; - SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); + BUTTON_BrushSendMessage( hwnd, hDC, WM_CTLCOLORBTN );
hrgn = set_control_clipping( hDC, &dis.rcItem );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=80683
Your paranoid android.
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout
=== debiant (64 bit WoW report) ===
user32: clipboard.c:1168: Test failed: OpenClipboard failed: 5 clipboard.c:1170: Test failed: EmptyClipboard failed: 1418 clipboard.c:1172: Test failed: CloseClipboard failed: 1418 clipboard.c:1174: Test failed: sequence diff 0 clipboard.c:1017: Test failed: wait failed clipboard.c:1174: Test failed: WM_DRAWCLIPBOARD not received clipboard.c:1174: Test failed: WM_CLIPBOARDUPDATE not received clipboard.c:1199: Test failed: WM_DESTROYCLIPBOARD received monitor: Timeout
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=14113 Signed-off-by: Jeff Smith whydoubt@gmail.com --- dlls/user32/button.c | 2 +- dlls/user32/static.c | 3 ++- dlls/user32/tests/static.c | 3 --- 3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/button.c b/dlls/user32/button.c index 4ff33624a43..d6b4d6e5943 100644 --- a/dlls/user32/button.c +++ b/dlls/user32/button.c @@ -188,7 +188,7 @@ static HBRUSH BUTTON_BrushSendMessage( HWND hwnd, HDC hDC, UINT message )
hBrush = (HBRUSH)SendMessageW( parent, message, (WPARAM)hDC, (LPARAM)hwnd ); /* Did the app forget to call DefWindowProc ? */ - if (!hBrush) + if (!hBrush || GetObjectType(hBrush) != OBJ_BRUSH) hBrush = (HBRUSH)DefWindowProcW( parent, message, (WPARAM)hDC, (LPARAM)hwnd ); return hBrush; } diff --git a/dlls/user32/static.c b/dlls/user32/static.c index 72e49e15e8f..f3f3c13fe69 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -293,7 +293,8 @@ static HBRUSH STATIC_SendWmCtlColorStatic(HWND hwnd, HDC hdc) if (!parent) parent = hwnd; hBrush = (HBRUSH) SendMessageW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); - if (!hBrush) /* did the app forget to call DefWindowProc ? */ + /* Did the app forget to call DefWindowProc ? */ + if (!hBrush || GetObjectType(hBrush) != OBJ_BRUSH) { /* FIXME: DefWindowProc should return different colors if a manifest is present */ diff --git a/dlls/user32/tests/static.c b/dlls/user32/tests/static.c index d42fc757c5d..c3a5486c308 100644 --- a/dlls/user32/tests/static.c +++ b/dlls/user32/tests/static.c @@ -322,11 +322,8 @@ static void test_style_colors(const char *class, int style, POINT *inside, POINT (color_tests[i].brushcolor == CLR_INVALID || is_pushbutton) ? ocolor0 : (is_simple || is_groupbox) ? ocolor0 : color_tests[i].brushcolor; - todo_wine_if(color_tests[i].brush != NULL && color_tests[i].brushcolor == CLR_INVALID && !is_pushbutton) ok(icolor == icolor_exp, "(%s,%#x,%d) Expected color %#x inside text area, got %#x\n", class, style, i, icolor_exp, icolor); - todo_wine_if(color_tests[i].brush != NULL && color_tests[i].brushcolor == CLR_INVALID && !is_pushbutton && - !is_simple && !is_groupbox) ok(ocolor == ocolor_exp, "(%s,%#x,%d) Expected color %#x outside text area, got %#x\n", class, style, i, ocolor_exp, ocolor); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=80684
Your paranoid android.
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout