UnhookWindowsHookEx()崩溃
SetWindowLong(…)
来恢复旧的窗口程序程序粉碎。 DLL代码:
#include "pch.h"
#include "pidhwnd.h"
#include "windows.h"
#include "TLHelp32.h"
BOOL IsHook = FALSE;
WNDPROC oldProc = NULL;
HWND gameHwnd =0 ;
HHOOK hMsgHook = NULL;
int hotkey = 0;
int Ctrl = 0, vk3f = 0;//热键参数
WNDPROC g_OldWndProc = NULL;
//钩子回调函数
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
//替换的窗口过程
LRESULT CALLBACK HookWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//自动打怪
void zddga();
///< 枚举窗口参数
typedef struct
{
HWND hwndWindow; // 窗口句柄
DWORD dwProcessID; // 进程ID class
const char* T_teit; //窗口标题
const char* T_class; //进程类名
}EnumWindowsArg;
///< 枚举窗口回调函数
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
EnumWindowsArg* pArg = (EnumWindowsArg*)lParam;
DWORD dwProcessID = 0;
// 通过窗口句柄取得进程ID
::GetWindowThreadProcessId(hwnd, &dwProcessID);
if (dwProcessID == pArg->dwProcessID)
{
CHAR szBuf_class[MAX_PATH] = {0};
CHAR wszTitle[MAX_PATH] = { 0 };
GetWindowTextA(hwnd, wszTitle, MAX_PATH);
GetClassName(
hwnd, // 窗口句柄
szBuf_class, // 接收窗口类名的缓冲区指针
MAX_PATH // 缓冲区字节大小
);
// MessageBox(NULL, szBuf_class, "提示!", 1);
if (strcmp(pArg->T_teit,"")==0)
{
if (memcmp(szBuf_class, pArg->T_class,strlen(pArg->T_class)) == 0)
{
pArg->hwndWindow = hwnd;
return FALSE;
}
}
if (strcmp(pArg->T_class, "") == 0)
{
if (memcmp(wszTitle, pArg->T_teit, strlen(pArg->T_teit)) == 0)
{
pArg->hwndWindow = hwnd;
return FALSE;
}
}
if (strcmp(pArg->T_class, "") != 0&& strcmp(pArg->T_teit, "") != 0)
{
if (memcmp(szBuf_class, pArg->T_class,strlen(pArg->T_class)) == 0 && memcmp(wszTitle, pArg->T_teit, strlen(pArg->T_teit)) == 0)
{
pArg->hwndWindow = hwnd;
return FALSE;
}
}
// 找到了返回FALSE
return TRUE;
}
// 没找到,继续找,返回TRUE
return TRUE;
}
///< 通过进程ID获取窗口句柄
HWND GetWindowHwndByPID(DWORD dwProcessID ,const char* T_class,const char* T_teit)
{
HWND hwndRet = NULL;
EnumWindowsArg ewa;
ewa.dwProcessID = dwProcessID;
ewa.hwndWindow = NULL;
ewa.T_class = T_class;
ewa.T_teit = T_teit;
EnumWindows(EnumWindowsProc, (LPARAM)&ewa);
if (ewa.hwndWindow)
{
hwndRet = ewa.hwndWindow;
}
return hwndRet;
}
BOOL setKeyRj(HWND hwnd,int _hotkey,int ctrl_z,int Vkzf)
{
//设置窗口线程的钩子函数
DWORD threadId, processId;
gameHwnd = hwnd;
hotkey = _hotkey;
Ctrl = ctrl_z;
vk3f = Vkzf;
threadId = GetWindowThreadProcessId(gameHwnd, &processId);
//这里的 hMsgHook 回调函数中需要用到 设置为全局
hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, HookProc, GetModuleHandle(NULL), threadId);
return (BOOL)hMsgHook;//WH_CALLWNDPROC
}
BOOL Unhook()
{
if (!hMsgHook)
{
return FALSE;
}
if (g_OldWndProc)
{
// recovering old wnd proc
SetWindowLong(gameHwnd, GWL_WNDPROC, (LONG)g_OldWndProc);
g_OldWndProc = NULL;
}
IsHook = FALSE;
UnregisterHotKey(gameHwnd, hotkey);//注销热键
BOOL ret= UnhookWindowsHookEx(hMsgHook);
hMsgHook =NULL;
return ret;
}
//钩子回调函数
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//由于窗口的 GetMessage PeekMessage 在不停的发生 所以回调函数在不停调用 这里设置全局变量 IsHook 验证一下 以免重复设置
if (!IsHook)
{
IsHook = TRUE;
//这里的 hotkey oldProc设置为全局变量 因为在后边的替换窗口过程需要用到
//hotkey = GlobalAddAtom("test_F3");
int result = RegisterHotKey(gameHwnd, hotkey, Ctrl, vk3f);
g_OldWndProc=(WNDPROC)GetWindowLong(gameHwnd, GWL_WNDPROC);
oldProc = (WNDPROC)SetWindowLong(gameHwnd, GWL_WNDPROC, (LONG)HookWndProc);
}
return CallNextHookEx(hMsgHook, nCode, wParam, lParam);
}
//替换的窗口过程
LRESULT CALLBACK HookWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//热键处理 hotkey是自己定义的热键标识 这样一来自己定义的热键处理 其他消息 包括其他热键都默认处理
if (uMsg == WM_HOTKEY && wParam == hotkey)
{
//执行 自定义热键的函数
zddga();
}
else
{
CallWindowProc(oldProc, hwnd, uMsg, wParam, lParam);
}
return 1;
}
int dg01 = 0;
void zddga()
{
if (dg01==0)
{
MessageBox(NULL, "开始自动打怪!", "提示!", 1);
dg01 = 1;
}
else
{
MessageBox(NULL, "停止自动打怪!", "提示!", 1);
dg01 = 0;
}
}
.h文件
#pragma once
///< 通过进程ID获取窗口句柄
HWND GetWindowHwndByPID(DWORD dwProcessID,const char* T_class, const char* T_teit);//T_class
//注册热键
BOOL setKeyRj(HWND hwnd, int _hotkey, int ctrl_z, int Vkzf);
//卸载热键
BOOL Unhook();