在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