每每编程时都要和窗口句柄hWnd打交道,如果只是MFC的程序还好说this->m_hWnd就解决了,这也只是当前窗口的句柄而已,都说家花哪有野花香,不费力的事情好像不太给力,给点难度对于我们这些初学者来说还是有点成就感的
下面有参考MSDN和网上的资料:
一、
HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);
这种方法最直接了,不过两参数中有一个不太好得到,WindowName就是窗口名,也就是窗口程序运行时任务栏上显示的;窗口的ClassName一般是看不到了,也就是这个最纠结了。如果当前只运行同一窗口程序的一个实例,就可以直接
::FindWindow(NULL, LPCTSTR lpWindowName);//这样返回的直接就是指定窗口名的窗口句柄了
二、
HANDLE WINAPI CreateToolhelp32Snapshot( __in DWORD dwFlags, __in DWORD th32ProcessID);
BOOL WINAPI Process32First( __in HANDLE hSnapshot, __in_out LPPROCESSENTRY32 lppe);
BOOL WINAPI Process32Next( __in HANDLE hSnapshot, __out LPPROCESSENTRY32 lppe);
这三个API函数配合使用 结构体PROCESSENTRY32可以参考MSDN
当然要#include "Tlhelp32.h"
先定义一个全局变量,类中的全局变量就可以
HWND SpecialhWnd;
//枚举窗口回调
//hwnd窗口句柄 lParam指定的进程ID
BOOL CALLBACK EnumWinProc(HWND hwnd, LPARAM lParam)
{
DWORD dwID;
GetWindowThreadProcessId(hwnd, &dwID);
if (dwID == (DWORD)lParam && IsWindowVisible(hwnd) && GetParent(hwnd) == NULL)
{//匹配条件为 进程ID相符&&窗口可见&&无父级窗口(自己是顶级窗口)
SpecialhWnd = hwnd;//全局变量保存符合的窗口句柄
}
return TRUE;
}
EnumWindow API参考MSDN,第一个参数为回调函数地址,第二个参数为提供给回调函数的参数
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
//进程快照枚举进程 lpszProcName指定进程名
void CXXXXXDlg::GethWndByProc32SnapShot(TCHAR* lpszProcName)
{
PROCESSENTRY32W PE32Info;
HANDLE hSnapShot;
BOOL bReport;
CString OutDebug;
memset(&PE32Info, 0, sizeof(PROCESSENTRY32W));
PE32Info.dwSize = sizeof(PROCESSENTRY32W);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//创建进程快照,返回快照句柄
bReport = Process32FirstW(hSnapShot, &PE32Info);//将第一个进程的信息填充到结构体中
while (bReport)
{
if (!_wcsicmp(PE32Info.szExeFile, lpszProcName))//将当前进程名与指定的进程名不区分大小写比对
{
EnumWindows((WNDENUMPROC)EnumWinProc, PE32Info.th32ProcessID);//枚举窗口
OutDebug.Format(L"进程: %ws > 进程ID: %d > 窗口句柄: 0xx", PE32Info.szExeFile, PE32Info.th32ProcessID, SpecialhWnd);
OutputDebugStringW(OutDebug);
}
bReport = Process32NextW(hSnapShot, &PE32Info);//
}
CloseHandle(hSnapShot);
return;
}
以上两种方法都有个不足就是,如果同时运行一个程序多个实例时,无论窗口名还是进程名都会有相同的好几个,这样第二种方法就只能获取到其中的一个,因为保存句柄的全局变量被重新赋值。
当然不是没有解决的方法,可以将保存句柄的变量定义成一个数组,也就是HWND hWnd[ nsize ];数组的大小自己控制,并定义一个局部的计数器,当有符合条件的句柄时就保存到句柄数组中去。
回调的实现也就是下面那样了:
//枚举窗口回调
//hwnd窗口句柄 lParam指定的进程ID
BOOL CALLBACK EnumWinProc(HWND hwnd, LPARAM lParam)
{
DWORD dwID;
int count = 0;
GetWindowThreadProcessId(hwnd, &dwID);
if (dwID == (DWORD)lParam && IsWindowVisible(hwnd) && GetParent(hwnd) == NULL)
{
SpecialhWnd[count++] = hwnd;//全局变量保存符合的窗口句柄
}
return TRUE;
}
这样同一程序的不同实例的窗口句柄都可以得到,不过该怎么去区分它们?
解决的方法总是有的,加上一组只能唯一的识别号,进程ID或许可以
除了使用二组数组,还有一种方法就是使用容器,因为不是很理解,这里也不好写下去了,能捧场的多留点口水,实在是想多学点
在网上也还见到过其他方法的,有兴趣的可以去找找,可以自己动动手实践一下