我想创建一个 C++ 程序来列出我当前打开的所有窗口(例如浏览器、文件资源管理器、Discord)及其位置/尺寸。到目前为止,我已经成功地使用
EnumWindows
列出了所有窗口,但它包括许多未命名的窗口以及程序管理器、设置(我没有打开)和 NVIDIA GeForce Overlay 等内容。
如何过滤掉不在 Alt+Tab 菜单或任务栏中的窗口?
我当前的代码:
#include <windows.h>
#include <iostream>
#pragma comment(lib, "User32.lib")
BOOL CALLBACK WindowCallback(HWND hwnd, LPARAM lParam)
{
const DWORD TITLE_SIZE = 1024;
TCHAR windowTitle[TITLE_SIZE];
GetWindowText(hwnd, windowTitle, TITLE_SIZE);
std::cout << "Window: " << windowTitle << std::endl;
return TRUE;
}
int main()
{
EnumWindows(WindowCallback, NULL);
return 0;
}
MSDN 上记录了任务栏上显示的窗口:
每当应用程序创建无主窗口(即没有父窗口且具有适当的扩展样式位的窗口)时,Shell 就会在任务栏上放置一个按钮(请参阅下面的管理任务栏按钮)。要切换到窗口,用户单击其窗口按钮。自 Windows 7 起,此功能已得到极大扩展。有关更多信息,请参阅任务栏扩展。
...
每当应用程序创建不属于自己的窗口时,Shell 就会在任务栏上创建一个按钮。要确保窗口按钮放置在任务栏上,请使用
扩展样式创建一个无主窗口。要防止将窗口按钮放置在任务栏上,请使用WS_EX_APPWINDOW
扩展样式创建无主窗口。作为替代方案,您可以创建一个隐藏窗口,并使该隐藏窗口成为可见窗口的所有者。WS_EX_TOOLWINDOW
仅当窗口的样式支持可见的任务栏按钮时,Shell 才会从任务栏中删除窗口的按钮。如果您想动态地将窗口的样式更改为不支持可见任务栏按钮的窗口样式,则必须先隐藏窗口(通过使用
调用ShowWindow
),更改窗口样式,然后显示窗口。SW_HIDE
...
哪些窗口出现在 Alt-Tab 窗口中已讨论 陈雷蒙的博客:
以下是重点内容(阅读全文以了解所有详细信息):
注意:该算法的细节是实现细节。它随时可能改变,所以不要依赖它。事实上,Flip 和 Flip3D 已经改变了这一点;我在这里只是谈论经典的 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; }
...
如果你不玩疯狂的窗口风格游戏,至少这是简单的规则。创建了
和WS_EX_TOOLWINDOW
扩展样式,以便人们可以玩游戏并将其窗口放在 Alt+Tab 列表中或将其取出,即使简单的规则通常会做出相反的决定。 ...WS_EX_APPWINDOW
...
具有
扩展样式的窗口被视为不可见,即使它是可见的。具有WS_EX_TOOLWINDOW
扩展样式的窗口被视为没有所有者,即使它有。WS_EX_APPWINDOW
...