@jondinham 提供的answer 对我来说非常有效。所以我想出了自己的解决方案。
1.我以前的解决方案遇到的问题
在 Windows 10 家庭版 1909 上运行。我得到了两个额外的意外 Windows“计算器”和“设置”。
另外,无法检测到Tencent QQ的窗口,原因如下:
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
不过,我觉得这个bug可能是腾讯QQ的特殊性造成的,我什至不能用DeferWindowPos把它的窗口置顶。
也许有人可以帮助我弄清楚为什么会发生这种情况并帮助改进@jondinham 以前的解决方案。
2.我的解决方案
我尝试检查窗口的图标,并过滤掉没有自己图标或使用与系统默认图标相同的图标的窗口。我使用来自answer 和answer 的代码sn-ps 并进行一些修改。这个解决方案对我来说效果很好。
HICON get_windows_HICON_critical(HWND hwnd)
{
// Get the window icon
HICON icon = reinterpret_cast<HICON>(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
if (icon == 0) {
// Alternative method. Get from the window class
icon = reinterpret_cast<HICON>(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
}
// Alternative method: get the first icon from the main module (executable image of the process)
if (icon == 0) {
icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// // Alternative method. Use OS default icon
// if (icon == 0) {
// icon = ::LoadIcon(0, IDI_APPLICATION);
// }
if(icon == ::LoadIcon(0, IDI_APPLICATION)){
// Filter out those with default icons
icon = 0;
}
return icon;
}
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
HICON icon = get_windows_HICON_critical(hWnd);
if(icon!=0){
std::cout << hWnd << ": " << windowTitle << std::endl;
}
}
return TRUE;
}
3.我的解决方案存在问题
我的解决方案不能处理Windows Store APP,根据this question.