diff --git a/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs b/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs index 9a68609e8f..869e135227 100644 --- a/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs +++ b/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs @@ -126,12 +126,9 @@ namespace BizHawk.Client.EmuHawk.ToolExtensions var tsmiTest = new ToolStripMenuItem { Text = "&Shell Context Menu" }; tsmiTest.Click += (o, ev) => { - var tsddi = o as ToolStripDropDownItem; + var tsddi = (ToolStripDropDownItem)o; tsddi.Owner.Update(); - using var menu = new ContextMenu(); - using var dummy = new Control(); - Win32ShellContextMenu.ShowContextMenu( - hf.FullPathWithoutMember, menu.Handle, dummy.Handle, tsddi.Owner.Location.X, tsddi.Owner.Location.Y); + Win32ShellContextMenu.ShowContextMenu(hf.FullPathWithoutMember, tsddi.Owner.Handle, tsddi.Owner.Location.X, tsddi.Owner.Location.Y); }; tsdd.Items.Add(tsmiTest); } diff --git a/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs b/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs index 3b1d6dc4da..516932e9d4 100644 --- a/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs +++ b/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs @@ -237,7 +237,7 @@ namespace BizHawk.Common private IContextMenu ComInterface { get; } private IContextMenu2 ComInterface2 { get; } - private static Guid SFObject = new("3981e224-f559-11d3-8e3a-00c04f6837d5"); + private static readonly Guid SFObject = new("3981e224-f559-11d3-8e3a-00c04f6837d5"); private Win32ShellContextMenu(string path) { @@ -264,12 +264,43 @@ namespace BizHawk.Common ComInterface2 = (IContextMenu2)ComInterface; } - public static void ShowContextMenu(string path, IntPtr handle, IntPtr hwnd, int x, int y) + // TODO: ref struct when c# 10 + private class TempMenu : IDisposable + { + [DllImport("user32.dll")] + private static extern IntPtr CreatePopupMenu(); + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool DestroyMenu(IntPtr hMenu); + + public IntPtr Handle { get; private set; } + + public TempMenu() + { + Handle = CreatePopupMenu(); + if (Handle == IntPtr.Zero) + { + throw new InvalidOperationException($"{nameof(CreatePopupMenu)} returned NULL!"); + } + } + + public void Dispose() + { + if (Handle != IntPtr.Zero) + { + _ = DestroyMenu(Handle); + Handle = IntPtr.Zero; + } + } + } + + public static void ShowContextMenu(string path, IntPtr parentWindow, int x, int y) { var ctxMenu = new Win32ShellContextMenu(path); + using var menu = new TempMenu(); const int CmdFirst = 0x8000; - ctxMenu.ComInterface.QueryContextMenu(handle, 0, CmdFirst, int.MaxValue, CMF.EXPLORE); - int command = TrackPopupMenuEx(handle, TPM.TPM_RETURNCMD, x, y, hwnd, IntPtr.Zero); + ctxMenu.ComInterface.QueryContextMenu(menu.Handle, 0, CmdFirst, int.MaxValue, CMF.EXPLORE); + var command = TrackPopupMenuEx(menu.Handle, TPM.TPM_RETURNCMD, x, y, parentWindow, IntPtr.Zero); if (command > 0) { const int SW_SHOWNORMAL = 1;