英文:
How to get the hWnd of a floating window of an application
问题
以下是您提供的代码部分的翻译:
我想获取(并更改)我的屏幕上的窗口位置。我已经使用下面的代码成功实现了这一点。但是一些应用程序具有浮动窗口(例如,我在Visual Studio之外拥有Solution Explorer浮动窗口),我无法获取这些窗口的句柄。
我希望通过在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;
}
// 获取窗口位置...
}
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);
请注意,翻译的文本仅包括代码部分,不包括问题或其他附加信息。
英文:
I want to get (and alter the position of) the windows on my screen. I have managed to do so with the code below. But some applications have floating windows (e.g. I have the Solution Explorer floating outside Visual Studio) and I am not getting the handles of these windows as well.
I had hoped to find those windows with the WS_EX_TOOLWINDOW flag by returning true
at the if-statement of WS_EX_TOOLWINDOW. But that wasn't the case. I also tried to use the EnumChildWindows
from the user32.dll. But also no luck.
So how do I get the handles of the floating (child) windows of the application hWnd I found with IsAltTabWindow()
?
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
得分: 0
感谢shingo和Hans Passant的建议(两种工具都起作用),我成功找到了浮动VS窗口的句柄。在调试时,我注意到IsAltTabWindow()
中的GetAncestor()
循环实际上返回了false,并阻止了对浮动窗口的处理。所以我只是删除了这些代码,现在浮动窗口的hWnd返回true。
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;
}
return true;
}
我真的不明白为什么原方法的作者要实现这个while循环。而且IsAltTabWindow()
不是最好的方法名,因为它不能覆盖所有窗口。但是,至少我现在得到了我想要的。
英文:
Thanks to the advice of both shingo and Hans Passant (both tools did the job) I managed to find the handle of the floating VS window. And while debugging I noticed that the while-loop about the GetAncestor()
in the IsAltTabWindow()
actually was returning false and prevented processing the floating windows. So I just removed those lines, and now the hWnd of the floating windows are returning true.
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;
}
return true;
}
I just don't have a clue why the original writer of the method implemented this while loop. And IsAltTabWindow() is not the best method-name, because it is not covering all windows. But hey, at least I get what I want now.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论