private void AdjustSystemMenuForSecurity(IntPtr hmenu) { if (formState[FormStateAddedSecurityMenuItem] == 0) { formState[FormStateAddedSecurityMenuItem] = 1; SecurityMenuItem securitySystemMenuItem = new SecurityMenuItem(this); Properties.SetObject(PropSecuritySystemMenuItem, securitySystemMenuItem); NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); info.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE | NativeMethods.MIIM_DATA; info.fType = 0; info.fState = 0; info.wID = securitySystemMenuItem.ID; info.hbmpChecked = IntPtr.Zero; info.hbmpUnchecked = IntPtr.Zero; info.dwItemData = IntPtr.Zero; // Note: This code is not shipping in the final product. We do not want to measure the // : performance hit of loading the localized resource for this at startup, so I // : am hard-wiring the strings below. If you need to localize these, move them to // : a SECONDARY resource file so we don't have to contend with our big error message // : file on startup. // if (IsRestrictedWindow) { info.dwTypeData = ".NET Restricted Window..."; } else { info.dwTypeData = ".NET Window..."; } info.cch = 0; UnsafeNativeMethods.InsertMenuItem(new HandleRef(this, hmenu), 0, true, info); NativeMethods.MENUITEMINFO_T sep = new NativeMethods.MENUITEMINFO_T(); sep.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE | NativeMethods.MIIM_DATA; sep.fType = NativeMethods.MFT_MENUBREAK; UnsafeNativeMethods.InsertMenuItem(new HandleRef(this, hmenu), 1, true, sep); } }
public static extern BOOL GetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, [In, Out] NativeMethods.MENUITEMINFO_T lpmii);
public static BOOL GetMenuItemInfo(HandleRef hMenu, int uItem, bool fByPosition, NativeMethods.MENUITEMINFO_T lpmii) { BOOL result = GetMenuItemInfo(hMenu.Handle, uItem, fByPosition, lpmii); GC.KeepAlive(hMenu.Wrapper); return(result); }
public extern static bool InsertMenuItem(HandleRef hMenu, int uItem, bool fByPosition, NativeMethods.MENUITEMINFO_T lpmii);
private NativeMethods.MENUITEMINFO_T CreateMenuItemInfo() { NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); info.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE | NativeMethods.MIIM_DATA; info.fType = data.State & (STATE_BARBREAK | STATE_BREAK | STATE_RADIOCHECK | STATE_OWNERDRAW); // V7#646 - Top level menu items shouldn't have barbreak or break // bits set on them... // bool isTopLevel = false; if (menu == GetMainMenu()) { isTopLevel = true; } if (data.caption.Equals("-")) { if (isTopLevel) { data.caption = " "; info.fType |= NativeMethods.MFT_MENUBREAK; } else { info.fType |= NativeMethods.MFT_SEPARATOR; } } info.fState = data.State & (STATE_CHECKED | STATE_DEFAULT | STATE_DISABLED); info.wID = MenuID; if (IsParent) { info.hSubMenu = Handle; } info.hbmpChecked = IntPtr.Zero; info.hbmpUnchecked = IntPtr.Zero; // Assign a unique ID to this menu item object... // The ID is stored in the dwItemData of the corresponding Win32 menu item, so that when we get Win32 // messages about the item later, we can delegate to the original object menu item object. A static // hash table is used to map IDs to menu item objects. // if (uniqueID == 0) { lock(allCreatedMenuItems) { uniqueID = (uint)Interlocked.Increment(ref nextUniqueID); Debug.Assert(uniqueID >= firstUniqueID); // ...check for ID range exhaustion (unlikely!) // We add a weak ref wrapping a MenuItem to the static hash table, as supposed to adding the item // ref itself, to allow the item to be finalized in case it is not disposed and no longer referenced // anywhere else, hence preventing leaks. See bug#352644 allCreatedMenuItems.Add(uniqueID, new WeakReference(this)); } } // To check it's 32-bit OS or 64-bit OS. if (IntPtr.Size == 4) { // Store the unique ID in the dwItemData... // For simple menu items, we can just put the unique ID in the dwItemData. But for owner-draw items, // we need to point the dwItemData at an MSAAMENUINFO structure so that MSAA can get the item text. // To allow us to reliably distinguish between IDs and structure pointers later on, we keep IDs in // the 0xC0000000-0xFFFFFFFF range. This is the top 1Gb of unmananged process memory, where an app's // heap allocations should never come from. So that we can still get the ID from the dwItemData for // an owner-draw item later on, a copy of the ID is tacked onto the end of the MSAAMENUINFO structure. // if (data.OwnerDraw) info.dwItemData = AllocMsaaMenuInfo(); else info.dwItemData = (IntPtr) unchecked((int) uniqueID); } else { // On Win64, there are no reserved address ranges we can use for menu item IDs. So instead we will // have to allocate an MSAMENUINFO heap structure for all menu items, not just owner-drawn ones. info.dwItemData = AllocMsaaMenuInfo(); } // We won't render the shortcut if: 1) it's not set, 2) we're a parent, 3) we're toplevel // if (data.showShortcut && data.shortcut != 0 && !IsParent && !isTopLevel) { info.dwTypeData = data.caption + "\t" + TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString((Keys)(int)data.shortcut); } else { // Windows issue: Items with empty captions sometimes block keyboard // access to other items in same menu. info.dwTypeData = (data.caption.Length == 0 ? " " : data.caption); } info.cch = 0; return info; }
internal virtual void CreateMenuItem() { if ((data.State & STATE_HIDDEN) == 0) { NativeMethods.MENUITEMINFO_T info = CreateMenuItemInfo(); UnsafeNativeMethods.InsertMenuItem(new HandleRef(menu, menu.handle), -1, true, info); hasHandle = info.hSubMenu != IntPtr.Zero; dataVersion = data.version; menuItemIsCreated = true; if(RenderIsRightToLeft) { Menu.UpdateRtl(true); } #if DEBUG NativeMethods.MENUITEMINFO_T infoVerify = new NativeMethods.MENUITEMINFO_T(); infoVerify.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); infoVerify.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE; UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, infoVerify); #endif } }
internal void UpdateMenuItem(bool force) { if (menu == null || !menu.created) { return; } if (force || menu is MainMenu || menu is ContextMenu) { NativeMethods.MENUITEMINFO_T info = CreateMenuItemInfo(); UnsafeNativeMethods.SetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); #if DEBUG NativeMethods.MENUITEMINFO_T infoVerify = new NativeMethods.MENUITEMINFO_T(); infoVerify.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); infoVerify.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE; UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, infoVerify); #endif if (hasHandle && info.hSubMenu == IntPtr.Zero) { ClearHandles(); } hasHandle = info.hSubMenu != IntPtr.Zero; dataVersion = data.version; if (menu is MainMenu) { Form f = ((MainMenu)menu).GetFormUnsafe(); if (f != null) { SafeNativeMethods.DrawMenuBar(new HandleRef(f, f.Handle)); } } } }
internal void UpdateItemRtl(bool setRightToLeftBit) { if(!menuItemIsCreated) { return; } NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); info.fMask = NativeMethods.MIIM_TYPE | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU; info.dwTypeData = new string('\0', Text.Length + 2); info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); info.cch = info.dwTypeData.Length - 1; UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); if(setRightToLeftBit) { info.fType |= NativeMethods.MFT_RIGHTJUSTIFY | NativeMethods.MFT_RIGHTORDER; } else { info.fType &= ~(NativeMethods.MFT_RIGHTJUSTIFY | NativeMethods.MFT_RIGHTORDER); } UnsafeNativeMethods.SetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); #if DEBUG info.fMask = NativeMethods.MIIM_TYPE | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU; info.dwTypeData = new string('\0', 256); info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); info.cch = info.dwTypeData.Length - 1; UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); Debug.Assert(((info.fType & NativeMethods.MFT_RIGHTORDER) != 0) == setRightToLeftBit, "Failed to set bit!"); #endif }