遍历所有顶层窗口

c++

Posted by YiMiTuMi on May 6, 2022

遍历所有顶层窗口

遍历窗口主要通过函数 EnumWindows 来实现,通过注册一个回调函数来获取窗口信息。

代码

WINDOWS_DATA_INFO 结构体:

typedef struct _WINDOWS_DATA_INFO
{
	CString strTitleName; //窗口标题
	int iWindowId;        //窗口ID
	int iProcessId;       //窗口所属进程ID

}WINDOWS_DATA_INFO, *PWINDOWS_DATA_INFO;

调用 EnumWindows 函数:

BOOL GetWindowsInfo()
{
	list<WINDOWS_DATA_INFO> listWindowInfo;  //保存所有窗口信息
	LPARAM param = reinterpret_cast<LPARAM>(&listWindowInfo);

	if (!EnumWindows(WindwosEnumFun, param))
	{
		return FALSE;
	}

	return TRUE;
}

在 listWindowInfo 这个 List 中保存窗口信息。

EnumWindows 的回调函数:

BOOL CALLBACK WindwosEnumFun(HWND hwnd, LPARAM param)
{
	do 
	{
		list<WINDOWS_DATA_INFO>* pListWindowInfo = reinterpret_cast<list<WINDOWS_DATA_INFO>*>(param);
		

		int iLen = GetWindowTextLength(hwnd); //窗口的标题文本字符长度
		if (iLen == 0) //判断是否存在标题
		{
			break;
		}

		HWND owner = GetWindow(hwnd, GW_OWNER);
		LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); //获取窗口样式

		//判断窗口是否最小化
		if (IsIconic(hwnd))
		{
			break;
		}

		//判断窗口可视状态
		if (!IsWindowVisible(hwnd))
		{
			break;
		}
		
		//判断窗口风格
		/*
		if ((owner && !(exstyle & WS_EX_APPWINDOW)) || (exstyle & WS_EX_LAYERED))
		{
			break;
		}
		*/

		const int iClassLength = 256;
		WCHAR szClassName[iClassLength];
		memset(szClassName, 0, iClassLength);
		
		//获取指定窗口所属类名
		int iClassNameLength = GetClassName(hwnd, szClassName, iClassLength);

		//忽略掉任务管理器和开始按钮
		if (wcscmp(szClassName, L"Progman") == 0 || wcscmp(szClassName, L"Button") == 0)
		{
			break;
		}

		//获取窗口标题
		const int ITitleLength = 500;
		WCHAR szTitleName[ITitleLength];
		memset(szTitleName, 0, ITitleLength);

		GetWindowText(hwnd, szTitleName, ITitleLength);

		CString strTitleName = szTitleName;
		if (strTitleName.IsEmpty())
		{
			break;
		}
		

		//通过窗口句柄获取进程ID
		DWORD dwProcessId = 0;
		GetWindowThreadProcessId(hwnd, &dwProcessId);

		WINDOWS_DATA_INFO windowDataInfo;
		windowDataInfo.strTitleName = strTitleName;
		windowDataInfo.iProcessId = (int)dwProcessId;
		windowDataInfo.iWindowId = (int)hwnd;

		pListWindowInfo->push_back(windowDataInfo);

	} while (FALSE);

	return TRUE;
}

注:我将窗口的风格判断屏闭了,如果不屏蔽将获取不到 QQ 和微信的特殊风格的窗口。

如果要获取最顶层的出口只需要取 List 的第一个值即可。

薰衣草 – 等待爱情