问题:
如题,如何遍历寻找指定进程?如何通过进程ID获取窗口句柄?HWND与CWnd之间是如何转换的?
解决:
1、HWND与CWnd之间的转换:使用 GetSafeHwnd 和 CWnd::FromHandle
// 已知 CWnd 获取 HWND
CWnd* pCWnd;
HWND hwnd = pCWnd->m_hWnd;
HWND hwnd1 = pCWnd->GetSafeHwnd();
// 已知 HWND 获取 CWnd
HWND hwnd2;
CWnd* pCwnd1 = CWnd::FromHandle(hwnd2);
2、如何遍历寻找指定进程:使用 EnumWindows
// 这里以匹配进程名称 Test Process 为例
::EnumWindows([](HWND hwnd, LPARAM lparam) ->BOOL {
wchar_t winText[256];
::GetWindowText(hwnd, winText, 255);
CString winStr = winText;
if (winStr.IsEmpty())
return TRUE; //!< 继续遍历
if(winStr.Compare(_T("Test Process")) == 0)
return FALSE;//结束遍历
return TRUE; //!< 继续遍历
}, NULL);
还可以加以判断是否是当前进程,寻找当前进程之外的指定进程:使用 _getpid 和 GetWindowThreadProcessId
//......
if(winStr.Compare(_T("Test Process")) == 0)
{
DWORD dwId = 0;
GetWindowThreadProcessId(hwnd, &dwId);
if (_getpid() == dwId)
return TRUE;// 是当前进程,继续遍历
return FALSE;//结束遍历
}
//......
3、获取指定进程ID的窗口句柄:使用CALLBACK 、EnumWindows 和 struct
//自定义枚举进程参数
typedef struct
{
HWND hwnd;
DWORD processId;
}WindowsArg;
//回调函数
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam)
{
WindowsArg * pArg = (WindowsArg *)lparam;
DWORD dwId = 0;
GetWindowThreadProcessId(hwnd, &dwId);
if (pArg.processId == dwId)
{
pArg->hwnd = hwnd;
return FALSE;//匹配进程ID成功,结束遍历
}
return TRUE; //!< 继续遍历
}
//通过进程ID获取窗口句柄
HWND GetHwndByProcessId(DWORD processId)
{
HWND hwndRet = NULL;
WindowsArg wa;
wa.processId = processId;
wa.hwnd = NULL;
EnumWindows(EnumWindowsProc, (LPARAM)&wa);
if (wa.hwnd)
hwndRet = wa.hwnd;
return hwndRet ;
}