-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
* FILE: user32/windows/menu.c
/* Internal MenuTrackMenu() flags */
#define TPM_INTERNAL 0xF0000000
-#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
/* Use global popup window because there's no way 2 menus can
* be tracked at the same time. */
static HWND top_popup;
+static HMENU top_popup_hmenu;
/* Flag set by EndMenu() to force an exit from menu tracking */
static BOOL fEndMenu = FALSE;
HeapFree(GetProcessHeap(), 0, ItemInfo);
}
+/***********************************************************************
+ * MenuInitSysMenuPopup
+ *
+ * Grey the appropriate items in System menu.
+ */
+void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LONG HitTest )
+{
+ BOOL gray;
+ UINT DefItem;
+ #if 0
+ MENUITEMINFOW mii;
+ #endif
+
+ gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
+ EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = ((style & WS_MAXIMIZE) != 0);
+ EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
+ EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
+ EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
+ EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = (clsStyle & CS_NOCLOSE) != 0;
+
+ /* The menu item must keep its state if it's disabled */
+ if(gray)
+ EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
+
+ /* Set default menu item */
+ if(style & WS_MINIMIZE) DefItem = SC_RESTORE;
+ else if(HitTest == HTCAPTION) DefItem = ((style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
+ else DefItem = SC_CLOSE;
+#if 0
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask |= MIIM_STATE;
+ if((DefItem != SC_CLOSE) && GetMenuItemInfoW(hmenu, DefItem, FALSE, &mii) &&
+ (mii.fState & (MFS_GRAYED | MFS_DISABLED))) DefItem = SC_CLOSE;
+#endif
+ SetMenuDefaultItem(hmenu, DefItem, MF_BYCOMMAND);
+}
+
+/******************************************************************************
+ *
+ * UINT MenuGetStartOfNextColumn(
+ * PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+static UINT MenuGetStartOfNextColumn(
+ PROSMENUINFO MenuInfo)
+{
+ PROSMENUITEMINFO MenuItems;
+ UINT i;
+
+ i = MenuInfo->FocusedItem;
+ if ( i == NO_SELECTED_ITEM )
+ return i;
+
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+ return NO_SELECTED_ITEM;
+
+ for (i++ ; i < MenuInfo->MenuItemCount; i++)
+ if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
+ return i;
+
+ return NO_SELECTED_ITEM;
+}
+
+/******************************************************************************
+ *
+ * UINT MenuGetStartOfPrevColumn(
+ * PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+
+static UINT FASTCALL MenuGetStartOfPrevColumn(
+ PROSMENUINFO MenuInfo)
+{
+ PROSMENUITEMINFO MenuItems;
+ UINT i;
+
+ if (!MenuInfo->FocusedItem || MenuInfo->FocusedItem == NO_SELECTED_ITEM)
+ return NO_SELECTED_ITEM;
+
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+ return NO_SELECTED_ITEM;
+
+ /* Find the start of the column */
+ for (i = MenuInfo->FocusedItem;
+ 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+ --i)
+ {
+ ; /* empty */
+ }
+
+ if (i == 0)
+ {
+ MenuCleanupAllRosMenuItemInfo(MenuItems);
+ return NO_SELECTED_ITEM;
+ }
+
+ for (--i; 0 != i; --i)
+ if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+ break;
+
+ MenuCleanupAllRosMenuItemInfo(MenuItems);
+ TRACE("ret %d.\n", i );
+
+ return i;
+}
+
+/***********************************************************************
+ * MenuFindSubMenu
+ *
+ * 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.
+ */
+static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
+{
+ ROSMENUINFO menu;
+ UINT i;
+ ROSMENUITEMINFO item;
+ if (((*hmenu)==(HMENU)0xffff) ||
+ (!MenuGetRosMenuInfo(&menu, *hmenu)))
+ return NO_SELECTED_ITEM;
+
+ MenuInitRosMenuItemInfo(&item);
+ for (i = 0; i < menu.MenuItemCount; i++) {
+ if (! MenuGetRosMenuItemInfo(menu.Self, i, &item))
+ {
+ MenuCleanupRosMenuItemInfo(&item);
+ return NO_SELECTED_ITEM;
+ }
+ if (!(item.fType & MF_POPUP)) continue;
+ if (item.hSubMenu == hSubTarget) {
+ MenuCleanupRosMenuItemInfo(&item);
+ return i;
+ }
+ else {
+ HMENU hsubmenu = item.hSubMenu;
+ UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget );
+ if (pos != NO_SELECTED_ITEM) {
+ *hmenu = hsubmenu;
+ return pos;
+ }
+ }
+ }
+ MenuCleanupRosMenuItemInfo(&item);
+ return NO_SELECTED_ITEM;
+}
/***********************************************************************
* MenuLoadBitmaps
DeleteObject(hFont);
}
-/***********************************************************************
- * MenuFindSubMenu
- *
- * 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.
- */
-static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
-{
- ROSMENUINFO menu;
- UINT i;
- ROSMENUITEMINFO item;
-
- if (((*hmenu)==(HMENU)0xffff) ||
- (!MenuGetRosMenuInfo(&menu, *hmenu)))
- return NO_SELECTED_ITEM;
-
- MenuInitRosMenuItemInfo(&item);
- for (i = 0; i < menu.MenuItemCount; i++)
- {
- if (! MenuGetRosMenuItemInfo(menu.Self, i, &item))
- {
- MenuCleanupRosMenuItemInfo(&item);
- return NO_SELECTED_ITEM;
- }
- if (!(item.fType & MF_POPUP)) continue;
- if (item.hSubMenu == hSubTarget) {
- MenuCleanupRosMenuItemInfo(&item);
- return i;
- }
- else {
- HMENU hsubmenu = item.hSubMenu;
- UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget );
- if (pos != NO_SELECTED_ITEM) {
- *hmenu = hsubmenu;
- return pos;
- }
- }
- }
- MenuCleanupRosMenuItemInfo(&item);
- return NO_SELECTED_ITEM;
-}
-
/***********************************************************************
* MenuFindItemByKey
*
ItemInfo = Items;
for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
{
- if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData)
+ if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData)
{
WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
do
*
* Get the size of a bitmap item.
*/
-static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size,
- HWND WndOwner)
+static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size, HWND WndOwner)
{
BITMAP bm;
HBITMAP bmp = lpitem->hbmpItem;
return;
}
- lpitem->XTab = 0;
+ lpitem->dxTab = 0;
if (lpitem->hbmpItem)
{
if( !(MenuInfo->dwStyle & MNS_NOCHECK))
lpitem->Rect.right += 2 * check_bitmap_width;
lpitem->Rect.right += 4 + MenuCharSize.cx;
- lpitem->XTab = lpitem->Rect.right;
+ lpitem->dxTab = lpitem->Rect.right;
lpitem->Rect.right += check_bitmap_width;
} else /* hbmpItem & MenuBar */ {
MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
lpitem->Rect.right += size.cx;
- if( lpitem->Text) lpitem->Rect.right += 2;
+ if( lpitem->lpstr) lpitem->Rect.right += 2;
itemheight = size.cy;
/* Special case: Minimize button doesn't have a space behind it. */
if( !(MenuInfo->dwStyle & MNS_NOCHECK))
lpitem->Rect.right += check_bitmap_width;
lpitem->Rect.right += 4 + MenuCharSize.cx;
- lpitem->XTab = lpitem->Rect.right;
+ lpitem->dxTab = lpitem->Rect.right;
lpitem->Rect.right += check_bitmap_width;
}
/* it must be a text item - unless it's the system menu */
- if (!(lpitem->fType & MF_SYSMENU) && lpitem->Text) {
+ if (!(lpitem->fType & MF_SYSMENU) && lpitem->lpstr) {
HFONT hfontOld = NULL;
RECT rc = lpitem->Rect;
LONG txtheight, txtwidth;
/* get text size after the tab */
tmpheight = DrawTextW( hdc, p, -1, &tmprc,
DT_SINGLELINE|DT_CALCRECT);
- lpitem->XTab += txtwidth;
+ lpitem->dxTab += txtwidth;
txtheight = max( txtheight, tmpheight);
txtwidth += MenuCharSize.cx + /* space for the tab */
tmprc.right - tmprc.left; /* space for the short cut */
txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
DT_SINGLELINE|DT_CALCRECT);
txtwidth = rc.right - rc.left;
- lpitem->XTab += txtwidth;
+ lpitem->dxTab += txtwidth;
}
lpitem->Rect.right += 2 + txtwidth;
itemheight = max( itemheight,
// }
maxX = max(maxX, lpitem.Rect.right);
orgY = lpitem.Rect.bottom;
- if ((lpitem.Text) && lpitem.XTab )
+ if ((lpitem.lpstr) && lpitem.dxTab )
{
- maxTab = max( maxTab, lpitem.XTab );
- maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.XTab);
+ maxTab = max( maxTab, lpitem.dxTab );
+ maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.dxTab);
}
}
if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem))
{
lpitem.Rect.right = maxX;
- if ((lpitem.Text) && 0 != lpitem.XTab)
+ if ((lpitem.lpstr) && 0 != lpitem.dxTab)
{
- lpitem.XTab = maxTab;
+ lpitem.dxTab = maxTab;
}
MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem);
}
}
/* process text if present */
- if (lpitem->Text)
+ if (lpitem->lpstr)
{
register int i = 0;
HFONT hfontOld = 0;
{
if (L'\t' == Text[i])
{
- rect.left = lpitem->XTab;
+ rect.left = lpitem->dxTab;
uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
else
{
- rect.right = lpitem->XTab;
+ rect.right = lpitem->dxTab;
uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
if (!top_popup) {
top_popup = MenuInfo.Wnd;
+ top_popup_hmenu = hmenu;
}
/* Display the window */
return TRUE;
}
+
/***********************************************************************
* MenuSelectItem
*/
else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW);
if (!top_popup) {
top_popup = hmenu->Wnd;
+ top_popup_hmenu = hmenu->Self;
}
SelectObject( hdc, hMenuFont );
if (Wnd == top_popup)
{
top_popup = NULL;
+ top_popup_hmenu = NULL;
}
break;
if (Wnd == top_popup)
{
top_popup = NULL;
+ top_popup_hmenu = NULL;
}
break;
return MenuInfo.Height;
}
-/***********************************************************************
- * MenuInitSysMenuPopup
- *
- * Grey the appropriate items in System menu.
- */
-void FASTCALL
-MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest )
-{
- BOOL Gray;
- UINT DefItem;
- #if 0
- MENUITEMINFOW mii;
- #endif
-
- Gray = 0 == (Style & WS_THICKFRAME) || 0 != (Style & (WS_MAXIMIZE | WS_MINIMIZE));
- EnableMenuItem(Menu, SC_SIZE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 != (Style & WS_MAXIMIZE);
- EnableMenuItem(Menu, SC_MOVE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 == (Style & WS_MINIMIZEBOX) || 0 != (Style & WS_MINIMIZE);
- EnableMenuItem(Menu, SC_MINIMIZE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 == (Style & WS_MAXIMIZEBOX) || 0 != (Style & WS_MAXIMIZE);
- EnableMenuItem(Menu, SC_MAXIMIZE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 == (Style & (WS_MAXIMIZE | WS_MINIMIZE));
- EnableMenuItem(Menu, SC_RESTORE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 != (ClsStyle & CS_NOCLOSE);
-
- /* The menu item must keep its state if it's disabled */
- if (Gray)
- {
- EnableMenuItem(Menu, SC_CLOSE, MF_GRAYED);
- }
-
- /* Set default menu item */
- if(Style & WS_MINIMIZE)
- {
- DefItem = SC_RESTORE;
- }
- else
- {
- if(HitTest == HTCAPTION)
- {
- DefItem = ((Style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
- }
- else
- {
- DefItem = SC_CLOSE;
- }
- }
- #if 0
- mii.cbSize = sizeof(MENUITEMINFOW);
- mii.fMask |= MIIM_STATE;
- if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
- (mii.fState & (MFS_GRAYED | MFS_DISABLED)))
- {
- DefItem = SC_CLOSE;
- }
- #endif
- SetMenuDefaultItem(Menu, DefItem, MF_BYCOMMAND);
-}
-
/***********************************************************************
* MenuShowSubPopup
*
return Ret;
}
+/**********************************************************************
+ * 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 )
+{
+ ROSMENUINFO MenuInfo;
+ BOOL Ret = FALSE;
+ if (top_popup_hmenu)
+ Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu);
+ if (Ret && hwnd == MenuInfo.WndOwner) EndMenu();
+}
+
/***********************************************************************
* MenuHideSubPopups
*
* Hide the sub-popup menus of this menu.
*/
static void FASTCALL
-MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect)
+MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo,
+ BOOL SendMenuSelect, UINT wFlags)
{
ROSMENUINFO SubMenuInfo;
ROSMENUITEMINFO ItemInfo;
TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect);
if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem)
- {
+ {
MenuInitRosMenuItemInfo(&ItemInfo);
ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE;
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)
|| 0 == (ItemInfo.fType & MF_POPUP)
|| 0 == (ItemInfo.fState & MF_MOUSESELECT))
- {
+ {
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
- }
+ }
ItemInfo.fState &= ~MF_MOUSESELECT;
ItemInfo.fMask |= MIIM_STATE;
MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo);
if (MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu))
- {
- MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE);
+ {
+ MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags);
MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL);
DestroyWindow(SubMenuInfo.Wnd);
SubMenuInfo.Wnd = NULL;
MenuSetRosMenuInfo(&SubMenuInfo);
- }
- }
+
+ if (!(wFlags & TPM_NONOTIFY))
+ SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu,
+ MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) );
+ }
+ }
}
/***********************************************************************
* Helper function for menu navigation routines.
*/
static void FASTCALL
-MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index)
+MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index, UINT wFlags)
{
ROSMENUINFO TopMenuInfo;
0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MF_POPUP))
{
/* both are top level menus (system and menu-bar) */
- MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE);
+ MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags);
MenuSelectItem(Mt->OwnerWnd, &TopMenuInfo, NO_SELECTED_ITEM, FALSE, NULL);
Mt->TopMenu = PtMenuInfo->Self;
}
else
{
- MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE);
+ MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE, wFlags);
}
MenuSelectItem(Mt->OwnerWnd, PtMenuInfo, Index, TRUE, NULL);
{
if (MenuInfo.FocusedItem != Index)
{
- MenuSwitchTracking(Mt, &MenuInfo, Index);
+ MenuSwitchTracking(Mt, &MenuInfo, Index, Flags);
}
/* If the popup menu is not already "popped" */
if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) &&
!(ItemInfo.fType & MF_SEPARATOR))
{
- MenuSwitchTracking(Mt, &MenuInfo, Index);
+ MenuSwitchTracking(Mt, &MenuInfo, Index, Flags);
if (!(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)))
Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
}
return TRUE;
}
-/******************************************************************************
- *
- * UINT MenuGetStartOfNextColumn(PROSMENUINFO MenuInfo)
- */
-static UINT MenuGetStartOfNextColumn(PROSMENUINFO MenuInfo)
-{
- UINT i;
- PROSMENUITEMINFO MenuItems;
-
- i = MenuInfo->FocusedItem;
- if (NO_SELECTED_ITEM == i)
- {
- return i;
- }
-
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
- {
- return NO_SELECTED_ITEM;
- }
-
- for (i++ ; i < MenuInfo->MenuItemCount; i++)
- {
- if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
- {
- return i;
- }
- }
-
- return NO_SELECTED_ITEM;
-}
-
-/******************************************************************************
- *
- * UINT MenuGetStartOfPrevColumn(PROSMENUINFO MenuInfo)
- */
-static UINT FASTCALL
-MenuGetStartOfPrevColumn(PROSMENUINFO MenuInfo)
-{
- UINT i;
- PROSMENUITEMINFO MenuItems;
-
- if (0 == MenuInfo->FocusedItem || NO_SELECTED_ITEM == MenuInfo->FocusedItem)
- {
- return NO_SELECTED_ITEM;
- }
-
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
- {
- return NO_SELECTED_ITEM;
- }
-
- /* Find the start of the column */
-
- for (i = MenuInfo->FocusedItem;
- 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
- --i)
- {
- ; /* empty */
- }
-
- if (0 == i)
- {
- MenuCleanupAllRosMenuItemInfo(MenuItems);
- return NO_SELECTED_ITEM;
- }
-
- for (--i; 0 != i; --i)
- {
- if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
- {
- break;
- }
- }
-
- MenuCleanupAllRosMenuItemInfo(MenuItems);
- TRACE("ret %d.\n", i );
-
- return i;
-}
-
/***********************************************************************
* MenuGetSubPopup
*
* NOTE: WM_NEXTMENU documented in Win32 is a bit different.
*/
static LRESULT FASTCALL
-MenuDoNextMenu(MTRACKER* Mt, UINT Vk)
+MenuDoNextMenu(MTRACKER* Mt, UINT Vk, UINT wFlags)
{
ROSMENUINFO TopMenuInfo;
ROSMENUINFO MenuInfo;
FALSE, 0 );
if (Mt->CurrentMenu != Mt->TopMenu)
{
- MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE);
+ MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags);
}
}
if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev))
{
- MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE);
+ MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE, Flags);
}
Mt->CurrentMenu = MenuPrev;
EndMenu = FALSE;
{
return;
}
- MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE);
+ MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE, Flags);
Mt->CurrentMenu = MenuPrev;
if (! MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu))
{
/* move menu bar selection if no more popups are left */
- if (! MenuDoNextMenu(Mt, VK_LEFT))
+ if (! MenuDoNextMenu(Mt, VK_LEFT, Flags))
{
MenuMoveSelection(Mt->OwnerWnd, &TopMenuInfo, ITEM_PREV);
}
{
if (Mt->CurrentMenu != Mt->TopMenu)
{
- MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE );
+ MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
hmenutmp = Mt->CurrentMenu = Mt->TopMenu;
}
else
}
/* try to move to the next item */
- if ( !MenuDoNextMenu(Mt, VK_RIGHT))
+ if ( !MenuDoNextMenu(Mt, VK_RIGHT, Flags))
MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT);
if ( hmenutmp || Mt->TrackFlags & TF_SUSPENDPOPUP )
if (!IsMenu(hmenu))
{
+ WARN("Invalid menu handle %p\n", hmenu);
SetLastError( ERROR_INVALID_MENU_HANDLE );
return FALSE;
}
{
if (!enterIdleSent)
{
- HWND win = (wFlags & TPM_ENTERIDLEEX) && (MenuInfo.Flags & MF_POPUP) ? MenuInfo.Wnd : NULL;
+ HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL;
enterIdleSent = TRUE;
SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win);
}
switch(msg.message)
{
- /* no WM_NC... messages in captured state */
-
- case WM_RBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- if (!(wFlags & TPM_RIGHTBUTTON)) break;
- /* fall through */
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- /* If the message belongs to the menu, removes it from the queue */
- /* Else, end menu tracking */
- fRemove = MenuButtonDown(&mt, hmenu, wFlags);
- fEndMenu = !fRemove;
- break;
+ /* no WM_NC... messages in captured state */
+
+ case WM_RBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ if (!(wFlags & TPM_RIGHTBUTTON)) break;
+ /* fall through */
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ /* If the message belongs to the menu, removes it from the queue */
+ /* Else, end menu tracking */
+ fRemove = MenuButtonDown(&mt, hmenu, wFlags);
+ fEndMenu = !fRemove;
+ break;
- case WM_RBUTTONUP:
- if (!(wFlags & TPM_RIGHTBUTTON)) break;
- /* fall through */
- case WM_LBUTTONUP:
- /* Check if a menu was selected by the mouse */
- if (hmenu)
- {
- executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+ case WM_RBUTTONUP:
+ if (!(wFlags & TPM_RIGHTBUTTON)) break;
+ /* fall through */
+ case WM_LBUTTONUP:
+ /* Check if a menu was selected by the mouse */
+ if (hmenu)
+ {
+ executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+ TRACE("executedMenuId %d\n", executedMenuId);
/* End the loop if executedMenuId is an item ID */
/* or if the job was done (executedMenuId = 0). */
- fEndMenu = fRemove = (executedMenuId != -1);
- }
- else
- {
+ fEndMenu = fRemove = (executedMenuId != -1);
+ }
/* No menu was selected by the mouse */
/* if the function was called by TrackPopupMenu, continue
with the menu tracking. If not, stop it */
- fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
- }
- break;
+ else
+ fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
- case WM_MOUSEMOVE:
- if (hmenu)
- fEndMenu |= !MenuMouseMove(&mt, hmenu, wFlags);
- break;
+ break;
- } /* switch(Msg.message) - mouse */
- }
- else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
- {
- fRemove = TRUE; /* Keyboard messages are always removed */
- switch(msg.message)
+ case WM_MOUSEMOVE:
+ /* the selected menu item must be changed every time */
+ /* the mouse moves. */
+
+ if (hmenu)
+ fEndMenu |= !MenuMouseMove( &mt, hmenu, wFlags );
+
+ } /* switch(msg.message) - mouse */
+ }
+ else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
+ {
+ fRemove = TRUE; /* Keyboard messages are always removed */
+ switch(msg.message)
{
- case WM_SYSKEYDOWN:
- case WM_KEYDOWN:
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
switch(msg.wParam)
- {
+ {
case VK_MENU:
- fEndMenu = TRUE;
- break;
+ case VK_F10:
+ fEndMenu = TRUE;
+ break;
+
case VK_HOME:
case VK_END:
- if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM,
- FALSE, 0 );
- MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
- VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo,
+ NO_SELECTED_ITEM, FALSE, 0 );
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+ VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
}
- break;
+ break;
case VK_UP:
case VK_DOWN: /* If on menu bar, pull-down the menu */
- if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- if (!(MenuInfo.Flags & MF_POPUP))
+ if (!(MenuInfo.Flags & MF_POPUP))
{
- if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
- {
- mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo,
- TRUE, wFlags);
- }
- }
- else /* otherwise try to move selection */
- {
- MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
- VK_DOWN == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
+ mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
}
+ else /* otherwise try to move selection */
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+ (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
}
- break;
+ break;
case VK_LEFT:
- MenuKeyLeft(&mt, wFlags);
- break;
+ MenuKeyLeft( &mt, wFlags );
+ break;
case VK_RIGHT:
- MenuKeyRight(&mt, wFlags);
- break;
+ MenuKeyRight( &mt, wFlags );
+ break;
case VK_ESCAPE:
- fEndMenu = MenuKeyEscape(&mt, wFlags);
- break;
+ fEndMenu = MenuKeyEscape(&mt, wFlags);
+ break;
case VK_F1:
- {
+ {
HELPINFO hi;
hi.cbSize = sizeof(HELPINFO);
hi.iContextType = HELPINFO_MENUITEM;
if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
- {
- if (MenuInfo.FocusedItem == NO_SELECTED_ITEM) hi.iCtrlId = 0;
+ {
+ if (MenuInfo.FocusedItem == NO_SELECTED_ITEM)
+ hi.iCtrlId = 0;
else
- {
+ {
MenuInitRosMenuItemInfo(&ItemInfo);
if (MenuGetRosMenuItemInfo(MenuInfo.Self,
MenuInfo.FocusedItem,
&ItemInfo))
- {
+ {
hi.iCtrlId = ItemInfo.wID;
- }
+ }
else
- {
+ {
hi.iCtrlId = 0;
- }
+ }
MenuCleanupRosMenuItemInfo(&ItemInfo);
- }
- }
+ }
+ }
hi.hItemHandle = hmenu;
hi.dwContextId = MenuInfo.dwContextHelpID;
hi.MousePos = msg.pt;
- SendMessageW(hwnd, WM_HELP, 0, (LPARAM) &hi);
+ SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
break;
- }
+ }
default:
- break;
- }
+ break;
+ }
break; /* WM_KEYDOWN */
case WM_CHAR:
PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
else mt.TrackFlags &= ~TF_SKIPREMOVE;
}
+ ERR("MenuTrackMenu 2\n");
(void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
SetCapture(NULL); /* release the capture */
{
if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
{
- MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE);
+ MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags);
if (MenuInfo.Flags & MF_POPUP)
{
SendMessageW( hWnd, WM_SETCURSOR, (WPARAM)hWnd, HTCAPTION );
+ MenuGetRosMenuInfo(&MenuInfo, hMenu);
+
if (!(wFlags & TPM_NONOTIFY))
{
SendMessageW( hWnd, WM_INITMENU, (WPARAM)hMenu, 0 );
+ /* If an app changed/recreated menu bar entries in WM_INITMENU
+ * menu sizes will be recalculated once the menu created/shown.
+ */
- MenuGetRosMenuInfo(&MenuInfo, hMenu);
-
- if (!MenuInfo.Height)
- {
- /* app changed/recreated menu bar entries in WM_INITMENU
- Recalculate menu sizes else clicks will not work */
- SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+ if (!MenuInfo.Height)
+ {
+ /* app changed/recreated menu bar entries in WM_INITMENU
+ Recalculate menu sizes else clicks will not work */
+ SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
- }
- /* This makes the menus of applications built with Delphi work.
- * 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(MenuInfo.Self == hMenu)
- {
- MenuInfo.Wnd = hWnd;
- MenuSetRosMenuInfo(&MenuInfo);
- }
+ }
}
+ /* This makes the menus of applications built with Delphi work.
+ * 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(MenuInfo.Self == hMenu)
+ {
+ MenuInfo.Wnd = hWnd;
+ MenuSetRosMenuInfo(&MenuInfo);
+ }
+
return TRUE;
}
/***********************************************************************
SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
ShowCaret(0);
top_popup = 0;
+ top_popup_hmenu = NULL;
return TRUE;
}
VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
{
HMENU hMenu = (ht == HTSYSMENU) ? NtUserGetSystemMenu( hWnd, FALSE) : GetMenu(hWnd);
- UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+ UINT wFlags = TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
UINT uItem = NO_SELECTED_ITEM;
HMENU hTrackMenu;
ROSMENUINFO MenuInfo;
- UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+ UINT wFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON;
TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", hwnd, wParam, wChar);
}
+/**********************************************************************
+ * TrackPopupMenuEx (USER32.@)
+ */
+BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
+ HWND Wnd, LPTPMPARAMS Tpm)
+{
+ BOOL ret = FALSE;
+
+ if (!IsMenu(Menu))
+ {
+ SetLastError( ERROR_INVALID_MENU_HANDLE );
+ return FALSE;
+ }
+
+ MenuInitTracking(Wnd, Menu, TRUE, Flags);
+
+ /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+ if (!(Flags & TPM_NONOTIFY))
+ SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+
+ if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
+ ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd,
+ Tpm ? &Tpm->rcExclude : NULL);
+ MenuExitTracking(Wnd);
+ return ret;
+}
+
+/**********************************************************************
+ * TrackPopupMenu (USER32.@)
+ */
+BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y,
+ int Reserved, HWND Wnd, CONST RECT *Rect)
+{
+ return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL);
+}
+
/*
* From MSDN:
* The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
return TRUE;
}
-
/*
* @implemented
*/
guii.cbSize = sizeof(GUITHREADINFO);
if(GetGUIThreadInfo(GetCurrentThreadId(), &guii) && guii.hwndMenuOwner)
{
- PostMessageW(guii.hwndMenuOwner, WM_CANCELMODE, 0, 0);
+ if (!fEndMenu &&
+ top_popup &&
+ guii.hwndMenuOwner != top_popup )
+ {
+ ERR("Capture GUI pti hWnd does not match top_popup!\n");
+ }
+ }
+
+ /* if we are in the menu code, and it is active */
+ if (!fEndMenu && top_popup)
+ {
+ /* terminate the menu handling code */
+ fEndMenu = TRUE;
+
+ /* needs to be posted to wakeup the internal menu handler */
+ /* which will now terminate the menu, in the event that */
+ /* the main window was minimized, or lost focus, so we */
+ /* don't end up with an orphaned menu */
+ PostMessageW( top_popup, WM_CANCELMODE, 0, 0);
}
return TRUE;
}
+// So this one maybe one day it will be a callback!
+BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
+ UINT wHilite )
+{
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO mii;
+ TRACE("(%p, %p, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite);
+ if (!hWnd)
+ {
+ SetLastError(ERROR_INVALID_WINDOW_HANDLE);
+ return FALSE;
+ }
+ if (!NtUserMenuItemInfo(hMenu, wItemID, wHilite, &mii, FALSE)) return FALSE;
+ if (!NtUserMenuInfo(hMenu, &MenuInfo, FALSE)) return FALSE;
+ if (MenuInfo.FocusedItem == wItemID) return TRUE;
+ MenuHideSubPopups( hWnd, &MenuInfo, FALSE, 0 );
+ MenuSelectItem( hWnd, &MenuInfo, wItemID, TRUE, 0 );
+ return TRUE;
+}
/*
* @implemented
return NtUserSetSystemMenu(hwnd, hMenu);
}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-TrackPopupMenu(
- HMENU Menu,
- UINT Flags,
- int x,
- int y,
- int Reserved,
- HWND Wnd,
- CONST RECT *Rect)
-{
- BOOL ret = FALSE;
-
- if (!IsMenu(Menu))
- {
- SetLastError( ERROR_INVALID_MENU_HANDLE );
- return FALSE;
- }
-
- MenuInitTracking(Wnd, Menu, TRUE, Flags);
-
- /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
- if (0 == (Flags & TPM_NONOTIFY))
- {
- SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
- }
-
- if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
- {
- ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, Rect);
- }
- MenuExitTracking(Wnd);
- return ret;
-}
-
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-TrackPopupMenuEx(
- HMENU Menu,
- UINT Flags,
- int x,
- int y,
- HWND Wnd,
- LPTPMPARAMS Tpm)
-{
- /* Not fully implemented */
- return TrackPopupMenu(Menu, Flags, x, y, 0, Wnd,
- NULL != Tpm ? &Tpm->rcExclude : NULL);
-}
-
//
// Example for the Win32/User32 rewrite.
// Def = TrackPopupMenuEx@24=NtUserTrackPopupMenuEx@24