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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC怎么通过进程ID得到窗口句柄相关的知识,希望对你有一定的参考价值。

我试过网上的好多办法,到我这都不管用,气之又气..
我通过CreateToolhelp32Snapshot 来枚举所有进程,接下来再通过Process32First以及Process32Next查看我想要的进程名,进程ID,得到进程ID后再通过OpenProcess函数得到了一个句柄,是HANDEL的,我想要的是HWND窗口句柄,进行强制转换是不可以的,用强制转换后的句柄去操作另外一个进程调用GetWindowText和SetWindowText失败,Get的是空,在GetLastError中的提示是无效句柄,我试过好多办法了都不行(包括SendMessage)..
先说一下我的目的 我是想通过进程句得到窗口句柄,然后改窗口标题名的,条件,在本进程内操作的是其他的进程...

下面是我代码,请大家帮帮忙,看该怎么弄,这里先谢谢了....

HANDLE hProcessSnap = NULL;
HWND h_test;
PROCESSENTRY32 pe32 = 0;
BOOL exist = false;

// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

// Fill in the size of the structure before using it
pe32.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(hProcessSnap,&pe32))

do

if(strcmp("notepad.exe",pe32.szExeFile)==0)

//这里这样强制转换后下面的句柄好像都是错的,不知道得到窗口句柄这步该怎么弄了...
h_test = (HWND)OpenProcess(PROCESS_ALL_ACCESS,0,pe32.th32ProcessID);

//下面的三行是测试用,看是否能得到窗口标题

//TCHAR temp[255];
//::GetWindowText(h_test,temp,sizeof(temp)/sizeof(TCHAR));
//MessageBox(temp); //这一步弹出来的信息总是一堆"烫"..

//以下代码是显示错误信息的.
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox((LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );

//设置窗口标题
if(!::SetWindowText(h_test,"ele1")) //此处我用了SendMessage发WM_SETTEXT消息也没有成功...

MessageBox("窗口标题设置失败!!");

else

MessageBox("成功!!");

exist = true;
break;

while(Process32Next(hProcessSnap,&pe32));

if(!exist)

MessageBox("请先开个文本!!");


CloseHandle(hProcessSnap);

参考技术A 强制转换是肯定不行的,我想了个笨方法。在获得某进程的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);
本回答被提问者采纳
参考技术B 不会,谢谢你的两份

以上是关于VC怎么通过进程ID得到窗口句柄的主要内容,如果未能解决你的问题,请参考以下文章

高分求解。VC++ 通过进程名或进程ID获取进程句柄

VC获取自身窗口句柄

如何获取控件句柄 vc

vb 句柄怎么用

怎么查询一个进程ID,进程线程ID,进程句柄和进程线程句柄用来填充PROCESS_INFORMATION

一个进程有很多窗口,怎么取这个进程的下所有窗口句柄