I've written a Windows Explorer clone, and while it's been an adventure, most of the stuff is now working fine.
But, I have this problem: when I right-click an item and the Windows 11-style Explorer context menu appears, and I choose "Edit with <any program>", the program that opens appears behind my window. Why? How can I make it go in front and steal the focus? There's no flicker or something, so it appears it's doing that on purpose.
Here's how I invoke the command:
Dim command As IExplorerCommand = _helper.MakeComObject(commandItem.ComServerPath, commandItem.ClsId, GetType(IExplorerCommand).GUID)
' init?
Dim init As IShellExtInit = TryCast(command, IShellExtInit)
If Not init Is Nothing Then
Dim dobj As IDataObject_PreserveSig = Clipboard.GetDataObjectFor(folder, items)
init.Initialize(folder.Pidl.AbsolutePIDL, dobj, IntPtr.Zero)
End If
' set site?
Dim s As IObjectWithSite = TryCast(command, IObjectWithSite)
If Not s Is Nothing Then
Dim sp As MockServiceProvider = New MockServiceProvider()
Dim h2 As HRESULT = s.SetSite(sp)
End If
Dim bindCtx As ComTypes.IBindCtx = Nothing
Functions.CreateBindCtx(0, bindCtx)
command.Invoke(array, Marshal.GetIUnknownForObject(bindCtx))
If you want to see some live action, the code is at https://github.com/lailablomme/Laila.Shell . The Windows 11-style Explorer menu code is in /Laila.Shell/Controls/ExplorerMenu.vb
.
Please note that when you want to run the application and see this menu, you need to run the project "Laila.Shell.SampleApp2.Package", so that it runs under an AppX context, otherwise it will revert to the default context menu.
Windows restricts which processes can get and can set the foreground window to prevent focus stealing, for security and end-user experience reasons mostly. The quite complex rules are detailed here: AllowSetForegroundWindow function Remarks
But what's interesting is a process that can set the foreground window can enable another process to set the foreground window by calling AllowSetForegroundWindow
, which is what you want.
In your case, you don't know which (future) process will need the focus, so you can call AllowSetForegroundWindow(ASFW_ANY)
so all processes will be enabled to set the foreground window.