dont use ContextMenu

winforms net6 doesn't support it, and "replacement" ContextMenuStrip doesn't work for this use case, so just create a slim wrapper using CreatePopupMenu/DestroyMenu directly
This commit is contained in:
CasualPokePlayer 2023-08-04 00:54:42 -07:00
parent ba8656e345
commit ca756a2df3
2 changed files with 37 additions and 9 deletions

View File

@ -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);
}

View File

@ -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;