枚举像alt-tab这样的窗口

我正在创build一个替代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; } 

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

这其实很简单,尽pipe几乎没有任何事情可以自己猜测。 注意:这个algorithm的细节是一个实现细节。 它可以在任何时候改变,所以不要依靠它。 事实上,它已经改变了Flip和Flip3D; 我只是在这里谈论经典的Alt + Tab窗口。

对于每个可见的窗口,走上它的所有者链,直到find根拥有者。 然后回到可见的最后一个活动popup链,直到find一个可见的窗口。 如果你回到你开始的地方,然后把窗口放在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; } 

点击链接陈的博客条目了解更多细节和一些angular落的条件。

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

但是也有一些例外,Windows Live Messenger在windows下创build阴影等方面有很多窍门:@

这里是我完整的代码,已经使用了一天,并没有注意到与真正的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); }