在ahk论坛中发现了一个获取资源管理器当前标签页的解决方案:
大致方法是根据Tab控件的hwnd来判断哪个Shell.Application窗口是当前标签页
不知道在Quicker中能不能实现
仔细研究了一下,大致明白了具体的实现方法。由于没有C#的调试环境就用了powershell。
在Shell.Application
层面,不同tab的hwnd是相同的
但tab各个控件的hwnd是不同的,可以通过IShellBrowser
从Shell.Application
对象中提取出对应tab控件的hwnd:
#powershell Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; [ComImport] [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ComServiceProvider { [return: MarshalAs(UnmanagedType.IUnknown)] Object QueryService(ref Guid guidService, ref Guid riid); } [ComImport] [Guid("000214e2-0000-0000-c000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IShellBrowser { IntPtr GetWindow(); } "@ $w=(New-Object -ComObject Shell.Application).Windows()[0] #<-使用其他下标获取其他窗口 $shellBrowser = [ComServiceProvider].GetMethod('QueryService').Invoke($w, @([guid]'4c96be40-915c-11cf-99d3-00aa004ae837', [guid]'000214e2-0000-0000-c000-000000000046')) $tabHwnd=[IShellBrowser].GetMethod('GetWindow').Invoke($shellBrowser, @())
同时,可以通过user32
的EnumChildWindows()
来列出某个explore窗口各个控件的hwnd
Add-Type @" using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Text; public class APIFuncs { [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); public static List<IntPtr> GetChildWindows(IntPtr parent) { List<IntPtr> result = new List<IntPtr>(); GCHandle listHandle = GCHandle.Alloc(result); try { EnumWindowProc childProc = new EnumWindowProc(EnumWindow); EnumChildWindows(parent, childProc,GCHandle.ToIntPtr(listHandle)); } finally { if (listHandle.IsAllocated) listHandle.Free(); } return result; } private static bool EnumWindow(IntPtr handle, IntPtr pointer) { GCHandle gch = GCHandle.FromIntPtr(pointer); List<IntPtr> list = gch.Target as List<IntPtr>; if (list == null) { throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); } list.Add(handle); // You can modify this to check to see if you want to cancel the operation, then return a null here return true; } public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); } "@ [apifuncs]::GetChildWindows($w.HWND)
这里会列出所有的控件,可以根据控件的名称ShellTabWindowClass1
来筛选Tab控件
控件的顺序会随着当前Tab而改变,排在最前面的ShellTabWindowClass1
控件hwnd就是当前激活tab的hwnd
这样就可以得到当前窗口的活动tab了
https://getquicker.net/Help/Versions 发了一个版本,试下看看
谢谢C大,资源管理器标签页终于能正常使用了😂
不过想问一下从Shell.Application Window获取Tab控件hwnd的操作怎么能移植到表达式内?我有个利用Shell操作选中文件的子程序需要获取到当前Tab的Shell.Application Window。后半部分获取活动Tab控件hwnd的话可以直接从Quicker的 获取窗口信息/查找窗口 查找子窗口/控件 动作来获得,不知道前半部分能不能直接在表达式里实现?
1.36.2 增加了设置选中文件的操作,可以试下看看。 https://getquicker.net/Help/Versions