我想获取屏幕上的窗口(并改变其位置)。我已经用下面的代码成功地做到了这一点。但有些应用程序有浮动窗口(例如,我的解决方案资源管理器浮动在Visual Studio之外),而且我也无法获取这些窗口的句柄。
我希望通过在WS_EX_TOOLWINDOW的if语句中返回true
来找到那些带有WS_EX_TOOLWINDOW标志的窗口。但事实并非如此。我还尝试使用user32.dll中的EnumChildWindows
。但也没有成功。
那么,如何获得我在IsAltTabWindow()
中找到的应用程序hWnd的浮动(子)窗口句柄呢?
private Snapshot()
{
EnumWindows(EvalWindow, 0);
}
internal bool EvalWindow(IntPtr hwnd, int lParam)
{
if (!IsAltTabWindow(hwnd))
{
return true;
}
// GetWindowPlacement...
}
private static bool IsAltTabWindow(IntPtr hwnd)
{
if (!IsWindowVisible(hwnd))
{
return false;
}
IntPtr extendedStyles = GetWindowLongPtr(hwnd, (-20)); // GWL_EXSTYLE
if ((extendedStyles.ToInt64() & 0x00040000) > 0) // WS_EX_APPWINDOW
{
return true;
}
if ((extendedStyles.ToInt64() & 0x00000080) > 0) // WS_EX_TOOLWINDOW
{
return false;
}
IntPtr hwndTry = GetAncestor(hwnd, GetAncestorFlags.SWP_GET_ROOT_OWNER);
IntPtr hwndWalk = IntPtr.Zero;
while (hwndTry != hwndWalk)
{
hwndWalk = hwndTry;
hwndTry = GetLastActivePopup(hwndWalk);
if (IsWindowVisible(hwndTry))
{
break;
}
}
if (hwndWalk != hwnd)
{
return false;
}
return true;
}
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
private static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
{
if (IntPtr.Size == 8)
{
return GetWindowLongPtr64(hWnd, nIndex);
}
return GetWindowLongPtr32(hWnd, nIndex);
}
[DllImport("user32.dll")]
private static extern IntPtr GetLastActivePopup(IntPtr hWnd);
[DllImport("user32.dll", ExactSpelling = true)]
private static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags gaFlags);
1条答案
按热度按时间ltqd579y1#
感谢shingo和Hans Passant的建议(两个工具都完成了这项工作),我设法找到了浮动VS窗口的句柄。在调试时,我注意到
IsAltTabWindow()
中关于GetAncestor()
的while-loop实际上返回了false,阻止了对浮动窗口的处理。所以我删除了这些行,现在浮动窗口的hWnd返回了true。我只是不知道为什么这个方法的原始作者实现了这个while循环。而且IsAltTabWindow()不是最好的方法名,因为它没有覆盖所有的窗口。但是嘿,至少我现在得到了我想要的。