diff --git a/UnitTests/Windows.Shell/ShellContextMenuTests.cs b/UnitTests/Windows.Shell/ShellContextMenuTests.cs index cb46eb88..595d8ebb 100644 --- a/UnitTests/Windows.Shell/ShellContextMenuTests.cs +++ b/UnitTests/Windows.Shell/ShellContextMenuTests.cs @@ -16,15 +16,15 @@ namespace Vanara.Windows.Shell.Tests [Test] public void CreateTest() { - using var shi = new ShellItem(TestCaseSources.WordDoc); + using var shi = ShellItem.Open(TestCaseSources.TempDir); using var menu = new ShellContextMenu(shi); - var items = menu.GetItems(); + var items = menu.GetItems(CMF.CMF_EXTENDEDVERBS | CMF.CMF_EXPLORE | CMF.CMF_CANRENAME | CMF.CMF_ITEMMENU); for (var i = 0; i < items.Length; i++) ShowMII(items[i], i); static void ShowMII(ShellContextMenu.MenuItemInfo mii, int c, int indent = 0) { - System.Diagnostics.Debug.WriteLine($"{new string(' ', indent * 3)}{c + 1}) \"{mii.Text}\" (#{mii.Id}) - Type={mii.Type}; State={mii.State}; Verb={mii.Verb}; Tooltip={mii.HelpText}; IconLoc={mii.VerbIconLocation}"); + TestContext.WriteLine($"{new string(' ', indent * 3)}{c + 1}) \"{mii.Text}\" (#{mii.Id}) - Type={mii.Type}; State={mii.State}; Verb={mii.Verb}; Tooltip={mii.HelpText}; IconLoc={mii.VerbIconLocation}"); for (int j = 0; j < mii.SubMenus.Length; j++) ShowMII(mii.SubMenus[j], j, indent + 1); } diff --git a/Windows.Shell/ShellObjects/ShellContextMenu.cs b/Windows.Shell/ShellObjects/ShellContextMenu.cs index 209a2925..79a6c255 100644 --- a/Windows.Shell/ShellObjects/ShellContextMenu.cs +++ b/Windows.Shell/ShellObjects/ShellContextMenu.cs @@ -39,7 +39,7 @@ namespace Vanara.Windows.Shell internal const int m_CmdFirst = 0x8000; private readonly IContextMenu2 m_ComInterface2; private readonly IContextMenu3 m_ComInterface3; - private readonly MessageWindow m_MessageWindow; + private readonly BasicMessageWindow m_MessageWindow; private bool disposedValue; static ShellContextMenu() => Ole32.OleInitialize(default); // Not sure why necessary, but it fails without @@ -75,10 +75,20 @@ namespace Vanara.Windows.Shell } } + //using var ppidls = new PinnedObject(pidls); + //var dcm = new DEFCONTEXTMENU + //{ + // psf = parent.IShellFolder, + // apidl = ppidls, + // cidl = (uint)pidls.Length, + + //}; + //SHCreateDefaultContextMenu(ref dcm, typeof(IContextMenu).GUID, out var ppv).ThrowIfFailed(); + //ComInterface = (IContextMenu)ppv; ComInterface = parent.IShellFolder.GetUIObjectOf(HWND.NULL, pidls); m_ComInterface2 = ComInterface as IContextMenu2; m_ComInterface3 = ComInterface as IContextMenu3; - m_MessageWindow = new MessageWindow(this); + m_MessageWindow = new BasicMessageWindow(WindowMessageFilter); } /// Finalizes an instance of the class. @@ -123,48 +133,28 @@ namespace Vanara.Windows.Shell return MenuItemInfo.GetMenuItems(hmenu, this); } - /// Handles context menu messages when the is displayed on a Form's main menu bar. - /// - /// - /// To display a shell context menu in a Form's main menu, call the Populate(Menu, CMF) method to populate the menu with the - /// shell item's menu items. In addition, you must intercept a number of special messages that will be sent to the menu's parent - /// form. To do this, you must override like so: - /// - /// - ///protected override void WndProc(ref Message m) { - ///if ((m_ContextMenu == null) || (!m_ContextMenu.HandleMenuMessage(ref m))) { - ///base.WndProc(ref m); - ///} - ///} - /// - /// Where m_ContextMenu is the being shown. - /// - /// The message to handle. - /// - /// if the message was a Shell Context Menu message, if not. If the method returns - /// false, then the message should be passed down to the base class's method. - /// - public bool HandleMenuMessage(ref Message m) + private bool WindowMessageFilter(HWND hwnd, uint msg, IntPtr wParam, IntPtr lParam, out IntPtr lReturn) { + lReturn = default; try { - if ((m.Msg == (int)WindowMessage.WM_COMMAND) && ((int)m.WParam >= m_CmdFirst)) + if ((msg == (uint)WindowMessage.WM_COMMAND) && ((int)wParam >= m_CmdFirst)) { - InvokeCommand((int)m.WParam - m_CmdFirst); + InvokeCommand((int)wParam - m_CmdFirst); return true; } else { - if (m_ComInterface3 != null) + if (m_ComInterface3 is not null) { - m_ComInterface3.HandleMenuMsg2((uint)m.Msg, m.WParam, m.LParam, out IntPtr result); - m.Result = result; + if (m_ComInterface3.HandleMenuMsg2(msg, wParam, lParam, out var lRet).Succeeded) + lReturn = lRet; return true; } - else if (m_ComInterface2 != null) + else if (m_ComInterface2 is not null) { - m_ComInterface2.HandleMenuMsg((uint)m.Msg, m.WParam, m.LParam); - m.Result = IntPtr.Zero; + if (m_ComInterface2.HandleMenuMsg(msg, wParam, lParam).Succeeded) + lReturn = default; return true; } } @@ -322,6 +312,7 @@ namespace Vanara.Windows.Shell // TODO: dispose managed state (managed objects) } + m_MessageWindow?.Dispose(); Marshal.ReleaseComObject(ComInterface); ComInterface = null; disposedValue = true; @@ -539,20 +530,5 @@ namespace Vanara.Windows.Shell return SubMenus; } } - - private class MessageWindow : Control - { - private readonly ShellContextMenu m_Parent; - - public MessageWindow(ShellContextMenu parent) => m_Parent = parent; - - protected override void WndProc(ref Message m) - { - if (!m_Parent.HandleMenuMessage(ref m)) - { - base.WndProc(ref m); - } - } - } } } \ No newline at end of file