遇到需要枚举窗口的操作, 发现使用EnumWindows和EnumChildWindows枚举的窗口不完整, 于是参考 SystemInformer 的写法整理了一下这个功能比较全面的枚举方法.
#include <windows.h>
#include <tchar.h>
#include <string>
#include <map>
#include <locale.h>
#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
typedef struct _WND_INFO
{
HWND hWnd;
DWORD dwPid;
DWORD dwTid;
_tstring strClass;
_tstring strText;
}WND_INFO;
void _EnumProcessWindows(std::map<HWND, WND_INFO>& infos, HWND hWnd, DWORD dwPid)
{
HWND childWindow = NULL;
ULONG nMaxTimes = 0x4000;
//使用 FindWindowEx 函数搜索子窗口
while (nMaxTimes > 0 && (childWindow = ::FindWindowEx(hWnd, childWindow, NULL, NULL)))
{
ULONG processId = 0;
ULONG threadId = 0;
threadId = ::GetWindowThreadProcessId(childWindow, &processId);
if (dwPid == processId)
{
TCHAR szClassBuf[MAX_PATH] = { 0 };
TCHAR szTextBuf[MAX_PATH] = { 0 };
::GetClassName(childWindow, szClassBuf, _countof(szClassBuf));
::GetWindowText(childWindow, szTextBuf, _countof(szTextBuf));
WND_INFO info;
info.hWnd = childWindow;
info.dwPid = processId;
info.dwTid = threadId;
info.strClass = szClassBuf;
info.strText = szTextBuf;
infos.insert(std::make_pair(childWindow, info));
}
nMaxTimes--;
}
}
std::map<HWND, WND_INFO> EnumProcessWindows(DWORD dwPid)
{
std::map<HWND, WND_INFO> infos;
//枚举 桌面窗口 的子窗口
_EnumProcessWindows(infos, ::GetDesktopWindow(), dwPid);
//枚举 仅消息窗口 的子窗口
_EnumProcessWindows(infos, HWND_MESSAGE, dwPid);
return infos;
}
int main()
{
::setlocale(LC_ALL, "");
std::map<HWND, WND_INFO> infos = EnumProcessWindows(23408);
for (const auto& item : infos)
{
const WND_INFO& info = item.second;
_tprintf(_T("0x%p Class:[%s] Text: [%s]\r\n"), item.first, info.strClass.c_str(), info.strText.c_str());
}
return 0;
}