C++QT获取其他exe的edit控件id并且设置edit内容
找到exe的窗口句柄
找到窗口的句柄有很多种方法,可以根据需求来选择操作。
1.知道exe的窗口类名已或者标题名字
你可以通过
例如系统自带的计算器的窗口名字为计算器,通过查找我们在spy找到了
然后右键属性就能找类名
这样可以通过FindWindowExA 来获取窗口id,并且设置名字为我的计算器
HWND pWnd = FindWindowExA(0, 0, "ApplicationFrameWindow","计算器");
printf("%p --->计算器的窗口\n", pWnd);
SendMessage(pWnd, WM_SETTEXT, 0, (LPARAM)"老子的计算器");
可以看到名字已经变了,但是为什么计算器的那个名字没有变了呢?那是因为计算器这个是窗口子控件的显示,需要变了子控件来进行修改,这个后面再来讲。
2.不知道窗口名字类等等,只知道exe的启动名字
因为各种原因,比如相同类的名字窗口很多,或者窗口没有标题,又或者找不到窗口名字和类名(启动程序名字和实际窗口标题不一样)等等都会造成无法进行查找指定的窗口HWND。打个最简单的比方
我要获取的注册框里面的输入框edit的HWND,但是这个窗口不是父窗口的内容,是新的窗口,且这个窗口没有名字以及很难找的类名,直接搜索主窗口的类名和标题是无法搜索出这个的。
此窗口为刚刚的那个窗口,可以看出没有任何标题名字,要一个个看,要在上百个窗口中找出这个窗口是一个非常难得事情。
因此需要在线程中检索出所有窗口的内容,具体代码如下
#include <windows.h>
#include <stdint.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <vector>
#include <iostream>
typedef struct EnumHWndsArg
{
std::vector<HWND> *vecHWnds;
DWORD dwProcessId;
}EnumHWndsArg, *LPEnumHWndsArg;
HANDLE GetProcessHandleByID(int nID)//通过进程ID获取进程句柄
{
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, nID);
}
DWORD GetProcessIDByName(const char* pName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, pName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
//printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
}
CloseHandle(hSnapshot);
return 0;
}
BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
{
EnumHWndsArg *pArg = (LPEnumHWndsArg)lParam;
DWORD processId;
GetWindowThreadProcessId(hwnd, &processId);
if (processId == pArg->dwProcessId)
{
pArg->vecHWnds->push_back(hwnd);
//printf("%p\n", hwnd);
}
return TRUE;
}
void GetHWndsByProcessID(DWORD processID, std::vector<HWND> &vecHWnds)
{
EnumHWndsArg wi;
wi.dwProcessId = processID;
wi.vecHWnds = &vecHWnds;
EnumWindows(lpEnumFunc, (LPARAM)&wi);
}
HWND GetChildHWnd(HWND mHwnd, int ID) //mHwnd是主窗口句柄,ID是控件的ID
{
HWND mIDHWnd=NULL, mChildHWnd=NULL; //mIDHWnd返回的控件句柄,mChildHWnd是主窗口的子窗口句柄
while (mHwnd)
{
int id = 0;
id = ::GetDlgCtrlID(mHwnd);
printf("id=%d\n", id);
if (id == ID)
{
mIDHWnd = mHwnd;
break;
}
if (mChildHWnd = ::GetWindow(mHwnd, GW_CHILD))
{
GetChildHWnd(mChildHWnd, ID);
}
mHwnd = ::GetWindow(mHwnd, GW_HWNDNEXT);
}
return mIDHWnd;
}
int32_t main()
{
DWORD pid = GetProcessIDByName("data1111.exe");
printf("pid = %u\n", pid);
if (pid != 0)
{
std::vector<HWND> vecHWnds;
GetHWndsByProcessID(pid, vecHWnds);
printf("vecHWnds.size() = %u\n", vecHWnds.size());
HWND h = vecHWnds[0];
HWND parent = GetParent(h);
HWND pchind6 = ::FindWindowExA(h, 0, "Edit", NULL);
Sleep(5000);
while (pchind6 != NULL)
{
SendMessage(pchind6, WM_SETTEXT, 0, (LPARAM)"你好呀");
printf("%p --->edit\n", pchind6);
pchind6 = ::FindWindowExA(h, pchind6, "Edit", NULL);
Sleep(1000);
}
}
getchar();
return S_OK;
}
假设我已经知道了
启动程序的名字,且注册窗口为第一控件ID,因为注册窗口在前所有顺序也靠前,通过FindWindowExA检索出edit的类名的所有控件id然后SendMessage发送指定消息即可。
当然你还可以触发确定按钮点击机制,是不是很爽呀。
qt如何使用
qt可以直接将代码复制进去即可使用,但是会遇到乱码问题,你可以先将项目设置为多字节,然后
QTextCodec *codec = QTextCodec::codecForName("utf-8");//修改这两行
SendMessage(vecHWndsEdit[HWndi], WM_SETTEXT, 0, (LPARAM)QString::fromUtf8("问题1").toLocal8Bit().data());
即可解决乱码,别问我头文件是什么,头文件是#include ;