获取应用程序的浮动窗口的hWnd窗口句柄的方法

huangapple go评论145阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年3月8日 19:03:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75672182.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定