Button should send BM_SETSTATE message after it has changed its internal state

Dmitry Timoshkov dmitry at baikal.ru
Thu Aug 26 08:43:25 CDT 2004


Hello,

this is a result of my bug hunting for a not existing capture bug.

An app I'm working on subclasses a button and relies on the fact
that on WM_LBUTTONDOWN message button sends BM_SETSTATE message *after*
it has changed its internal state.

I've written a test case for WM_LBUTTONDOWN/WM_LBUTTONUP messages
just in case.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Button should send BM_SETSTATE message after it has changed
    its internal state.

diff -u cvs/hq/wine/controls/button.c wine/controls/button.c
--- cvs/hq/wine/controls/button.c	2004-08-23 13:33:05.000000000 +0900
+++ wine/controls/button.c	2004-08-26 22:02:00.000000000 +0900
@@ -256,8 +256,8 @@ static LRESULT WINAPI ButtonWndProc_comm
     case WM_LBUTTONDOWN:
         SetCapture( hWnd );
         SetFocus( hWnd );
-        SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 );
         set_button_state( hWnd, get_button_state( hWnd ) | BUTTON_BTNPRESSED );
+        SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 );
         break;
 
     case WM_KEYUP:
diff -u cvs/hq/wine/dlls/user/tests/msg.c wine/dlls/user/tests/msg.c
--- cvs/hq/wine/dlls/user/tests/msg.c	2004-08-26 14:46:31.000000000 +0900
+++ wine/dlls/user/tests/msg.c	2004-08-26 21:58:11.000000000 +0900
@@ -1670,6 +1670,25 @@ static const struct message WmKillFocusS
     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
     { 0 }
 };
+static const struct message WmLButtonDownSeq[] =
+{
+    { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_CTLCOLORBTN, sent|defwinproc },
+    { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
+    { WM_CTLCOLORBTN, sent|defwinproc },
+    { 0 }
+};
+static const struct message WmLButtonUpSeq[] =
+{
+    { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
+    { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
+    { WM_CTLCOLORBTN, sent|defwinproc },
+    { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
+    { 0 }
+};
 
 static WNDPROC old_button_proc;
 
@@ -1679,7 +1698,7 @@ static LRESULT CALLBACK button_hook_proc
     LRESULT ret;
     struct message msg;
 
-    trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+    trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
 
     msg.message = message;
     msg.flags = sent|wparam|lparam;
@@ -1688,6 +1707,9 @@ static LRESULT CALLBACK button_hook_proc
     msg.lParam = lParam;
     add_message(&msg);
 
+    if (message == BM_SETSTATE)
+	ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
+
     defwndproc_counter++;
     ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
     defwndproc_counter--;
@@ -1754,6 +1776,20 @@ static void test_button_messages(void)
 
 	DestroyWindow(hwnd);
     }
+
+    hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE,
+			   0, 0, 50, 14, 0, 0, 0, NULL);
+    ok(hwnd != 0, "Failed to create button window\n");
+
+    SetFocus(0);
+    flush_sequence();
+
+    SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
+    ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
+
+    SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
+    ok_sequence(WmLButtonUpSeq, "WM_LBUTTONDOWN on a button", FALSE);
+    DestroyWindow(hwnd);
 }
 
 /************* painting message test ********************/






More information about the wine-patches mailing list