C# 像alt tab一样枚举窗口
我正在为Vista创建替换的alt选项卡,但在列出所有活动程序时遇到一些问题 我正在使用EnumWindows获取一个窗口列表,但是这个列表很大。当我只打开10个窗口时,它包含大约400个项目。它似乎是一个hwnd为每一个单一的控制和许多其他东西 因此,我必须以某种方式筛选此列表,但我无法完全按照alt tab的方式进行筛选 这是我现在用来过滤列表的代码。它工作得很好,但我有一些不需要的窗口,比如VisualStudio中的分离工具窗口,我也怀念iTunes和Warcraft3等窗口C# 像alt tab一样枚举窗口,c#,windows,winapi,C#,Windows,Winapi,我正在为Vista创建替换的alt选项卡,但在列出所有活动程序时遇到一些问题 我正在使用EnumWindows获取一个窗口列表,但是这个列表很大。当我只打开10个窗口时,它包含大约400个项目。它似乎是一个hwnd为每一个单一的控制和许多其他东西 因此,我必须以某种方式筛选此列表,但我无法完全按照alt tab的方式进行筛选 这是我现在用来过滤列表的代码。它工作得很好,但我有一些不需要的窗口,比如VisualStudio中的分离工具窗口,我也怀念iTunes和Warcraft3等窗口 priva
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;
}
陈雷蒙不久前回答了这个问题
(): 其实很简单 你几乎猜不到什么 靠你自己。注:详情如下: 算法是一种实现 细节它可以随时改变,所以 不要依赖它。事实上,它已经存在了 使用Flip和Flip3D进行更改;我只是 谈论经典的Alt+Tab 这里是窗户 对于每个可见窗口,向上走 所有者链,直到找到根为止 主人。然后,沿着可见的道路往回走 最后一个激活的弹出链,直到找到 可见的窗口。如果你回到家里 从哪里开始,然后把 在Alt+选项卡列表中的窗口。在里面 伪代码: 有关更多详细信息和一些转角条件,请点击陈的博客链接。谢谢Mike B。 Raymonds博客上的例子为我指明了正确的方向 不过,也有一些例外情况,Windows Live messenger因在Windows下创建阴影等而遭到大量黑客攻击:@ 这是我的完整代码,我已经用了一天了,没有注意到它和真正的alt标签有什么不同。有一些底层代码没有发布,但弄清楚它的功能并没有问题。:)
这是pascal/delphi中的一个函数,您可以轻松地将其转换为C 它包括对Windows 10应用程序的支持
EnumWindows(@ListApps,0);
函数ListApps(LHWindow:HWND;lParam:Pointer):布尔;stdcall;
变量
lhnd;
LH父母:HWND;
词汇风格:德沃德;
AppClassName:字符的数组[0..255];
斗篷:红衣主教;
titlelen:整数;
标题:字符串;
开始
LHDesktop:=GetDesktopWindow;
GetClassName(LHWindow,AppClassName,255);
LHParent:=GetWindowLong(LHWindow,GWL\uHwndParent);
LExStyle:=GetWindowLong(LHWindow,GWL_EXSTYLE);
如果AppClassName='ApplicationFrameWindow',则
DwmGetWindowAttribute(左窗,DWMWA_斗篷,@斗篷,sizeof(红衣主教))
其他的
隐身:=DWM_普通_应用_未隐身;
如果IsWindow可见(LHWindow)
和(AppClassName'Windows.UI.Core.CoreWindow')
和((隐身=DWM_未隐身)或(隐身=DWM_正常_应用_未隐身))
和((LHParent=0)或(LHParent=LHDesktop))
和(应用程序。HandleLHWindow)
和((LExStyle和WS_-EX_-TOOLWINDOW=0)或(LExStyle和WS_-EX_-APPWINDOW 0))
然后
开始
titlelen:=GetWindowTextLength(LHWindow);
设置长度(标题、标题栏);
GetWindowText(LHWindow,PChar(标题),标题栏+1);
{将每个添加到列表中}
但是.ListBox1.Items.Add(title);
{也将每个HWND添加到列表中,稍后使用SwitchToThisWindow切换}
{ ... }
结束;
结果:=真;
结束;
干得好vhanla。我的Pascal有点生疏,但你的解决方案帮了大忙。我是新手,所以请原谅我的代码和/或表达方式。答案相对简单
要创建Alt选项卡窗口列表,似乎需要三个条件
1) 窗口必须可见-使用GetWindowVisible
2) 窗口不能是工具栏窗口-使用GetWindowInfo
3) 不得遮盖车窗-使用DwmGetWindowAttribute
我不认为你需要看类名。我认为WS_EX_APPWINDOW标志经常会失败(例如Chrome)——即使与WS_EX_TOOLWINDOW一起使用也是如此。也。。。如果在顶层枚举窗口,我认为不需要查看父窗口
public static bool IsAltTabWindow(IntPtr hWnd)
{
const uint WS_EX_TOOLWINDOW = 0x00000080;
const uint DWMWA_CLOAKED = 14;
// It must be a visible Window
if (!IsWindowVisible(hWnd)) return false;
// It must not be a Tool bar window
WINDOWINFO winInfo = new WINDOWINFO(true);
GetWindowInfo(hWnd, ref winInfo);
if ((winInfo.dwExStyle & WS_EX_TOOLWINDOW) != 0) return false;
// It must not be a cloaked window
uint CloakedVal;
DwmGetWindowAttribute(hWnd, DWMWA_CLOAKED, out CloakedVal, sizeof(uint));
return CloakedVal == 0;
}
“窗口信息”来自哪里?我已经用谷歌搜索了很多方法,但没有发现任何有用的东西。它是自定义类型吗?您可以使用:请注意,此实现不支持Raymond的博客文章中提到的
WS_EX_TOOLWINDOW
和WS_EX_APPWINDOW
扩展样式。这里有一个基于此方法的更完整和健壮的示例,它来自另一个alt tab实用程序,这似乎准确地显示了常规alt选项卡菜单的功能。要检测UWP应用程序,请检查“ApplicationFrameWindow”窗口类名称,然后使用dwmGetWindow属性(LHWindow,DWMWA_斗篷,@斗篷,sizeof(基数))
对其进行求值,如果cloacked
(整数)返回0,则表示UWP应用程序未隐藏。
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);
}
public static bool IsAltTabWindow(IntPtr hWnd)
{
const uint WS_EX_TOOLWINDOW = 0x00000080;
const uint DWMWA_CLOAKED = 14;
// It must be a visible Window
if (!IsWindowVisible(hWnd)) return false;
// It must not be a Tool bar window
WINDOWINFO winInfo = new WINDOWINFO(true);
GetWindowInfo(hWnd, ref winInfo);
if ((winInfo.dwExStyle & WS_EX_TOOLWINDOW) != 0) return false;
// It must not be a cloaked window
uint CloakedVal;
DwmGetWindowAttribute(hWnd, DWMWA_CLOAKED, out CloakedVal, sizeof(uint));
return CloakedVal == 0;
}