user32: Fix for the ending of menu tracking in the default handler of WM_CANCELMODE message with test.
This commit is contained in:
parent
8955d7c233
commit
e861d8be43
|
@ -88,6 +88,7 @@ extern void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam, WCHAR wChar ) DECLSPEC
|
||||||
extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
|
extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
|
||||||
HWND hwnd, BOOL suppress_draw ) DECLSPEC_HIDDEN;
|
HWND hwnd, BOOL suppress_draw ) DECLSPEC_HIDDEN;
|
||||||
extern UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget ) DECLSPEC_HIDDEN;
|
extern UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget ) DECLSPEC_HIDDEN;
|
||||||
|
extern void MENU_EndMenu(HWND) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* nonclient area */
|
/* nonclient area */
|
||||||
extern LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) DECLSPEC_HIDDEN;
|
extern LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -618,7 +618,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
|
||||||
|
|
||||||
case WM_CANCELMODE:
|
case WM_CANCELMODE:
|
||||||
iMenuSysKey = 0;
|
iMenuSysKey = 0;
|
||||||
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
|
MENU_EndMenu( hwnd );
|
||||||
if (GetCapture() == hwnd) ReleaseCapture();
|
if (GetCapture() == hwnd) ReleaseCapture();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,7 @@ static UINT ODitemheight; /* default owner drawn item height */
|
||||||
/* Use global popup window because there's no way 2 menus can
|
/* Use global popup window because there's no way 2 menus can
|
||||||
* be tracked at the same time. */
|
* be tracked at the same time. */
|
||||||
static HWND top_popup;
|
static HWND top_popup;
|
||||||
|
static HMENU top_popup_hmenu;
|
||||||
|
|
||||||
/* Flag set by EndMenu() to force an exit from menu tracking */
|
/* Flag set by EndMenu() to force an exit from menu tracking */
|
||||||
static BOOL fEndMenu = FALSE;
|
static BOOL fEndMenu = FALSE;
|
||||||
|
@ -1884,8 +1885,10 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags,
|
||||||
hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
|
hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
|
||||||
(LPVOID)hmenu );
|
(LPVOID)hmenu );
|
||||||
if( !menu->hWnd ) return FALSE;
|
if( !menu->hWnd ) return FALSE;
|
||||||
if (!top_popup) top_popup = menu->hWnd;
|
if (!top_popup) {
|
||||||
|
top_popup = menu->hWnd;
|
||||||
|
top_popup_hmenu = hmenu;
|
||||||
|
}
|
||||||
/* Display the window */
|
/* Display the window */
|
||||||
|
|
||||||
SetWindowPos( menu->hWnd, HWND_TOPMOST, 0, 0, 0, 0,
|
SetWindowPos( menu->hWnd, HWND_TOPMOST, 0, 0, 0, 0,
|
||||||
|
@ -1953,7 +1956,10 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
|
||||||
if (lppop->FocusedItem == wIndex) return;
|
if (lppop->FocusedItem == wIndex) return;
|
||||||
if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
|
if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
|
||||||
else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
|
else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
|
||||||
if (!top_popup) top_popup = lppop->hWnd;
|
if (!top_popup) {
|
||||||
|
top_popup = lppop->hWnd;
|
||||||
|
top_popup_hmenu = hmenu;
|
||||||
|
}
|
||||||
|
|
||||||
SelectObject( hdc, get_menu_font(FALSE));
|
SelectObject( hdc, get_menu_font(FALSE));
|
||||||
|
|
||||||
|
@ -2462,6 +2468,20 @@ HWND MENU_IsMenuActive(void)
|
||||||
return top_popup;
|
return top_popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* MENU_EndMenu
|
||||||
|
*
|
||||||
|
* Calls EndMenu() if the hwnd parameter belongs to the menu owner
|
||||||
|
*
|
||||||
|
* Does the (menu stuff) of the default window handling of WM_CANCELMODE
|
||||||
|
*/
|
||||||
|
void MENU_EndMenu( HWND hwnd )
|
||||||
|
{
|
||||||
|
POPUPMENU *menu;
|
||||||
|
menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu ) : NULL;
|
||||||
|
if (menu && hwnd == menu->hwndOwner) EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MENU_PtMenu
|
* MENU_PtMenu
|
||||||
*
|
*
|
||||||
|
@ -3363,6 +3383,7 @@ static BOOL MENU_ExitTracking(HWND hWnd)
|
||||||
SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
|
SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
|
||||||
ShowCaret(0);
|
ShowCaret(0);
|
||||||
top_popup = 0;
|
top_popup = 0;
|
||||||
|
top_popup_hmenu = NULL;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3530,7 +3551,10 @@ static LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam,
|
||||||
|
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
/* zero out global pointer in case resident popup window was destroyed. */
|
/* zero out global pointer in case resident popup window was destroyed. */
|
||||||
if (hwnd == top_popup) top_popup = 0;
|
if (hwnd == top_popup) {
|
||||||
|
top_popup = 0;
|
||||||
|
top_popup_hmenu = NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_SHOWWINDOW:
|
case WM_SHOWWINDOW:
|
||||||
|
|
|
@ -40,6 +40,7 @@ static ATOM atomMenuCheckClass;
|
||||||
static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
|
static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
|
||||||
static UINT (WINAPI *pSendInput)(UINT, INPUT*, size_t);
|
static UINT (WINAPI *pSendInput)(UINT, INPUT*, size_t);
|
||||||
static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
|
static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
|
||||||
|
static BOOL (WINAPI *pEndMenu) (void);
|
||||||
|
|
||||||
static void init_function_pointers(void)
|
static void init_function_pointers(void)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +54,7 @@ static void init_function_pointers(void)
|
||||||
GET_PROC(GetMenuInfo)
|
GET_PROC(GetMenuInfo)
|
||||||
GET_PROC(SendInput)
|
GET_PROC(SendInput)
|
||||||
GET_PROC(SetMenuInfo)
|
GET_PROC(SetMenuInfo)
|
||||||
|
GET_PROC(EndMenu)
|
||||||
|
|
||||||
#undef GET_PROC
|
#undef GET_PROC
|
||||||
}
|
}
|
||||||
|
@ -2847,6 +2849,89 @@ static void test_menu_trackpopupmenu(void)
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* test handling of WM_CANCELMODE messages */
|
||||||
|
static int g_got_enteridle;
|
||||||
|
static HWND g_hwndtosend;
|
||||||
|
static LRESULT WINAPI menu_cancelmode_wnd_proc(HWND hwnd, UINT msg,
|
||||||
|
WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_ENTERMENULOOP:
|
||||||
|
g_got_enteridle = 0;
|
||||||
|
return SendMessage( g_hwndtosend, WM_CANCELMODE, 0, 0);
|
||||||
|
case WM_ENTERIDLE:
|
||||||
|
{
|
||||||
|
if( g_got_enteridle++ == 0) {
|
||||||
|
/* little hack to get another WM_ENTERIDLE message */
|
||||||
|
PostMessage( hwnd, WM_MOUSEMOVE, 0, 0);
|
||||||
|
return SendMessage( g_hwndtosend, WM_CANCELMODE, 0, 0);
|
||||||
|
}
|
||||||
|
pEndMenu();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DefWindowProc( hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_menu_cancelmode(void)
|
||||||
|
{
|
||||||
|
DWORD ret;
|
||||||
|
HWND hwnd, hwndchild;
|
||||||
|
HMENU menu;
|
||||||
|
if( !pEndMenu) { /* win95 */
|
||||||
|
win_skip( "EndMenu is not available\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hwnd = CreateWindowEx( 0, MAKEINTATOM(atomMenuCheckClass), NULL,
|
||||||
|
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
hwndchild = CreateWindowEx( 0, MAKEINTATOM(atomMenuCheckClass), NULL,
|
||||||
|
WS_VISIBLE | WS_CHILD, 10, 10, 20, 20,
|
||||||
|
hwnd, NULL, NULL, NULL);
|
||||||
|
ok( hwnd != NULL && hwndchild != NULL,
|
||||||
|
"CreateWindowEx failed with error %d\n", GetLastError());
|
||||||
|
g_hwndtosend = hwnd;
|
||||||
|
SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR)menu_cancelmode_wnd_proc);
|
||||||
|
SetWindowLongPtr( hwndchild, GWLP_WNDPROC, (LONG_PTR)menu_cancelmode_wnd_proc);
|
||||||
|
menu = CreatePopupMenu();
|
||||||
|
ok( menu != NULL, "CreatePopupMenu failed with error %d\n", GetLastError());
|
||||||
|
ret = AppendMenuA( menu, MF_STRING, 1, "winetest");
|
||||||
|
ok( ret, "Functie failed lasterror is %u\n", GetLastError());
|
||||||
|
/* seems to be needed only on wine :( */
|
||||||
|
{MSG msg; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);}
|
||||||
|
/* test the effect of sending a WM_CANCELMODE message in the WM_INITMENULOOP
|
||||||
|
* handler of the menu owner */
|
||||||
|
/* test results is exctracted from variable g_got_enteridle. Possible values:
|
||||||
|
* 0 : complete conformance. Sending WM_CANCELMODE cancels a menu initializing tracking
|
||||||
|
* 1 : Sending WM_CANCELMODE cancels a menu that is in tracking state
|
||||||
|
* 2 : Sending WM_CANCELMODE does not work
|
||||||
|
*/
|
||||||
|
/* menu owner is top level window */
|
||||||
|
g_hwndtosend = hwnd;
|
||||||
|
ret = TrackPopupMenu( menu, 0x100, 100,100, 0, hwnd, NULL);
|
||||||
|
todo_wine {
|
||||||
|
ok( g_got_enteridle == 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle);
|
||||||
|
}
|
||||||
|
ok( g_got_enteridle < 2, "received %d WM_ENTERIDLE messages, should be less then 2\n", g_got_enteridle);
|
||||||
|
/* menu owner is child window */
|
||||||
|
g_hwndtosend = hwndchild;
|
||||||
|
ret = TrackPopupMenu( menu, 0x100, 100,100, 0, hwndchild, NULL);
|
||||||
|
todo_wine {
|
||||||
|
ok(g_got_enteridle == 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle);
|
||||||
|
}
|
||||||
|
ok(g_got_enteridle < 2, "received %d WM_ENTERIDLE messages, should be less then 2\n", g_got_enteridle);
|
||||||
|
/* now send the WM_CANCELMODE messages to the WRONG window */
|
||||||
|
/* those should fail ( to have any effect) */
|
||||||
|
g_hwndtosend = hwnd;
|
||||||
|
ret = TrackPopupMenu( menu, 0x100, 100,100, 0, hwndchild, NULL);
|
||||||
|
ok( g_got_enteridle == 2, "received %d WM_ENTERIDLE messages, should be 2\n", g_got_enteridle);
|
||||||
|
/* cleanup */
|
||||||
|
DestroyMenu( menu);
|
||||||
|
DestroyWindow( hwndchild);
|
||||||
|
DestroyWindow( hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(menu)
|
START_TEST(menu)
|
||||||
{
|
{
|
||||||
init_function_pointers();
|
init_function_pointers();
|
||||||
|
@ -2884,4 +2969,5 @@ START_TEST(menu)
|
||||||
|
|
||||||
test_menu_hilitemenuitem();
|
test_menu_hilitemenuitem();
|
||||||
test_menu_trackpopupmenu();
|
test_menu_trackpopupmenu();
|
||||||
|
test_menu_cancelmode();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue