枚举像alt-tab这样的窗口

27 c# windows winapi

我正在创建一个alt-tab替代Vista,但我列出了所有活动程序的一些问题.

我正在使用EnumWindows获取Windows列表,但这个列表很大.当我只打开10个窗户时,它包含大约400个项目.对于每一个控件和许多其他东西来说,它似乎都是一个蠢货.

因此,我必须以某种方式过滤此列表,但我无法像alt-tab那样完全执行此操作.

这是我现在用来过滤列表的代码.它工作得很好,但我得到了一些不需要的窗口,如Visual Studio中的独立工具窗口,我也想念iTunes和Warcraft3等窗口.

private bool ShouldWindowBeDisplayed(IntPtr window)
{
    uint windowStyles = Win32.GetWindowLong(window, GWL.GWL_STYLE);

    if (((uint)WindowStyles.WS_VISIBLE & windowStyles) != (uint)WindowStyles.WS_VISIBLE ||
        ((uint)WindowExStyles.WS_EX_APPWINDOW & windowStyles) != (uint)WindowExStyles.WS_EX_APPWINDOW)
    {
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*urr 24

Raymond Chen回答了这个问题(http://blogs.msdn.com/oldnewthing/archive/2007/10/08/5351207.aspx):

它实际上非常简单,尽管你自己几乎没有任何猜测.注意:此算法的详细信息是实现细节.它可以随时改变,所以不要依赖它.事实上,Flip和Flip3D已经改变了; 我刚才在这里谈论Classic Alt + Tab窗口.

对于每个可见窗口,向上走其所有者链,直到找到根所有者.然后沿着可见的最后一个活动弹出链向后走,直到找到一个可见的窗口.如果您回到启动的位置,请将窗口置于Alt + Tab列表中.在伪代码中:

BOOL IsAltTabWindow(HWND hwnd)
{
 // Start at the root owner
 HWND hwndWalk = GetAncestor(hwnd, GA_ROOTOWNER);

 // See if we are the last active visible popup
 HWND hwndTry;
 while ((hwndTry = GetLastActivePopup(hwndWalk)) != hwndTry) {
  if (IsWindowVisible(hwndTry)) break;
  hwndWalk = hwndTry;
 }
 return hwndWalk == hwnd;
}
Run Code Online (Sandbox Code Playgroud)

请点击陈的博客文章链接,了解更多详情和一些角落条件.

  • 这是一个基于此方法的更完整和强大的示例https://github.com/christianrondeau/GoToWindow/blob/e41b822e7254fdc40a40fbbeec251e6ffc1959f8/GoToWindow.Api/WindowsListFactory.cs#L45这是来自另一个alt-tab实用程序,它似乎准确显示常规的alt-tab菜单. (3认同)
  • 要检测 UWP 应用程序,请检查“ApplicationFrameWindow”窗口类名,然后使用“DwmGetWindowAttribute(LHWindow, DWMWA_CLOAKED, @cloaked, sizeof(Cardinal))”对其进行评估,如果“cloacked”(整数)返回 0,则意味着 UWP 应用程序未隐藏。 (2认同)

小智 11

谢谢Mike B.来自Raymonds博客的例子向我指出了正确的方向.

然而,有一些例外情况需要做,Windows Live Messenger在Windows等下创建阴影有很多黑客攻击:@

这是我的完整代码,现在已经使用了一天,并没有注意到真正的alt选项卡有任何差异.有一些底层代码没有发布,但它确定它的作用是没有问题的.:)

    private static bool KeepWindowHandleInAltTabList(IntPtr window)
    {
        if (window == Win32.GetShellWindow())   //Desktop
            return false;

        //http://stackoverflow.com/questions/210504/enumerate-windows-like-alt-tab-does
        //http://blogs.msdn.com/oldnewthing/archive/2007/10/08/5351207.aspx
        //1. For each visible window, walk up its owner chain until you find the root owner. 
        //2. Then walk back down the visible last active popup chain until you find a visible window.
        //3. If you're back to where you're started, (look for exceptions) then put the window in the Alt+Tab list.
        IntPtr root = Win32.GetAncestor(window, Win32.GaFlags.GA_ROOTOWNER);

        if (GetLastVisibleActivePopUpOfWindow(root) == window)
        {
            WindowInformation wi = new WindowInformation(window);

            if (wi.className == "Shell_TrayWnd" ||                          //Windows taskbar
                wi.className == "DV2ControlHost" ||                         //Windows startmenu, if open
                (wi.className == "Button" && wi.windowText == "Start") ||   //Windows startmenu-button.
                wi.className == "MsgrIMEWindowClass" ||                     //Live messenger's notifybox i think
                wi.className == "SysShadow" ||                              //Live messenger's shadow-hack
                wi.className.StartsWith("WMP9MediaBarFlyout"))              //WMP's "now playing" taskbar-toolbar
                return false;

            return true;
        }
        return false;
    }

    private static IntPtr GetLastVisibleActivePopUpOfWindow(IntPtr window)
    {
        IntPtr lastPopUp = Win32.GetLastActivePopup(window);
        if (Win32.IsWindowVisible(lastPopUp))
            return lastPopUp;
        else if (lastPopUp == window)
            return IntPtr.Zero;
        else
            return GetLastVisibleActivePopUpOfWindow(lastPopUp);
    }
Run Code Online (Sandbox Code Playgroud)

  • 'WindowInformation'来自哪里?我用Google搜索了很多方法,并没有认出任何有用的东西.它是自定义类型吗? (5认同)