Happy to announce that I have figured it out !
Key insight came from : https://github.com/eythaann/Seelen-UI/blob/b5581ab5e714b4e69e7d6fb8b871ab37e094dea3/src/background/modules/tray/application.rs#L442
Where I observed that the IUIAutomationElement3
had a method named ShowContextMenu(). I had seen this before but having never dealt with COM objects before I didnt know how to use it. Also I noticed in their implementation that they are using ShowWindowAsync(hWnd_Overflow, 5)
once and that is enough for ShowContextMenu()
to work. Turns out you dont need the window to be actually visible inorder for ShowContextMenu()
. And then they are hiding it just like in the question.
A nice blog on UIAutomationClient : https://scorpiosoftware.net/2024/03/26/the-power-of-ui-automation/
And the interop library on nuget (You can also do without it by adding a COM reference using Visual Studio) : https://www.nuget.org/packages/Interop.UIAutomationClient.Signed#versions-body-tab
So here's my implementation:
using System.Runtime.InteropServices;
using Interop.UIAutomationClient;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string className, string windowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string className, string windowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern int ShowWindowAsync(IntPtr hWnd, int nCmdShow)
void Main()
{
IntPtr hWnd_Outer = FindWindow("TopLevelWindowForOverflowXamlIsland", null);
IntPtr hWnd_Inner = FindWindowEx(hWnd_Outer, IntPtr.Zero, "Windows.UI.Composition.DesktopWindowContentBridge", null);
CUIAutomation ui = new();
const int classPropertyId = 30012;
var innerIconContainer = ui.ElementFromHandle(hWnd_Inner);
var icons = innerIconContainer.FindAll(TreeScope.TreeScope_Children, ui.CreateTrueCondition());
var icon = icons.GetElement(6) as IUIAutomationElement3;
ShowWindowAsync(hWnd_Outer, 5);
icon.ShowContextMenu();
ShowWindowAsync(hWnd_Outer, 0)
}
And the result: