menu: SetMenu SWP fix

Huw D M Davies h.davies1 at physics.ox.ac.uk
Tue Feb 17 10:48:47 CST 2004


        Huw Davies <huw at codeweavers.com>
        SetMenu should always call SetWindowPos whether the window is
        visible or not.  However we shouldn't call SWP from
        CreateWindowEx.
        Added a test for this behaviour.

-- 
Huw Davies
huw at codeweavers.com
Index: controls/menu.c
===================================================================
RCS file: /home/wine/wine/controls/menu.c,v
retrieving revision 1.175
diff -u -r1.175 menu.c
--- controls/menu.c	12 Feb 2004 00:35:02 -0000	1.175
+++ controls/menu.c	17 Feb 2004 16:40:57 -0000
@@ -3758,9 +3758,12 @@
 
 
 /**********************************************************************
- *         SetMenu    (USER32.@)
+ *         MENU_SetMenu
+ *
+ * Helper for SetMenu. Also called by WIN_CreateWindowEx to avoid the
+ * SetWindowPos call that would result if SetMenu were called directly.
  */
-BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
+BOOL MENU_SetMenu( HWND hWnd, HMENU hMenu )
 {
     TRACE("(%p, %p);\n", hWnd, hMenu);
 
@@ -3784,13 +3787,22 @@
         lpmenu->Height = 0;  /* Make sure we recalculate the size */
     }
     SetWindowLongW( hWnd, GWL_ID, (LONG_PTR)hMenu );
-
-    if (IsWindowVisible(hWnd))
-        SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
-                      SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
     return TRUE;
 }
 
+
+/**********************************************************************
+ *         SetMenu    (USER32.@)
+ */
+BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
+{   
+    if(!MENU_SetMenu(hWnd, hMenu))
+        return FALSE;
+ 
+    SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+    return TRUE;
+}
 
 
 /**********************************************************************
Index: windows/win.c
===================================================================
RCS file: /home/wine/wine/windows/win.c,v
retrieving revision 1.235
diff -u -r1.235 win.c
--- windows/win.c	6 Feb 2004 05:18:56 -0000	1.235
+++ windows/win.c	17 Feb 2004 16:40:57 -0000
@@ -1185,7 +1185,7 @@
     if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
         (wndPtr->dwExStyle & WS_EX_APPWINDOW))
     {
-        if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
+        if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
         else
         {
             LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
@@ -1196,7 +1196,7 @@
                 else
                     cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
 
-                if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
+                if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
             }
         }
     }
Index: dlls/user/tests/msg.c
===================================================================
RCS file: /home/wine/wine/dlls/user/tests/msg.c,v
retrieving revision 1.1
diff -u -r1.1 msg.c
--- dlls/user/tests/msg.c	2 Oct 2003 04:32:56 -0000	1.1
+++ dlls/user/tests/msg.c	17 Feb 2004 16:40:57 -0000
@@ -296,6 +296,44 @@
     { WM_SETCURSOR, sent|parent },
     { 0 }
 };
+/* SetMenu for NonVisible windows with size change*/
+static struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+    { WM_MOVE, sent },
+    { WM_SIZE, sent },
+    { 0 }
+};
+/* SetMenu for NonVisible windows with no size change */
+static struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+    { 0 }
+};
+/* SetMenu for Visible windows with size change */
+static struct message WmSetMenuVisibleSizeChangeSeq[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_NCPAINT, sent|wparam, 1 },
+    { WM_GETTEXT, sent },
+    { WM_ACTIVATE, sent },
+    { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+    { WM_MOVE, sent },
+    { WM_SIZE, sent },
+    { 0 }
+};
+/* SetMenu for Visible windows with no size change */
+static struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_NCPAINT, sent|wparam, 1 },
+    { WM_GETTEXT, sent },
+    { WM_ACTIVATE, sent },
+    { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+    { 0 }
+};
 
 static int sequence_cnt, sequence_size;
 static struct message* sequence;
@@ -380,6 +418,7 @@
 {
     HWND hwnd, hparent, hchild;
     HWND hchild2, hbutton;
+    HMENU hmenu;
 
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
                            100, 100, 200, 200, 0, 0, 0, NULL);
@@ -420,6 +459,30 @@
 
     DestroyWindow(hchild);
     ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
+    DestroyWindow(hchild2);
+    DestroyWindow(hbutton);
+    DestroyWindow(hparent);
+    flush_sequence();
+
+    /* Message sequence for SetMenu */
+    hmenu = CreateMenu();
+    ok (hmenu != 0, "Failed to create menu\n");
+    ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
+                           100, 100, 200, 200, 0, hmenu, 0, NULL);
+    ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
+    ok (SetMenu(hwnd, 0), "SetMenu");
+    ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");    
+    ok (SetMenu(hwnd, 0), "SetMenu");
+    ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");    
+    ShowWindow(hwnd, TRUE);
+    flush_sequence();
+    ok (SetMenu(hwnd, 0), "SetMenu");
+    ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");    
+    ok (SetMenu(hwnd, hmenu), "SetMenu");
+    ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");    
+    DestroyWindow(hwnd);
+
 }
 
 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Index: include/win.h
===================================================================
RCS file: /home/wine/wine/include/win.h,v
retrieving revision 1.81
diff -u -r1.81 win.h
--- include/win.h	20 Jan 2004 04:29:20 -0000	1.81
+++ include/win.h	17 Feb 2004 16:40:57 -0000
@@ -141,6 +141,8 @@
 
 extern BOOL FOCUS_MouseActivate( HWND hwnd );
 
+extern BOOL MENU_SetMenu(HWND, HMENU);
+
 /* check if hwnd is a broadcast magic handle */
 inline static BOOL is_broadcast( HWND hwnd )
 {



More information about the wine-patches mailing list