2019年新出的一款免费游戏Apex,很火;然后看到有类似与CF那样切换武器可以实现子弹自动上膛的官方bug,所以有想法写一个辅助工具(捍卫者单喷变连喷)现在是已经完成了,测试也很OK。所以,写个文档记录一下。关于Hook的介绍就不说了。我的资源有现成的程序。
1. 要有一个DLL的Hook(全局),需要键盘钩子、鼠标钩子。
2.通过调用windows系统的SetWindowsHookEx函数来注入钩子
3.不需要钩子的时候,使用UnHookWindowsHookEx释放钩子
DLL的代码(3个文件):
1. HKTest.DPR
library HKTest;
uses
HKProc in 'HKProc.pas',
uMyThread in 'uMyThread.pas';
exports
EnableHotKeyHook,
DisableHotKeyHook;
begin
hNextHookProc:=0;
hMouseHookProc:=0;
procSaveExit:=ExitProc;
end.
2.HKProc.pas
unit HKProc;
interface
uses
Windows, Messages ;
var
hNextHookProc:HHook;
hMouseHookProc:HHook;
procSaveExit:Pointer;
g_iInterval1, g_iInterval2, g_iInterval3: integer; //换弹间隔,收起武器间隔,切换武器2 间隔
function KeyboardHookHandler(iCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
function EnableHotKeyHook(iInterval1, iInterval2, iInterval3: integer):BOOL;export;
function DisableHotKeyHook:BOOL;export;
function MouseHookHandler(iCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
function EnableMouseHook:BOOL;export;
function DisableMouseHook:BOOL;export;
procedure HotKeyHookExit;far;
implementation
uses
uMyThread;
function KeyboardHookHandler(iCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
const _KeyPressMask = $80000000;
begin
Result:=0;
if iCode<0 then
begin
Result:= CallNextHookEx(hNextHookProc, iCode, wParam, lParam);
Exit;
end;
//侦测按键F1
if (wParam = vk_f1) then
begin
Result:=1;
EnableMouseHook;//开启鼠标Hook
end
else if (wParam = vk_f4) then //侦测按键F4
begin
Result:=1;
DisableMouseHook;//关闭鼠标Hook
end;
end;
function EnableHotKeyHook(iInterval1, iInterval2, iInterval3: integer):BOOL;export;
begin
Result:=False;
g_iInterval1:= iInterval1;
g_iInterval2:= iInterval2;
g_iInterval3:= iInterval3;
if hNextHookProc <> 0 then
Exit;
//挂上WH_KEYBOARD这类型的HOOK,同时传回值必须保留下来,免得HOOK呼叫链断掉
hNextHookProc:= SetWindowsHookEx(WH_KEYBOARD, KeyboardHookHandler, HInstance,0);
Result:= hNextHookProc <> 0;
end;
function DisableHotKeyHook:BOOL;export;
begin
if hNextHookProc <>0 then
begin
//解除KeyboardHook
UnHookWindowsHookEx(hNextHookProc);
hNextHookProc:=0;
MessageBeep(0);
MessageBeep(0);
end;
Result:= hNextHookProc = 0;
end;
function MouseHookHandler(iCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
begin
Result:=0;
if iCode<0 then
begin
Result:= CallNextHookEx(hMouseHookProc, iCode, wParam, lParam);
Exit;
end;
//侦测鼠标左键
if (wParam = WM_LBUTTONDOWN) then
begin
Result:= CallNextHookEx(hMouseHookProc, iCode, wParam, lParam);
TMyThread.Create(g_iInterval1,g_iInterval2,g_iInterval3);//通过线程来执行按键,3个参数是每个按键的间隔时间ms
end;
end;
function EnableMouseHook:BOOL;export;
begin
Result:=False;
if hMouseHookProc <> 0 then
Exit;
//挂上WH_KEYBOARD这类型的HOOK,同时传回值必须保留下来,免得HOOK呼叫链断掉
hMouseHookProc:= SetWindowsHookEx(WH_MOUSE, MouseHookHandler, HInstance,0);
Result:= hMouseHookProc <> 0;
end;
function DisableMouseHook:BOOL;export;
begin
if hMouseHookProc <>0 then
begin
//解除KeyboardHook
UnHookWindowsHookEx(hMouseHookProc);
hMouseHookProc:=0;
MessageBeep(0);
MessageBeep(0);
end;
Result:= hMouseHookProc = 0;
end;
procedure HotKeyHookExit;
begin
//如果忘了解除HOOK,自动代理解除的动作
if hNextHookProc<>0 then
DisableHotKeyHook;
if hMouseHookProc<>0 then
DisableMouseHook;
ExitProc:=procSaveExit;
end;
end.
3.uMyThread.pas
unit uMyThread;
interface
uses
windows, Classes, SysUtils;
type
TMyThread = class(TThread)
private
{ Private declarations }
g_iInterval1, g_iInterval2, g_iInterval3:integer;
protected
procedure Execute; override;
public
constructor create(iInterval1,iInterval2,iInterval3:integer);
end;
implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TMyThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
{ TMyThread }
constructor TMyThread.create(iInterval1, iInterval2, iInterval3: integer);
begin
inherited Create(False);
g_iInterval1:= iInterval1;
g_iInterval2:= iInterval2;
g_iInterval3:= iInterval3;
FreeOnTerminate:= True;
end;
procedure TMyThread.Execute;
begin
sleep(g_iInterval1);//按键间隔
keybd_event(82,MapVirtualKey(82,0),0,0); //r
keybd_event(82,MapVirtualKey(82,0),KEYEVENTF_KEYUP,0);
sleep(g_iInterval2);
keybd_event(51,MapVirtualKey(51,0),0,0);//3
keybd_event(51,MapVirtualKey(51,0),KEYEVENTF_KEYUP,0);
sleep(g_iInterval3);
keybd_event(50,MapVirtualKey(50,0),0,0);//2
keybd_event(50,MapVirtualKey(50,0),KEYEVENTF_KEYUP,0);
sleep(10);
end;
end.
测试界面程序:
代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, iniFiles;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Label3: TLabel;
Edit2: TEdit;
Label4: TLabel;
Label5: TLabel;
Edit3: TEdit;
Label6: TLabel;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function EnableHotKeyHook(iInterval1, iInterval2, iInterval3: integer):BOOL;external 'HKTest.dll';
function DisableHotKeyHook:BOOL;external 'HKTest.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
ini: TiniFile;
begin
if EnableHotKeyHook(StrToInt(edit1.text), StrToInt(edit2.text), StrToInt(edit3.text)) then
showMessage('HotKey Testing。。。');
ini:= TIniFile.Create(ExtractFilePath(Application.ExeName)+'myini.ini');
ini.WriteString('interval','r',edit1.text);
ini.WriteString('interval','3',edit2.text);
ini.WriteString('interval','2',edit3.text);
ini.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if DisableHotKeyHook then
showMessage('HotKey Testing done!!');
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
DisableHotKeyHook;
end;
procedure TForm1.FormShow(Sender: TObject);
var
ini: TiniFile;
begin
ini:= TIniFile.Create(ExtractFilePath(Application.ExeName)+'myini.ini');
edit1.text:= ini.ReadString('interval','r','300');
edit2.text:= ini.ReadString('interval','3','200');
edit3.text:= ini.ReadString('interval','2','200');
ini.Free;
end;
end.
|
请发表评论