From a07966dba809d18416e818e1dec80d5fe7dbe326 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 26 Feb 2014 15:08:11 -0600 Subject: [PATCH] user32: Create popup menu windows before WM_ENTERMENULOOP. --- dlls/user32/menu.c | 90 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 915b1c57a70..8bb508dfd37 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -1817,6 +1817,41 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd ) /*********************************************************************** + * MENU_InitPopup + * + * Popup menu initialization before WM_ENTERMENULOOP. + */ +static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) +{ + POPUPMENU *menu; + DWORD ex_style = 0; + + TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu); + + if (!(menu = MENU_GetMenu( hmenu ))) return FALSE; + + /* store the owner for DrawItem */ + if (!IsWindow( hwndOwner )) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } + menu->hwndOwner = hwndOwner; + + if (flags & TPM_LAYOUTRTL) + ex_style = WS_EX_LAYOUTRTL; + + /* NOTE: In Windows, top menu popup is not owned. */ + menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL, + WS_POPUP, 0, 0, 0, 0, + hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), + (LPVOID)hmenu ); + if( !menu->hWnd ) return FALSE; + return TRUE; +} + + +/*********************************************************************** * MENU_ShowPopup * * Display a popup menu. @@ -1829,7 +1864,6 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, POINT pt; HMONITOR monitor; MONITORINFO info; - DWORD ex_style = 0; TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", hwndOwner, hmenu, id, x, y, xanchor, yanchor); @@ -1841,14 +1875,6 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, menu->FocusedItem = NO_SELECTED_ITEM; } - /* store the owner for DrawItem */ - if (!IsWindow( hwndOwner )) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - menu->hwndOwner = hwndOwner; - menu->nScrollPos = 0; MENU_PopupMenuCalcSize( menu ); @@ -1865,10 +1891,7 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, GetMonitorInfoW( monitor, &info ); if (flags & TPM_LAYOUTRTL) - { - ex_style = WS_EX_LAYOUTRTL; flags ^= TPM_RIGHTALIGN; - } if( flags & TPM_RIGHTALIGN ) x -= width; if( flags & TPM_CENTERALIGN ) x -= width / 2; @@ -1896,20 +1919,14 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, } if( y < info.rcWork.top ) y = info.rcWork.top; - /* NOTE: In Windows, top menu popup is not owned. */ - menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL, - WS_POPUP, x, y, width, height, - hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), - (LPVOID)hmenu ); - if( !menu->hWnd ) return FALSE; if (!top_popup) { top_popup = menu->hWnd; top_popup_hmenu = hmenu; } /* Display the window */ - SetWindowPos( menu->hWnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + SetWindowPos( menu->hWnd, HWND_TOPMOST, x, y, width, height, + SWP_SHOWWINDOW | SWP_NOACTIVATE ); UpdateWindow( menu->hWnd ); return TRUE; } @@ -2386,6 +2403,8 @@ static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, /* use default alignment for submenus */ wFlags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN); + MENU_InitPopup( hwndOwner, item->hSubMenu, wFlags ); + MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem, wFlags, rect.left, rect.top, rect.right, rect.bottom ); if (selectFirst) @@ -3291,7 +3310,7 @@ static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags) * It also enables menus to be displayed in more than one window, * but there are some bugs left that need to be fixed in this case. */ - if ((menu = MENU_GetMenu( hMenu ))) menu->hWnd = hWnd; + if (!bPopup && (menu = MENU_GetMenu( hMenu ))) menu->hWnd = hWnd; if (!top_popup) top_popup_hmenu = hMenu; /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */ @@ -3442,16 +3461,29 @@ BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y, return FALSE; } - MENU_InitTracking(hWnd, hMenu, TRUE, wFlags); + if (MENU_InitPopup( hWnd, hMenu, wFlags )) + { + MENU_InitTracking(hWnd, hMenu, TRUE, wFlags); - /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ - if (!(wFlags & TPM_NONOTIFY)) - SendMessageW( hWnd, WM_INITMENUPOPUP, (WPARAM)hMenu, 0); + /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( hWnd, WM_INITMENUPOPUP, (WPARAM)hMenu, 0); - if (MENU_ShowPopup( hWnd, hMenu, 0, wFlags, x, y, 0, 0 )) - ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, - lpTpm ? &lpTpm->rcExclude : NULL ); - MENU_ExitTracking(hWnd, TRUE); + if (MENU_ShowPopup( hWnd, hMenu, 0, wFlags, x, y, 0, 0 )) + ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, + lpTpm ? &lpTpm->rcExclude : NULL ); + MENU_ExitTracking(hWnd, TRUE); + + if (menu->hWnd) + { + DestroyWindow( menu->hWnd ); + menu->hWnd = 0; + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( hWnd, WM_UNINITMENUPOPUP, (WPARAM)hMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(menu)) ); + } + } return ret; } -- 2.11.4.GIT