windows 如何获取应用程序浮动窗口的hWnd

yeotifhr  于 2023-03-13  发布在  Windows
关注(0)|答案(1)|浏览(225)

我想获取屏幕上的窗口(并改变其位置)。我已经用下面的代码成功地做到了这一点。但有些应用程序有浮动窗口(例如,我的解决方案资源管理器浮动在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);
ltqd579y

ltqd579y1#

感谢shingo和Hans Passant的建议(两个工具都完成了这项工作),我设法找到了浮动VS窗口的句柄。在调试时,我注意到IsAltTabWindow()中关于GetAncestor()的while-loop实际上返回了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()不是最好的方法名,因为它没有覆盖所有的窗口。但是嘿,至少我现在得到了我想要的。

相关问题