user32: Add a test for combobox navigation with arrow keys, make it pass under Wine

Dmitry Timoshkov dmitry at codeweavers.com
Thu Mar 27 01:35:59 CDT 2008


Hello,

this patch fixes the problem reported in the bug 12070.

Changelog:
    user32: Add a test for combobox navigation with arrow keys,
    make it pass under Wine.
---
 dlls/user32/combo.c     |   29 +++++------
 dlls/user32/listbox.c   |    2 +-
 dlls/user32/tests/msg.c |  127 ++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 133 insertions(+), 25 deletions(-)

diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c
index 549600e..14eebe8 100644
--- a/dlls/user32/combo.c
+++ b/dlls/user32/combo.c
@@ -884,16 +884,9 @@ static HBRUSH COMBO_PrepareColors(
   }
   else
   {
-    if (lphc->wState & CBF_EDIT)
-    {
+      /* FIXME: In which cases WM_CTLCOLORLISTBOX should be sent? */
       hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLOREDIT,
 				       (WPARAM)hDC, (LPARAM)lphc->self );
-    }
-    else
-    {
-      hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLORLISTBOX,
-				       (WPARAM)hDC, (LPARAM)lphc->self );
-    }
   }
 
   /*
@@ -1350,6 +1343,14 @@ static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd )
 
                 TRACE("[%p]: lbox selection change [%x]\n", lphc->self, lphc->wState );
 
+                /* do not roll up if selection is being tracked
+                 * by arrowkeys in the dropdown listbox */
+                if (!(lphc->wState & CBF_NOROLLUP))
+                {
+                    CBRollUp( lphc, (HIWORD(wParam) == LBN_SELCHANGE), TRUE );
+                }
+                else lphc->wState &= ~CBF_NOROLLUP;
+
 		CB_NOTIFY( lphc, CBN_SELCHANGE );
 
 		if( HIWORD(wParam) == LBN_SELCHANGE)
@@ -1363,17 +1364,11 @@ static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd )
 		       SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
 		   }
 		   else
+                   {
 		       InvalidateRect(lphc->self, &lphc->textRect, TRUE);
+                       UpdateWindow(lphc->self);
+                   }
 		}
-
-		/* do not roll up if selection is being tracked
-		 * by arrowkeys in the dropdown listbox */
-                if( ((lphc->wState & CBF_DROPPED) && !(lphc->wState & CBF_NOROLLUP)) )
-                {
-                   CBRollUp( lphc, (HIWORD(wParam) == LBN_SELCHANGE), TRUE );
-                }
-		else lphc->wState &= ~CBF_NOROLLUP;
-
                 break;
 
 	   case LBN_SETFOCUS:
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index 7232644..0b318fa 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -2442,7 +2442,7 @@ static LRESULT LISTBOX_HandleKeyDown( LB_DESCR *descr, DWORD key )
             LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
         if (descr->style & LBS_NOTIFY)
         {
-            if( descr->lphc )
+            if (descr->lphc && IsWindowVisible( descr->self ))
             {
                 /* make sure that combo parent doesn't hide us */
                 descr->lphc->wState |= CBF_NOROLLUP;
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index b8d9375..ca166d8 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -43,6 +43,10 @@
 
 #define SW_NORMALNA	        0xCC    /* undoc. flag in MinMaximize */
 
+#ifndef WM_KEYF1
+#define WM_KEYF1 0x004d
+#endif
+
 #ifndef WM_SYSTIMER
 #define WM_SYSTIMER	    0x0118
 #endif
@@ -2740,7 +2744,6 @@ static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wPara
         message != WM_NCPAINT &&
         message != WM_SYNCPAINT &&
         message != WM_ERASEBKGND &&
-        message != WM_NCPAINT &&
         message != WM_NCHITTEST &&
         message != WM_GETTEXT &&
         message != WM_MDIGETACTIVE &&
@@ -2793,7 +2796,6 @@ static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam,
         message != WM_NCPAINT &&
         message != WM_SYNCPAINT &&
         message != WM_ERASEBKGND &&
-        message != WM_NCPAINT &&
         message != WM_NCHITTEST &&
         message != WM_GETTEXT &&
         message != WM_GETICON &&
@@ -2863,7 +2865,6 @@ static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam,
         message != WM_NCPAINT &&
         message != WM_SYNCPAINT &&
         message != WM_ERASEBKGND &&
-        message != WM_NCPAINT &&
         message != WM_NCHITTEST &&
         message != WM_GETTEXT &&
         message != WM_GETICON &&
@@ -4855,7 +4856,6 @@ static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam,
     msg.lParam = lParam;
     add_message(&msg);
 
-
     defwndproc_counter++;
     ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam);
     defwndproc_counter--;
@@ -4918,6 +4918,111 @@ static void test_static_messages(void)
     }
 }
 
