Win10中的EnumWindows函数仅枚举桌面应用程序

问题描述 投票:0回答:2

EnumWindows 上的文档下划线:

注意 对于 Windows 8 及更高版本,EnumWindows 仅枚举桌面应用程序的顶级窗口。

“桌面应用程序”“非桌面应用程序” 有什么区别?

这与

地铁应用程序有关吗?

我问这个问题是因为与 Win7 相比,

EnumWindows 在 Win10 中的表现有些不同。

c# windows windows-10 pinvoke
2个回答
9
投票
另一个解决方案是使用 win32u.dll 中未记录的 api,它的原型是:

NTSTATUS WINAPI NtUserBuildHwndList ( HDESK in_hDesk, HWND in_hWndNext, BOOL in_EnumChildren, BOOL in_RemoveImmersive, DWORD in_ThreadID, UINT in_Max, HWND *out_List, UINT *out_Cnt );

将其传递到具有 Max 条目的 HWND 列表中,将所有其他参数设置为零,输出 Cnt 给出返回条目的数量。如果结果代码为 STATUS_BUFFER_TOO_SMALL,则重新分配包含更多条目的列表,然后重试。

与Win10之前的版本相比,增加了参数RemoveImmersive。如果为 TRUE,则相同的列表将作为 EnumWindows 返回(没有沉浸式窗口)。如果为 FALSE,则返回完整列表。

列表的第一个条目是 0x00000001 作为句柄,必须被忽略。

此 api 的优点是在调用 FindWIndowEx 期间不可能更改窗口列表(在构建列表期间设置锁定)

EnumWindows、EnumDesktopWindows、EnumChildWindows、FindWindow、FindWindowEx 都使用此 api。

特此请求 Microsoft 添加公共 api EnumWindowsEx 或 EnumAllWindows,以便开发人员有一个安全的方法来枚举所有窗口。据我所知,他们将过滤器添加到 EnumWindows 中以修复自定义任务列表,这些任务列表显示可见但隐藏的沉浸式/metro/uwp 窗口。但应该支持开发者获取完整列表的方法。

更新:有关如何使用此 api 的示例,InitWin32uDLL 执行 win32u.dll 的运行时加载,lib_NtUserBuildHwndListW10 是 GetProcAddress 指针

/********************************************************/ /* enumerate all top level windows including metro apps */ /********************************************************/ BOOL Gui_RealEnumWindows(WNDENUMPROC in_Proc, LPARAM in_Param) { /* locals */ INT lv_Cnt; HWND lv_hWnd; BOOL lv_Result; HWND lv_hFirstWnd; HWND lv_hDeskWnd; HWND *lv_List; // only needed in Win8 or later if (gv_SysInfo.Basic.OsVersionNr < OSVER_WIN8) return EnumWindows(in_Proc, in_Param); // no error yet lv_Result = TRUE; // first try api to get full window list including immersive/metro apps lv_List = _Gui_BuildWindowList(0, 0, 0, 0, 0, &lv_Cnt); // success? if (lv_List) { // loop through list while (lv_Cnt-- > 0 && lv_Result) { // get handle lv_hWnd = lv_List[lv_Cnt]; // filter out the invalid entry (0x00000001) then call the callback if (IsWindow(lv_hWnd)) lv_Result = in_Proc(lv_hWnd, in_Param); } // free the list MemFree(lv_List); } else { // get desktop window, this is equivalent to specifying NULL as hwndParent lv_hDeskWnd = GetDesktopWindow(); // fallback to using FindWindowEx, get first top-level window lv_hFirstWnd = FindWindowEx(lv_hDeskWnd, 0, 0, 0); // init the enumeration lv_Cnt = 0; lv_hWnd = lv_hFirstWnd; // loop through windows found // - since 2012 the EnumWindows API in windows has a problem (on purpose by MS) // that it does not return all windows (no metro apps, no start menu etc) // - luckally the FindWindowEx() still is clean and working while (lv_hWnd && lv_Result) { // call the callback lv_Result = in_Proc(lv_hWnd, in_Param); // get next window lv_hWnd = FindWindowEx(lv_hDeskWnd, lv_hWnd, 0, 0); // protect against changes in window hierachy during enumeration if (lv_hWnd == lv_hFirstWnd || lv_Cnt++ > 10000) break; } } // return the result return lv_Result; } HWND *_Gui_BuildWindowList ( HDESK in_hDesk, HWND in_hWnd, BOOL in_EnumChildren, BOOL in_RemoveImmersive, UINT in_ThreadID, INT *out_Cnt ) { /* locals */ UINT lv_Max; UINT lv_Cnt; UINT lv_NtStatus; HWND *lv_List; // is api not supported? if (!InitWin32uDLL()) return NULL; // initial size of list lv_Max = 512; // retry to get list for (;;) { // allocate list if ((lv_List = (HWND*)MemAlloc(lv_Max*sizeof(HWND))) == NULL) break; // call the api lv_NtStatus = lib_NtUserBuildHwndListW10( in_hDesk, in_hWnd, in_EnumChildren, in_RemoveImmersive, in_ThreadID, lv_Max, lv_List, &lv_Cnt); // success? if (lv_NtStatus == NOERROR) break; // free allocated list MemFree(lv_List); // clear lv_List = NULL; // other error then buffersize? or no increase in size? if (lv_NtStatus != STATUS_BUFFER_TOO_SMALL || lv_Cnt <= lv_Max) break; // update max plus some extra to take changes in number of windows into account lv_Max = lv_Cnt + 16; } // return the count *out_Cnt = lv_Cnt; // return the list, or NULL when failed return lv_List; }
    

8
投票
你是对的。

EnumWindows

 只会查找属于非现代 (Metro) 应用程序的程序的窗口。它将获得属于传统(桌面)程序的窗口。 
FindWindowEx
,根据
几个来源,确实适用于所有类型的窗口,包括来自现代应用程序的窗口。

© www.soinside.com 2019 - 2024. All rights reserved.