Zhiyi Zhang : comctl32/tests: Test that WM_THEMECHANGED should invalidate client area.

Alexandre Julliard julliard at winehq.org
Wed Apr 28 16:18:47 CDT 2021


Module: wine
Branch: master
Commit: a9eaf7a7da2bbca5e2c69481f9a5c14e738144fc
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a9eaf7a7da2bbca5e2c69481f9a5c14e738144fc

Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date:   Tue Apr 27 11:34:51 2021 +0800

comctl32/tests: Test that WM_THEMECHANGED should invalidate client area.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/comctl32/tests/misc.c | 206 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 205 insertions(+), 1 deletion(-)

diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c
index a3ba2028873..f4fcb300bb2 100644
--- a/dlls/comctl32/tests/misc.c
+++ b/dlls/comctl32/tests/misc.c
@@ -24,6 +24,7 @@
 
 #include "wine/test.h"
 #include "v6util.h"
+#include "msg.h"
 
 static PVOID (WINAPI * pAlloc)(LONG);
 static PVOID (WINAPI * pReAlloc)(PVOID, LONG);
@@ -35,8 +36,21 @@ static BOOL (WINAPI * pStr_SetPtrA)(LPSTR, LPCSTR);
 static INT (WINAPI * pStr_GetPtrW)(LPCWSTR, LPWSTR, INT);
 static BOOL (WINAPI * pStr_SetPtrW)(LPWSTR, LPCWSTR);
 
+static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
+static BOOL (WINAPI *pRemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
+static LRESULT (WINAPI *pDefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+
 static HMODULE hComctl32 = 0;
 
+/* For message tests */
+enum seq_index
+{
+    CHILD_SEQ_INDEX,
+    NUM_MSG_SEQUENCES
+};
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
 static char testicon_data[] =
 {
     0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00,
@@ -79,6 +93,40 @@ static BOOL InitFunctionPtrs(void)
     return TRUE;
 }
 
+static BOOL init_functions_v6(void)
+{
+    hComctl32 = LoadLibraryA("comctl32.dll");
+    if (!hComctl32)
+    {
+        trace("Could not load comctl32.dll version 6\n");
+        return FALSE;
+    }
+
+    COMCTL32_GET_PROC(410, SetWindowSubclass)
+    COMCTL32_GET_PROC(412, RemoveWindowSubclass)
+    COMCTL32_GET_PROC(413, DefSubclassProc)
+
+    return TRUE;
+}
+
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+    MSG msg;
+    int diff = 200;
+    int min_timeout = 100;
+    DWORD time = GetTickCount() + diff;
+
+    while (diff > 0)
+    {
+        if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT)
+            break;
+        while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+            DispatchMessageA(&msg);
+        diff = time - GetTickCount();
+    }
+}
+
 static void test_GetPtrAW(void)
 {
     if (pStr_GetPtrA)
@@ -406,6 +454,156 @@ static void test_comctl32_classes(BOOL v6)
     check_class("SysLink", v6, CS_GLOBALCLASS, 0, FALSE);
 }
 
