diff --git a/controls/menu.c b/controls/menu.c index e3ccf55f9cb..24b2fc5e281 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -578,6 +578,39 @@ static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags ) return NULL; } +/*********************************************************************** + * MENU_FindSubMenu + * + * Find a Sub menu. Return the position of the submenu, and modifies + * *hmenu in case it is found in another sub-menu. + * If the submenu cannot be found, NO_SELECTED_ITEM is returned. + */ +UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget ) +{ + POPUPMENU *menu; + UINT i; + MENUITEM *item; + if (((*hmenu)==0xffff) || + (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(*hmenu)))) + return NO_SELECTED_ITEM; + item = menu->items; + for (i = 0; i < menu->nItems; i++, item++) { + if(!(item->fType & MF_POPUP)) continue; + if (item->hSubMenu == hSubTarget) { + return i; + } + else { + HMENU hsubmenu = item->hSubMenu; + UINT pos = MENU_FindSubMenu( &hsubmenu, hSubTarget ); + if (pos != NO_SELECTED_ITEM) { + *hmenu = hsubmenu; + return pos; + } + } + } + return NO_SELECTED_ITEM; +} + /*********************************************************************** * MENU_FreeItemData */ @@ -1589,7 +1622,7 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, * MENU_SelectItem */ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex, - BOOL sendMenuSelect ) + BOOL sendMenuSelect, HMENU topmenu ) { LPPOPUPMENU lppop; HDC hdc; @@ -1599,10 +1632,6 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex, lppop = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ); if (!lppop->nItems) return; - if ((wIndex != NO_SELECTED_ITEM) && - (lppop->items[wIndex].fType & MF_SEPARATOR)) - wIndex = NO_SELECTED_ITEM; - if (lppop->FocusedItem == wIndex) return; if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd ); else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW); @@ -1622,20 +1651,32 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex, lppop->FocusedItem = wIndex; if (lppop->FocusedItem != NO_SELECTED_ITEM) { - lppop->items[lppop->FocusedItem].fState |= MF_HILITE; - MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc, &lppop->items[lppop->FocusedItem], - lppop->Height, !(lppop->wFlags & MF_POPUP), - ODA_SELECT ); + if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) { + lppop->items[wIndex].fState |= MF_HILITE; + MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc, + &lppop->items[wIndex], lppop->Height, + !(lppop->wFlags & MF_POPUP), ODA_SELECT ); + } if (sendMenuSelect) { MENUITEM *ip = &lppop->items[lppop->FocusedItem]; SendMessageA( hwndOwner, WM_MENUSELECT, - MAKELONG(ip->wID,ip->fType | (ip->fState | MF_MOUSESELECT)), hmenu); + MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID, + ip->fType | ip->fState | MF_MOUSESELECT | + (lppop->wFlags & MF_SYSMENU)), hmenu); } } else if (sendMenuSelect) { - SendMessageA( hwndOwner, WM_MENUSELECT, - MAKELONG( hmenu, lppop->wFlags | MF_MOUSESELECT), hmenu ); + if(topmenu){ + int pos; + if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){ + POPUPMENU *ptm = (POPUPMENU *) USER_HEAP_LIN_ADDR( topmenu ); + MENUITEM *ip = &ptm->items[pos]; + SendMessageA( hwndOwner, WM_MENUSELECT, MAKELONG(pos, + ip->fType | ip->fState | MF_MOUSESELECT | + (ptm->wFlags & MF_SYSMENU)), topmenu); + } + } } ReleaseDC( lppop->hWnd, hdc ); } @@ -1665,7 +1706,7 @@ static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset ) ; i += offset) if (!(menu->items[i].fType & MF_SEPARATOR)) { - MENU_SelectItem( hwndOwner, hmenu, i, TRUE ); + MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 ); return; } } @@ -1674,7 +1715,7 @@ static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset ) i >= 0 && i < menu->nItems ; i += offset) if (!(menu->items[i].fType & MF_SEPARATOR)) { - MENU_SelectItem( hwndOwner, hmenu, i, TRUE ); + MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 ); return; } } @@ -1979,7 +2020,7 @@ static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu, submenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hsubmenu ); MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE ); - MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect ); + MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 ); if (submenu->hWnd == MENU_GetTopPopupWnd()->hwndSelf ) { @@ -2192,11 +2233,11 @@ static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id ) { /* both are top level menus (system and menu-bar) */ MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE ); - MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE ); + MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 ); pmt->hTopMenu = hPtMenu; } else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE ); - MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE ); + MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 ); } @@ -2304,7 +2345,8 @@ static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags ) if( id == NO_SELECTED_ITEM ) { MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu, - NO_SELECTED_ITEM, TRUE ); + NO_SELECTED_ITEM, TRUE, pmt->hTopMenu); + } else if( ptmenu->FocusedItem != id ) { @@ -2401,7 +2443,8 @@ static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk ) if( hNewMenu != pmt->hTopMenu ) { - MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE ); + MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, + FALSE, 0 ); if( pmt->hCurrentMenu != pmt->hTopMenu ) MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE ); } @@ -2414,7 +2457,7 @@ static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk ) } pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */ - MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE ); + MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE, 0 ); return TRUE; } @@ -2478,7 +2521,7 @@ static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags ) NO_SELECTED_ITEM ) { MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu, - prevcol, TRUE ); + prevcol, TRUE, 0 ); return; } @@ -2545,7 +2588,7 @@ static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags ) NO_SELECTED_ITEM ) { TRACE("Going to %d.\n", nextcol ); MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu, - nextcol, TRUE ); + nextcol, TRUE, 0 ); return; } @@ -2686,7 +2729,7 @@ static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, case VK_HOME: case VK_END: MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, - NO_SELECTED_ITEM, FALSE ); + NO_SELECTED_ITEM, FALSE, 0 ); /* fall through */ case VK_UP: MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, @@ -2751,7 +2794,8 @@ static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, else if (pos == (UINT)-1) MessageBeep(0); else { - MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos, TRUE ); + MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos, + TRUE, 0 ); executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags); fEndMenu = (executedMenuId != -1); } @@ -2786,7 +2830,7 @@ static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, ShowWindow( menu->hWnd, SW_HIDE ); uSubPWndLevel = 0; } - MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE ); + MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 ); SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 ); } @@ -2897,7 +2941,7 @@ void MENU_TrackKbdMenuBar( WND* wndPtr, UINT wParam, INT vkey) if( hTrackMenu ) { - MENU_SelectItem( wndPtr->hwndSelf, hTrackMenu, uItem, TRUE ); + MENU_SelectItem( wndPtr->hwndSelf, hTrackMenu, uItem, TRUE, 0 ); if( uItem == NO_SELECTED_ITEM ) MENU_MoveSelection( wndPtr->hwndSelf, hTrackMenu, ITEM_NEXT ); @@ -3315,7 +3359,7 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return FALSE; if (menu->FocusedItem == wItemID) return TRUE; MENU_HideSubPopups( hWnd, hMenu, FALSE ); - MENU_SelectItem( hWnd, hMenu, wItemID, TRUE ); + MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 ); return TRUE; } diff --git a/include/menu.h b/include/menu.h index f8c25b6ca5e..741def89956 100644 --- a/include/menu.h +++ b/include/menu.h @@ -19,5 +19,6 @@ extern void MENU_TrackMouseMenuBar( WND *wnd, INT ht, POINT pt ); extern void MENU_TrackKbdMenuBar( WND *wnd, UINT wParam, INT vkey ); extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, BOOL suppress_draw ); +extern UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget ); #endif /* __WINE_MENU_H */ diff --git a/windows/winproc.c b/windows/winproc.c index ce59de2c6cf..196f6937a40 100644 --- a/windows/winproc.c +++ b/windows/winproc.c @@ -7,6 +7,7 @@ #include #include "wine/winbase16.h" +#include "wine/winuser16.h" #include "winuser.h" #include "stackframe.h" #include "builtin16.h" @@ -20,6 +21,7 @@ #include "commctrl.h" #include "task.h" #include "thread.h" +#include "menu.h" DECLARE_DEBUG_CHANNEL(msg) DECLARE_DEBUG_CHANNEL(relay) @@ -1097,10 +1099,20 @@ INT WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32, *plparam = (LPARAM)(HMENU)HIWORD(*plparam); return 0; case WM_MENUCHAR: - case WM_MENUSELECT: *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) ); *plparam = (LPARAM)(HMENU)HIWORD(*plparam); return 0; + case WM_MENUSELECT: + if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF)) + { + HMENU hmenu=(HMENU)HIWORD(*plparam); + UINT Pos=MENU_FindSubMenu( &hmenu, wParam16); + if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */ + *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) ); + } + else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) ); + *plparam = (LPARAM)(HMENU)HIWORD(*plparam); + return 0; case WM_MDIACTIVATE: if( *plparam ) { @@ -1780,8 +1792,14 @@ INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32, (HMENU16)LOWORD(*plparam) ); *pwparam16 = (*plparam == 0); return 0; - case WM_MENUCHAR: case WM_MENUSELECT: + if(HIWORD(wParam32) & MF_POPUP) + { + UINT16 hmenu; + if((hmenu = GetSubMenu((HMENU16)*plparam, *pwparam16))) *pwparam16=hmenu; + } + /* fall through */ + case WM_MENUCHAR: *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam ); return 0; case WM_MDIACTIVATE: