我们知道一个进程可能是没有主窗口(比如系统的服务进程)而有的进程可能又拥有不止一个的主窗口(比如OutLook软件),那么我们该如何才能取得指定进程的所有主窗口呢?
我们必须明确我们感兴趣“主窗口”这个概念,到底什么样的窗口才是主窗口,他应该具有那些特点。
首先,主窗口必须是可见的也就是拥有WS_VISABLE属性(其实也有很多不可见的主窗口,但是我们在这里暂不考虑
这一点)
其次,主窗口应该是没有父窗口,也就是他的父窗口句柄为NULL.。
有了这两个条件我们就可以着手实现部分了。
要取得指定进程的主窗口的一般方法为
使用EnumWindows函数,枚举出所有的符合主窗口条件的上层窗口,然后通过GetWindowThreadProcessId函数获得
窗口所属的进程ID,如果所得到的进程ID和已知的进程ID相同,就说明该窗口是这个进程的一个主窗口。
上面就是基本的思路。
下面是本人设计的一个类,用来实现此项功能
#pragma once
#include
#include
class CProcessMainWndArray {
DWORD m_dwProcessId;
std::vector
public:
CProcessMainWndArray(DWORD dwProcessId = 0)
: m_dwProcessId(dwProcessId) {
m_vHwnd.clear();
EnumWindows(enumProc, (LPARAM)this);
}
~CProcessMainWndArray() {};
private:
static BOOL __stdcall enumProc(HWND hWnd, LPARAM lParam) {
CProcessMainWndArray* pWndIterator = (CProcessMainWndArray*)lParam;
DWORD dwCurProcessId;
GetWindowThreadProcessId(hWnd, &dwCurProcessId);
if ((GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE) &&
GetParent(hWnd) == NULL &&
(dwCurProcessId == pWndIterator->getCurProcessId())) {
pWndIterator->getMainHwndArray()->push_back(hWnd);
}
return TRUE;
}
private:
DWORD getCurProcessId()
{ return m_dwProcessId; }
std::vector
{ return &m_vHwnd; }
public:
bool isEmpty()
{ return m_vHwnd.empty(); }
std::vector
{ return m_vHwnd.begin(); }
std::vector
{ return m_vHwnd.end(); }
size_t size()
{ return m_vHwnd.size(); }
HWND operator[](int nIndex)
{ return m_vHwnd[nIndex]; }
};
该类的使用非常简单,例如
#include
int main()
{
//0x0524为目标进程的ID
CProcessMainWndArray wnd(0X0524);
if (wnd.isEmpty()) {
std::cout << "There are no main windows in target process" << std::endl;
return -1;
}
//第一种方法
std::cout << "The handles of this process are : " << std::endl;
std::vector
for (iter; iter != wnd.end(); ++iter) {
char szHwnd[MAX_PATH] = { 0 };
sprintf(szHwnd, "0x%x", *iter);
std::cout << szHwnd << std::endl;
}
//第二种方法
std::cout << "The handles of this process are : " << std::endl;
for (size_t i = 0; i < wnd.size(); i++) {
char szHwnd[MAX_PATH] = { 0 };
sprintf(szHwnd, "0x%x", wnd[i]);
std::cout << szHwnd << std::endl;
}
return 0;
}
//类的构造函数
//参数:dwProcessId目标进程的ID
//该函数的功能主要是枚举系统的所有上层窗口,并将窗口句柄记录在vector之中
CProcessMainWndArray(DWORD dwProcessId = 0)
: m_dwProcessId(dwProcessId) {
m_vHwnd.clear();
EnumWindows(enumProc, (LPARAM)this);
}
//枚举窗口的回调函数
//参数:hWnd窗口句柄
// lParam:应用程序定义的的32位值,在这里为CProcessMainWndArray类型的指针
//函数功能:回调函数用来枚举所有的上层窗口,并将符合条件窗口句柄存入m_vHwnd之中
//
static BOOL __stdcall enumProc(HWND hWnd, LPARAM lParam) {
CProcessMainWndArray* pWndIterator = (CProcessMainWndArray*)lParam;
DWORD dwCurProcessId;
GetWindowThreadProcessId(hWnd, &dwCurProcessId);
if ((GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE) &&
GetParent(hWnd) == NULL &&
(dwCurProcessId == pWndIterator->getCurProcessId())) {
pWndIterator->getMainHwndArray()->push_back(hWnd);
}
return TRUE;
}
//得到进程ID
DWORD getCurProcessId()
{ return m_dwProcessId; }
//得到记录窗口句柄的m_vHwnd的指针
std::vector
{ return &m_vHwnd; }
//判断数组(m_vHwnd)是否为空,如果为空,说明该进程没有主窗口
bool isEmpty()
{ return m_vHwnd.empty(); }
//得到指向m_vHwnd第一个元素的迭代器
std::vector
{ return m_vHwnd.begin(); }
//得到指向m_vHwnd最后一个元素后面位置的迭代器
std::vector
{ return m_vHwnd.end(); }
//取得m_vHwnd中句柄的数量
size_t size()
{ return m_vHwnd.size(); }
//运算符重载,用于返回存在于m_vHwnd数组中指定下标的句柄
HWND operator[](int nIndex)
{ return m_vHwnd[nIndex]; }
本例是参考msdn上的一篇文章,然后根据自己的思路重写了一个,放在这里和大家共享,希望能起到一个
抛砖引玉的作用,如果大家有其他好的方法,希望不吝赐教! :)