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