5.WindowsAPI函数原型
消息处理函数的原型:
函数功能:该函数是一个应用程序定义的函数。它处理发送给窗口的消息。WINDPROC类型定义了一个指向该回调函数的指针。WindowProc是用于应用程序定义函数的占位符。
LRESULT CALLBACK WindowProc( // 定义了一个指向该回调函数的指针。
HWND hwnd, // 发送方的窗口句柄
UINT msg, // 消息id,即消息的种类
WPARAM wparam, // 详细信息
LPARAM lparam); // 详细信息
FindWindow函数获得一个顶层窗体的句柄,该窗体的类名和窗体名与给定的字符串相匹配。这个函数不查找子窗体。在查找时不区分大写和小写。
如果有指定的类名和窗口的名字则表示成功返回一个窗口的句柄。否则返回零。
HWND FindWindow(
LPCTSTR lpClassName, // 指向类名
LPCTSTR lpWindowName // 指向窗口名
);
该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而和函数PostMessage不同,PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。
LRESULT SendMessage(
HWND hWnd, // 其窗口程序将接收消息的窗口的句柄。
UINT Msg, // 指定被发送的消息
WPARAM wParam, // 指定附加的消息特定信息
LPARAM IParam) // 指定附加的消息特定信息
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。消息队列里的消息通过调用GetMessage和PeekMessage取得。
BOOL WINAPI PostMessage(
HWND hWnd, // 其窗口程序接收消息的窗口的句柄
UINT Msg, // 指定被寄送的消息
WPARAM wParam, // 指定附加的消息特定的信息
LPARAM lParam); // 指定附加的消息特定的信息
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零
DWORD GetWindowThreadProcessId( // 获得窗口所属进程ID和线程ID
HWND hWnd, // 窗口句柄
LPDWORD lpdwProcessId // 进程ID地址
);
HANDLE OpenProcess( // 获得进程的句柄
DWORD dwDesiredAccess, // 该进程访问权限
BOOL bInheritHandle, // 所得到的进程句柄是否可以被继承
DWORD dwProcessId // 被打开进程的PID
);
从指定的进程中读入内存信息,被读取的区域必须具有訪问权限。
BOOL ReadProcessMemory(
HANDLE hProcess, // 进程句柄
LPCVOID lpBaseAddress, // 读出数据的地址
LPVOID lpBuffer, // 存放读取数据的地址
DWORD nSize, // 读出的数据大小
LPDWORD lpNumberOfBytesRead // 数据的实际大小
);
6.代码编写
(1).VC6.0创建MFC窗体应用程序
VC6.0 新建 -> MFC AppWizard[exe] -> 应用程序类型:基本对话框
(2).程序读取雷数基址
DWORD pid;
HWND h = ::FindWindow("扫雷",NULL);
if(h == 0) {
MessageBox("游戏未打开", "提示", MB_OK);
return ;
}
::GetWindowThreadProcessId(h, &pid);
HANDLE hp = ::OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if(hp == NULL) {
MessageBox("打开进程出错", "提示", MB_OK);
return ;
}
::ReadProcessMemory(hp, (LPCVOID)0x01005194, &m_EditBase, 4, &pid);
UpdateData(false);
(3).模拟鼠标点击事件,点击第一个棋子
WORD yx[2];
HWND h = ::FindWindow("扫雷",NULL);
if(h == 0) {
MessageBox("游戏未打开", "提示", MB_OK);
return ;
}
yx[0] = 14 + 6;
yx[1] = 56 + 6;
::SendMessage(h, WM_LBUTTONDOWN, 1, *(int*)yx);
::SendMessage(h, WM_LBUTTONUP, 0, *(int*)yx);
(4).游戏菜单类CALL调用
HWND h = ::FindWindow("扫雷",NULL);
if(h == 0) {
MessageBox("游戏未打开", "提示", MB_OK);
return ;
}
::SendMessage(h, WM_COMMAND, 0x209, 0); // 初级
::SendMessage(h, WM_COMMAND, 0x20A, 0); // 中级
::SendMessage(h, WM_COMMAND, 0x20B, 0); // 高级
::SendMessage(h, WM_COMMAND, 0x20C, 0); // 自定义
7.结果
8.总结
通过本次学习,主要掌握以下知识点:
(1).CE找相关数据的基址;
(2).分析棋盘数据;
(3).找简单的菜单类CALL,并模拟鼠标消息调用菜单;
(4).熟悉Windows API函数;
(5).掌握C++代码读写内存数据;