VC怎么通过进程ID得到窗口句柄

2024-12-04 10:38:40
推荐回答(2个)
回答(1):

强制转换是肯定不行的,我想了个笨方法。在获得某进程的Id后,获取桌面上每个窗口的进程Id,再与先获得的进程Id进行比较,然后就能知道哪个窗口属于哪个进程的了。

另外网上找的一篇文章:http://www.vckbase.com/document/viewdoc/?id=404

下面是我弄的笨方法,将记事本的标题改为123,在MFC下编译通过:

void ChangeTitle()
{
// 需要修改的进程名
CString strFind = L"notepad.exe";

// 替换的文字
CString strReplace = L"123";
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
DWORD m_dwProcessId;

// 获得句柄
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == (HANDLE)-1)
{
printf("\nCreateToolhelp32Snapshot()failed:%d",GetLastError());
return;
}
pe32.dwSize = sizeof(PROCESSENTRY32);

// 列举所有进程名称
if (Process32First(hProcessSnap, &pe32))
{
do
{
CString str;
str.Format(L"%s",pe32.szExeFile);

// 找到需要修改的进程的Id
if(str == strFind)
{
m_dwProcessId = pe32.th32ProcessID;
}
}
while (Process32Next(hProcessSnap, &pe32));
}
else
{
printf("\nProcess32Firstt() failed:%d",GetLastError());
}

// 关闭句柄
CloseHandle (hProcessSnap);

////////////////////////////
HWND hwnd = ::FindWindow(L"Shell_TrayWnd",NULL);

if (hwnd)
{
hwnd = ::FindWindowEx(hwnd,NULL,L"ReBarWindow32",NULL);
if (hwnd)
{
hwnd = ::FindWindowEx(hwnd,NULL,L"MSTaskSwWClass",NULL);
if (hwnd)
{
hwnd = ::FindWindowEx(hwnd,NULL,L"ToolbarWindow32",NULL);
}
}
}

if (!hwnd)
{
AfxMessageBox(L"Find Window Error");
return;
}

// 获取任务栏按钮数量
int nCount = ::SendMessage(hwnd,TB_BUTTONCOUNT,0,0);
CString str;
str.Format(L"%u",nCount);
m_editX.SetWindowText(str);

// 分配内存
DWORD dwProcessId;

// 获取任务栏的进程Id
DWORD hThread = ::GetWindowThreadProcessId(hwnd, &dwProcessId);

// 打开任务栏的进程(Explorer)
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,false,dwProcessId);

// 在任务栏的进程空间分配内存
HANDLE hMem = VirtualAllocEx(hProcess,NULL,0x1000,MEM_COMMIT,PAGE_READWRITE);

if (hMem == NULL)
{
AfxMessageBox(L"Memory alloc error.");
return;
}

WCHAR sz[600];

for(int i = 0; i < nCount; i++)
{
// 获取按钮信息
::SendMessage(hwnd,TB_GETBUTTON,i,(LPARAM)hMem);

TBBUTTON tb;
SIZE_T nByteRead = 0;
::ReadProcessMemory(hProcess,hMem,&tb,sizeof(tb),&nByteRead);

// 由得到的按钮Id获取按钮文字
::SendMessage(hwnd,TB_GETBUTTONTEXT,tb.idCommand,(LPARAM)hMem);

::ReadProcessMemory(hProcess,hMem,sz,sizeof(WCHAR) * 600,&nByteRead);

str.Format(L"%s",sz);

HWND hwndFind = ::FindWindow(NULL, str);
::GetWindowThreadProcessId(hwndFind, &dwProcessId);
if(dwProcessId == m_dwProcessId)
{
::SetWindowText(hwndFind,strReplace);
}
}

::VirtualFreeEx(hProcess,hMem,NULL,MEM_RELEASE);
::CloseHandle(hProcess);
}

回答(2):

不会,谢谢你的两份