+struct wm_themechanged_test
+{
+    const char *class;
+    const struct message *expected_msg;
+    int ignored_msg_count;
+    DWORD ignored_msgs[16];
+    BOOL todo;
+};
+
+static BOOL ignore_message(UINT msg)
+{
+    /* these are always ignored */
+    return (msg >= 0xc000 ||
+            msg == WM_GETICON ||
+            msg == WM_GETOBJECT ||
+            msg == WM_TIMECHANGE ||
+            msg == WM_DISPLAYCHANGE ||
+            msg == WM_DEVICECHANGE ||
+            msg == WM_DWMNCRENDERINGCHANGED ||
+            msg == WM_WININICHANGE ||
+            msg == WM_CHILDACTIVATE);
+}
+
+static LRESULT CALLBACK test_wm_themechanged_proc(HWND hwnd, UINT message, WPARAM wParam,
+                                                  LPARAM lParam, UINT_PTR id, DWORD_PTR ref_data)
+{
+    const struct wm_themechanged_test *test = (const struct wm_themechanged_test *)ref_data;
+    static int defwndproc_counter = 0;
+    struct message msg = {0};
+    LRESULT ret;
+    int i;
+
+    if (ignore_message(message))
+        return pDefSubclassProc(hwnd, message, wParam, lParam);
+
+    /* Extra messages to be ignored for a test case */
+    for (i = 0; i < test->ignored_msg_count; ++i)
+    {
+        if (message == test->ignored_msgs[i])
+            return pDefSubclassProc(hwnd, message, wParam, lParam);
+    }
+
+    msg.message = message;
+    msg.flags = sent | wparam | lparam;
+    if (defwndproc_counter)
+        msg.flags |= defwinproc;
+    msg.wParam = wParam;
+    msg.lParam = lParam;
+    add_message(sequences, CHILD_SEQ_INDEX, &msg);
+
+    if (message == WM_NCDESTROY)
+        pRemoveWindowSubclass(hwnd, test_wm_themechanged_proc, 0);
+
+    ++defwndproc_counter;
+    ret = pDefSubclassProc(hwnd, message, wParam, lParam);
+    --defwndproc_counter;
+
+    return ret;
+}
+
+static HWND create_control(const char *class, DWORD style, HWND parent, DWORD_PTR data)
+{
+    HWND hwnd;
+
+    if (parent)
+        style |= WS_CHILD;
+    hwnd = CreateWindowExA(0, class, "test", style, 0, 0, 50, 20, parent, 0, 0, NULL);
+    ok(!!hwnd, "Failed to create %s style %#x parent %p\n", class, style, parent);
+    pSetWindowSubclass(hwnd, test_wm_themechanged_proc, 0, data);
+    return hwnd;
+}
+
+static const struct message wm_themechanged_paint_erase_seq[] =
+{
+    {WM_THEMECHANGED, sent | wparam | lparam},
+    {WM_PAINT, sent | wparam | lparam},
+    {WM_ERASEBKGND, sent | defwinproc},
+    {0},
+};
+
+static const struct message wm_themechanged_paint_seq[] =
+{
+    {WM_THEMECHANGED, sent | wparam | lparam},
+    {WM_PAINT, sent | wparam | lparam},
+    {0},
+};
+
+static const struct message wm_themechanged_no_paint_seq[] =
+{
+    {WM_THEMECHANGED, sent | wparam | lparam},
+    {0},
+};
+
+static void test_WM_THEMECHANGED(void)
+{
+    HWND parent, child;
+    char buffer[64];
+    int i;
+
+    static const struct wm_themechanged_test tests[] =
+    {
+        {ANIMATE_CLASSA, wm_themechanged_no_paint_seq},
+        {WC_BUTTONA, wm_themechanged_paint_erase_seq, 2, {WM_GETTEXT, WM_GETTEXTLENGTH}, TRUE},
+        {WC_COMBOBOXA, wm_themechanged_paint_erase_seq, 1, {WM_CTLCOLOREDIT}, TRUE},
+        {WC_COMBOBOXEXA, wm_themechanged_no_paint_seq},
+        {DATETIMEPICK_CLASSA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {WC_EDITA, wm_themechanged_paint_erase_seq, 7, {WM_GETTEXTLENGTH, WM_GETFONT, EM_GETSEL, EM_GETRECT, EM_CHARFROMPOS, EM_LINEFROMCHAR, EM_POSFROMCHAR}, TRUE},
+        {WC_HEADERA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {HOTKEY_CLASSA, wm_themechanged_no_paint_seq},
+        {WC_IPADDRESSA, wm_themechanged_paint_erase_seq, 1, {WM_CTLCOLOREDIT}, TRUE},
+        {WC_LISTBOXA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {WC_LISTVIEWA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {MONTHCAL_CLASSA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {WC_NATIVEFONTCTLA, wm_themechanged_no_paint_seq},
+        {WC_PAGESCROLLERA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {PROGRESS_CLASSA, wm_themechanged_paint_erase_seq, 3, {WM_STYLECHANGING, WM_STYLECHANGED, WM_NCPAINT}, TRUE},
+        {REBARCLASSNAMEA, wm_themechanged_no_paint_seq, 1, {WM_WINDOWPOSCHANGING}},
+        {WC_STATICA, wm_themechanged_paint_erase_seq, 2, {WM_GETTEXT, WM_GETTEXTLENGTH}, TRUE},
+        {STATUSCLASSNAMEA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {"SysLink", wm_themechanged_no_paint_seq},
+        {WC_TABCONTROLA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {TOOLBARCLASSNAMEA, wm_themechanged_paint_erase_seq, 1, {WM_WINDOWPOSCHANGING}, TRUE},
+        {TOOLTIPS_CLASSA, wm_themechanged_no_paint_seq},
+        {TRACKBAR_CLASSA, wm_themechanged_paint_seq, 0, {0}, TRUE},
+        {WC_TREEVIEWA, wm_themechanged_paint_erase_seq, 1, {0x1128}, TRUE},
+        {UPDOWN_CLASSA, wm_themechanged_paint_erase_seq, 0, {0}, TRUE},
+        {WC_SCROLLBARA, wm_themechanged_paint_erase_seq, 1, {SBM_GETSCROLLINFO}, TRUE},
+    };
+
+    parent = CreateWindowExA(0, WC_STATICA, "parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100,
+                             200, 200, 0, 0, 0, NULL);
+    ok(!!parent, "Failed to create parent window\n");
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i)
+    {
+        child = create_control(tests[i].class, WS_VISIBLE, parent, (DWORD_PTR)&tests[i]);
+        flush_events();
+        flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+        SendMessageW(child, WM_THEMECHANGED, 0, 0);
+        flush_events();
+
+        sprintf(buffer, "Test %d class %s WM_THEMECHANGED", i, tests[i].class);
+        ok_sequence(sequences, CHILD_SEQ_INDEX, tests[i].expected_msg, buffer, tests[i].todo);
+        DestroyWindow(child);
+    }
+
+    DestroyWindow(parent);
+}
+
 START_TEST(misc)
 {
     ULONG_PTR ctx_cookie;
@@ -416,15 +614,21 @@ START_TEST(misc)
 
     test_GetPtrAW();
     test_Alloc();
-
     test_comctl32_classes(FALSE);
 
+    FreeLibrary(hComctl32);
+
     if (!load_v6_module(&ctx_cookie, &hCtx))
         return;
+    if(!init_functions_v6())
+        return;
+    init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
 
     test_comctl32_classes(TRUE);
     test_builtin_classes();
     test_LoadIconWithScaleDown();
+    test_WM_THEMECHANGED();
 
     unload_v6_module(ctx_cookie, hCtx);
+    FreeLibrary(hComctl32);
 }




More information about the wine-cvs mailing list