枚举窗口
- FindWindow:
windows中可以使用FindWindow查找指定窗口:
HWND WINAPI FindWindow(
_In_opt_ LPCTSTR lpClassName,//窗口类名
_In_opt_ LPCTSTR lpWindowName//窗口名,标题
);
lpClassName为注册窗口时的类名,如果为NULL,则匹配标题,返回值为句柄。类名窗口名可以使用spyxx可以看得到(最后介绍)。
使用如下:
HWND handle = NULL;
FindWindow(NULL, "任务管理器");
RECT rect;
int width, height;
if (handle)
{
GetWindowRect(handle, &rect);
width = rect.right - rect.left, height = rect.bottom - rect.top;
cout << "宽: " << width << endl << "高: " << height << endl;
cout<<MoveWindow(handle, 100, 100, width, height, true)<<endl;
}
- FindWindowEx:
HWND WINAPI FindWindowEx(
_In_opt_ HWND hwndParent,//父窗口句柄
_In_opt_ HWND hwndChildAfter,//子窗口句柄
_In_opt_ LPCTSTR lpszClass,//类名
_In_opt_ LPCTSTR lpszWindow//窗口名
);
当hwndParent为NULL时即枚举桌面子窗口。
- EnumWindows:
BOOL WINAPI EnumWindows(
_In_ WNDENUMPROC lpEnumFunc,//回调函数
_In_ LPARAM lParam//传递给回调函数的参数
);
该枚举屏幕上的顶层窗口,并将窗口句柄传送给应用程序定义的回调函数,其中lParam是传递给lpEnumFunc的参数。回调函数返回FALSE将停止枚举,否则EnumWindows函数继续到所有顶层窗口枚举完为止。
- EnumChildWindows:
BOOL WINAPI EnumChildWindows(
_In_opt_ HWND hWndParent,\\父窗口
_In_ WNDENUMPROC lpEnumFunc,\\回调函数
_In_ LPARAM lParam\\传递给回调函数的参数
);
该函数遍历指定窗口的所有子窗口,其他参数和EnumWindows类似。
有了这几个函数之后,就可以遍历窗口、遍历特定窗口子控件、对某个窗口发送消息等。
如下代码可以用于枚举窗口:
#include <windows.h>
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
//子窗口回调函数
BOOL CALLBACK EnumChildWindowsProc(HWND hwnd,LPARAM lParam)
{
char title[100] = { 0 };
GetWindowTextA(hwnd, title, 100);
if (strlen(title)>0)
cout <<hex<<"句柄:"<<hwnd<<" 标题:"<<title << endl;
return true;
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
char title[100] = { 0 };
GetWindowTextA(hwnd, title, 100);
if (strlen(title) > 0)
cout << hex << "句柄:" << hwnd << " 标题:" << title << endl;
EnumChildWindows(hwnd, EnumChildWindowsProc, NULL);
return true;
}
BOOL myEnumWindow(HWND hwnd)
{
char title[100] = { 0 };
HWND after = NULL;
while (after = ::FindWindowEx(hwnd, after, NULL, NULL))
{
GetWindowTextA(after, title, 100);
if(strlen(title)>0)
cout <<"句柄:"<<hex<< after<<" 标题:" << title <<endl;
myEnumWindow(after);
}
return true;
}
int main()
{
HWND handle = NULL;
FindWindow(NULL, "任务管理器");//查找特定窗口的窗口句柄
RECT rect;
int width, height;
if (handle)
{
GetWindowRect(handle, &rect);//获取窗口信息
width = rect.right - rect.left, height = rect.bottom - rect.top;
cout << "宽: " << width << endl << "高: " << height << endl;
cout << MoveWindow(handle, 100, 100, width, height, true) << endl;
}
//使用EnumWindows枚举窗口,获取所有顶层可见窗口及他们的子窗口
EnumWindows(EnumWindowsProc, NULL);
cout << endl << endl << "第二种方法:" << endl;
myEnumWindow(NULL);//使用FindWindowEx枚举窗口
getchar();
getchar();
return 0;
}
枚举窗口,获取到窗口句柄之后,很多操作都可以进行啦。
效果:
注:部分不可见窗口,可能使用使用上边的代码都无法查找到,可以尝试使用如下代码获取,myEnumWindow 为上述代码中的函数,只是调用参数为 HWND_MESSAGE:
myEnumWindow(HWND_MESSAGE);
改了个MFC的版本:
- 代码:
BEGIN_MESSAGE_MAP(CEnumWindowDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_ENUM, &CEnumWindowDlg::OnBnClickedEnum)
ON_BN_CLICKED(IDC_FIND, &CEnumWindowDlg::OnBnClickedFind)
ON_BN_CLICKED(IDC_FIND_MSG, &CEnumWindowDlg::OnBnClickedFindMsg)
ON_BN_CLICKED(ID_EXIT, &CEnumWindowDlg::OnBnClickedExit)
END_MESSAGE_MAP()
BOOL CALLBACK EnumChildWindowsProc(HWND hwnd, LPARAM lParam)
{
CEnumWindowDlg * pParent = (CEnumWindowDlg*)lParam;
TCHAR title[MAX_PATH] = { 0 };
if (GetWindowText(hwnd, title, sizeof(title)) > 0)
{
CString s;
int pos = pParent->m_list.GetItemCount();
s.Format(_T("%d"), pos);
pParent->m_list.InsertItem(pos, s);
s.Format(_T("%p"), hwnd);
pParent->m_list.SetItemText(pos, 1, s);
pParent->m_list.SetItemText(pos, 2, CString(title));
}
return true;
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
CEnumWindowDlg * pParent = (CEnumWindowDlg*)lParam;
TCHAR title[MAX_PATH] = { 0 };
if (GetWindowText(hwnd, title, sizeof(title)))
{
CString s;
int pos = pParent->m_list.GetItemCount();
s.Format(_T("%d"), pos);
pParent->m_list.InsertItem(pos, s);
s.Format(_T("%p"), hwnd);
pParent->m_list.SetItemText(pos, 1, s);
pParent->m_list.SetItemText(pos, 2, CString(title));
}
EnumChildWindows(hwnd, EnumChildWindowsProc, lParam);
return true;
}
BOOL CEnumWindowDlg::myEnumWindow(HWND hwnd)
{
TCHAR title[MAX_PATH] = { 0 };
HWND after = NULL;
while (after = ::FindWindowEx(hwnd, after, NULL, NULL))
{
if (::GetWindowText(after, title, sizeof(title)) > 0)
{
CString s;
int pos = m_list.GetItemCount();
s.Format(_T("%d"), pos);
m_list.InsertItem(pos, s);
s.Format(_T("%p"), after);
m_list.SetItemText(pos, 1, s);
m_list.SetItemText(pos, 2, CString(title));
}
myEnumWindow(after);
}
return true;
}
// CEnumWindowDlg 消息处理程序
BOOL CEnumWindowDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
m_list.SetExtendedStyle(m_list.GetStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
CRect rect;
GetWindowRect(&rect);
m_list.InsertColumn(0, _T("序号"), LVCFMT_LEFT, rect.Width() / 8, 0);
m_list.InsertColumn(1, _T("句柄"), LVCFMT_LEFT, rect.Width() / 4, 1);
m_list.InsertColumn(2, _T("窗口名"), LVCFMT_LEFT, 5 * rect.Width() / 8, 2);
((CButton*)GetDlgItem(IDC_ENUM))->SetCheck(TRUE);
EnumWindows(EnumWindowsProc, (LPARAM)this);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CEnumWindowDlg::OnBnClickedEnum()
{
m_list.DeleteAllItems();
EnumWindows(EnumWindowsProc, (LPARAM)this);
}
void CEnumWindowDlg::OnBnClickedFind()
{
m_list.DeleteAllItems();
myEnumWindow(NULL);//使用FindWindowEx枚举窗口
}
void CEnumWindowDlg::OnBnClickedFindMsg()
{
m_list.DeleteAllItems();
myEnumWindow(HWND_MESSAGE);//使用FindWindowEx枚举窗口
}
void CEnumWindowDlg::OnBnClickedExit()
{
CDialogEx::OnOK();
}
- 效果:
代码链接:
VS2015工程:http://download.csdn.net/detail/yangyang031213/9891558
https://github.com/yangyang0312/cpp/tree/master/windows/EnumWindow
- 附:spyxx.exe的使用:http://blog.csdn.net/yangyang031213/article/details/61624372