+/****************** ComboBox message test *************************/
+#define ID_COMBOBOX 0x000f
+
+static const struct message WmKeyDownComboSeq[] =
+{
+    { WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 },
+    { WM_COMMAND, sent|wparam, MAKEWPARAM(1000, LBN_SELCHANGE) },
+    { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDOK) },
+    { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELCHANGE) },
+    { WM_CTLCOLOREDIT, sent|parent },
+    { WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0 },
+    { 0 }
+};
+
+static WNDPROC old_combobox_proc;
+
+static LRESULT CALLBACK combobox_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    static long defwndproc_counter = 0;
+    LRESULT ret;
+    struct message msg;
+
+    /* do not log painting messages */
+    if (message != WM_PAINT &&
+        message != WM_NCPAINT &&
+        message != WM_SYNCPAINT &&
+        message != WM_ERASEBKGND &&
+        message != WM_NCHITTEST &&
+        message != WM_GETTEXT &&
+        message != WM_GETICON &&
+        message != WM_DEVICECHANGE)
+    {
+        trace("combo: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+        msg.message = message;
+        msg.flags = sent|wparam|lparam;
+        msg.wParam = wParam;
+        msg.lParam = lParam;
+        add_message(&msg);
+    }
+
+    defwndproc_counter++;
+    ret = CallWindowProcA(old_combobox_proc, hwnd, message, wParam, lParam);
+    defwndproc_counter--;
+
+    return ret;
+}
+
+static void subclass_combobox(void)
+{
+    WNDCLASSA cls;
+
+    if (!GetClassInfoA(0, "ComboBox", &cls)) assert(0);
+
+    old_combobox_proc = cls.lpfnWndProc;
+
+    cls.hInstance = GetModuleHandle(0);
+    cls.lpfnWndProc = combobox_hook_proc;
+    cls.lpszClassName = "my_combobox_class";
+    UnregisterClass(cls.lpszClassName, cls.hInstance);
+    if (!RegisterClassA(&cls)) assert(0);
+}
+
+static void test_combobox_messages(void)
+{
+    HWND parent, combo;
+    LRESULT ret;
+
+    subclass_combobox();
+
+    parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+                             100, 100, 200, 200, 0, 0, 0, NULL);
+    ok(parent != 0, "Failed to create parent window\n");
+    flush_sequence();
+
+    combo = CreateWindowEx(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
+                           0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL);
+    ok(combo != 0, "Failed to create combobox window\n");
+
+    UpdateWindow(combo);
+
+    ret = SendMessage(combo, WM_GETDLGCODE, 0, 0);
+    ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08lx\n", ret);
+
+    ret = SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)"item 0");
+    ok(ret == 0, "expected 0, got %ld\n", ret);
+    ret = SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)"item 1");
+    ok(ret == 1, "expected 1, got %ld\n", ret);
+    ret = SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)"item 2");
+    ok(ret == 2, "expected 2, got %ld\n", ret);
+
+    SendMessage(combo, CB_SETCURSEL, 0, 0);
+    SetFocus(combo);
+    flush_sequence();
+
+    log_all_parent_messages++;
+    SendMessage(combo, WM_KEYDOWN, VK_DOWN, 0);
+    SendMessage(combo, WM_KEYUP, VK_DOWN, 0);
+    log_all_parent_messages--;
+    ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE);
+
+    DestroyWindow(combo);
+    DestroyWindow(parent);
+}
+
 /************* painting message test ********************/
 
 void dump_region(HRGN hrgn)
@@ -10038,6 +10143,8 @@ static LRESULT (WINAPI *listbox_orig_proc)(HWND, UINT, WPARAM, LPARAM);
 
 static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
 {
+    static long defwndproc_counter = 0;
+    LRESULT ret;
     struct message msg;
 
     /* do not log painting messages */
@@ -10059,7 +10166,11 @@ static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPAR
         add_message(&msg);
     }
 
-    return CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp);
+    defwndproc_counter++;
+    ret = CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp);
+    defwndproc_counter--;
+
+    return ret;
 }
 
 static void check_lb_state_dbg(HWND listbox, int count, int cur_sel,
@@ -10078,7 +10189,7 @@ static void check_lb_state_dbg(HWND listbox, int count, int cur_sel,
     ok_(__FILE__, line)(ret == top_index, "expected top index %d, got %ld\n", top_index, ret);
 }
 
-static void test_listbox(void)
+static void test_listbox_messages(void)
 {
     HWND parent, listbox;
     LRESULT ret;
@@ -10135,6 +10246,7 @@ static void test_listbox(void)
 
     log_all_parent_messages--;
 
+    DestroyWindow(listbox);
     DestroyWindow(parent);
 }
 
@@ -10192,6 +10304,8 @@ START_TEST(msg)
     test_mdi_messages();
     test_button_messages();
     test_static_messages();
+    test_listbox_messages();
+    test_combobox_messages();
     test_paint_messages();
     test_interthread_messages();
     test_message_conversion();
@@ -10216,7 +10330,6 @@ START_TEST(msg)
     test_nullCallback();
     test_SetForegroundWindow();
     test_dbcs_wm_char();
-    test_listbox();
 
     UnhookWindowsHookEx(hCBT_hook);
     if (pUnhookWinEvent)
-- 
1.5.4.3






More information about the wine-patches mailing list