Авось кому пригодится, или у меня, как всегда, в хламе затеряется
Код:
Add(MainForm,1717544,511,42) { Width=370 Height=561 Position=1 Point(Handle) link(onCreate,15561254:doPopup,[(555,62)(555,86)(499,86)(499,111)]) } Add(InfoTip,13344029,21,28) { Info=#12:onHook > ...|0:|10:{keyboard}|23:256xx - нажатие клавиши|29:260xx - нажатие клавиши [ALT]|26:257xx - отпускание клавиши|21:где xx - код клавиши |41:например нажатие и отпускание [пробел] |8:25632 |6:25732 |50:256/257 - код нажатия/отпускания, 32 - код клавиши|0:|59:Отдельная идентификация левых и правых [shift],[ctrl],[alt]|0:|66:Особое внимание следует обратить на правую [alt], а точнее [AltGr]|63:Поведение [AltGr] соответствует поведению [(L)Ctrl] + [(R)Alt],|64:то-есть при нажатии выдается двойной код 260162 и 260165, а при |26:отпускании 257162 и 257165|69:Изза чего могут возникнуть трудности идентификации отпускания клавиши|75:так как для [(L)Ctrl] и [AltGr] будет присутствовать одинаковый код 257162 |0:|0:|7:{mouse}|20:5130 - нажатие ЛКМ |21:5140 - отпускание ЛКМ|18:5160 - нажатие ПКМ|21:5170 - отпускание ПКМ|18:5190 - нажатие СКМ|21:5200 - отпускание СКМ|17:5231 - нажатие Х1|20:5241 - отпускание Х1|17:5232 - нажатие Х2|20:5242 - отпускание Х2|23:5120 - перемещение мыши|42:522xx - прокрутка вперед, xx - delta (120)|31:522-xx - прокрутка назад (-120)|0:|47:Положительное значение указывает, что колесико |38:повернулось вперед (от пользователя); |47:отрицательное значение указывает, что колесико |46:было повернуло назад (в сторону пользователя).|0:|74:Следует помнить, что при нажатии кнопок присутствует код перемещения мыши.|75:Щелчок ЛКМ выдаст примерно такую последовательность 5130, 5120, 5140, 5120.|0:|0:|105:Срабатывает при использовании штатных KeyHook, KeyEvent и кнопок MouseEvent (на перемещение не реагирует)|0:|67:Компилируется FPC и D4, а также FPC 3.0.4 rev 2 for HiAsm (Unicode)| HAlign=0 Width=449 Height=676 Margin=5 } Add(WinTools,15561254,511,98) { link(Handle,1717544:Handle,[]) } Add(Memo,14423304,861,56) { Left=165 Top=5 Width=180 Height=410 AddType=1 ScrollBars=2 } Add(Button,5053081,609,42) { Left=5 Top=10 Caption="Mouse" Data=Integer(14) link(onClick,7720006:doWork1,[(676,48)]) } Add(Button,12364061,609,84) { Left=5 Top=35 Caption="keyboard" Data=Integer(13) link(onClick,7720006:doWork3,[(676,90)]) } Add(InlineCode,11918827,714,56) { WorkPoints=#69:doHook = Устанавливает процедуру перехватчика в цепочку перехватчиков|80:doUnHook = Удаляет процедуру перехватчика, установленную в цепочке перехватчиков|104:doNotCallNext = Запретить передачу сведений о перехватчике в следующую процедуру в цепочке перехватчиков| EventPoints=#40:onHook = Происходит при каждом перехвате|103:onError = (0)Ошибка установки, (1)Попытка повторной установки, (2)Успешно установлен, (3)Успешно удален|36:onWheelDelta = Прокрутка колеса мыши|51:onMouseMove = Перемещении мыши, в потоке координаты|0:| VarPoints=#35:MessageID = Идентификатор сообщения|52:MouseX = Координаты X курсора в экранных координатах|52:MouseY = Координаты Y курсора в экранных координатах|55:vkCode = Код виртуального ключа в диапазоне от 1 до 254|43:skCode = Код аппаратного сканирования ключа| DataPoints=#54:HookID = Тип перехватчика (14 - мышь, 13 - клавиатура)| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Kol,Share,Debug,Windows;|0:|4:type|28: THiAsmClass = class(TDebug)|8: private|3: |7: public|20: HookID:THI_Event;|4: |20: onHook:THI_Event;|21: onError:THI_Event;|26: onWheelDelta:THI_Event;|29: onMouseMove:THI_Event; |4: |47: procedure MessageID(var dt:TData; idx:word);|44: procedure MouseX(var dt:TData; idx:word);|44: procedure MouseY(var dt:TData; idx:word);|44: procedure vkCode(var dt:TData; idx:word);|44: procedure skCode(var dt:TData; idx:word);|4: |49: procedure doHook(var _Data:TData; Index:word);|51: procedure doUnHook(var _Data:TData; Index:word);|56: procedure doNotCallNext(var _Data:TData; Index:word);|4: |22: constructor Create;|35: destructor Destroy; override; |4:end;|0:|24:type // WH_KEYBOARD_LL|120: tagKBDLLHOOKSTRUCT = record // https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/ns-winuser-kbdllhookstruct|17: vkCode: dword;|19: scanCode: dword;|16: flags: dword;|15: time: dword;|26: dwExtraInfo: ^Cardinal;|4:end;|1: |21:type // WH_MOUSE_LL|117: tagMSLLHOOKSTRUCT = record //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/ns-winuser-msllhookstruct|20: pt:TPoint; // x,y|19: mouseData:Dword;|15: flags:Dword;|14: time:Dword;|24: dwExtraInfo:^Cardinal|6:end; |0:|17:const |132: WH_KEYBOARD_LL = 13; // Устанавливает процедуру перехватчика, которая отслеживает события ввода с клавиатуры низкого уровня. |134: WH_MOUSE_LL = 14; // Устанавливает процедуру перехватчика, которая отслеживает события ввода с помощью мыши низкого уровня. |39:///////////////////////////////////////|16: HC_ACTION = 0;|41://///////////////////////////////////// |39: WM_KEYDOWN = $0100; // 256|39: WM_KEYUP = $0101; // 257|39: WM_SYSKEYDOWN = $0104; // 260|60: WM_SYSKEYUP = $0105; // 261 нету, WM_KEYUP ??? |74://///////////////////////////////////// также как и всех ***BUTTONDBLCLK |47: WM_LBUTTONDOWN = $0201; // 513 левая|39: WM_LBUTTONUP = $0202; // 514|39: WM_LBUTTONDBLCLK = $0203; // 515|48: WM_RBUTTONDOWN = $0204; // 516 правая|39: WM_RBUTTONUP = $0205; // 517|41: WM_RBUTTONDBLCLK = $0206; // 518 |49: WM_MBUTTONDOWN = $0207; // 519 средняя|41: WM_MBUTTONUP = $0208; // 520 |39: WM_MBUTTONDBLCLK = $0209; // 521|49: WM_XBUTTONDOWN = $020B; // 523 боковые|39: WM_XBUTTONUP = $020C; // 524|42: WM_XBUTTONDBLCLK = $020D; // 525 |0:|39: WM_MOUSEMOVE = $0200; // 512|39: WM_MOUSEWHEEL = $020A; // 522|0:|4:var |16: HHook:THandle;|22: hiClass:THiAsmClass;|16: MsgID:integer;|18: isNext:bool; |20: MousePoint:TPoint;|24: VirtualKeyCode: dword;|18: ScanCode: dword;|0:|80:// #############################################################################|15:implementation |0:|0:|81:// ******************************************************************************|74://https://learn.microsoft.com/ru-ru/windows/win32/winmsg/lowlevelmouseproc|127:function lowlevelmouseproc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; //wParam:integer, lParam:integer|8:var |28: tagMLHS:tagMSLLHOOKSTRUCT;|16: ptr:^SmallInt;|18: w1, w2:SmallInt;|7: |5:begin|108:// Если значение nCode меньше нуля, процедура перехватчика должна передать сообщение функции CallNextHookEx |79:// без дальнейшей обработки и возвратить значение, возвращаемое CallNextHookEx.|25:if nCode < HC_ACTION then|6: begin|54: result := CallNextHookEx(HHook,nCode,wParam,lParam);|8: exit; |5: end;|1: |14: isNext:=true;|1: |48: tagMLHS := tagMSLLHOOKSTRUCT(pointer(lParam)^);|25: ptr:=@tagMLHS.mouseData;|21: w1:= SmallInt(ptr^);|30: //ptr:= ptr + 1; // only fpc?|13: Inc(ptr, 1);|21: w2:= SmallInt(ptr^);|0:|17: MsgID:= wParam; |24: MousePoint:=tagMLHS.pt;|0:|16: case MsgID of |16: WM_MOUSEMOVE: |7: begin|85: _hi_OnEvent(hiClass.onMouseMove, int2Str(MousePoint.x)+'|'+int2Str(MousePoint.y));|6: end;|16: WM_MOUSEWHEEL:|7: begin|41: _hi_OnEvent(hiClass.onWheelDelta, w2);|6: end;|5: end;|0:|59: _hi_OnEvent(hiClass.onHook, int2Str(MsgID) + int2Str(w2));|0:|89: //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-callnexthookex |15: if isNext then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|10: end |5: else|8: begin|17: result := 1;|7: end;|4:end;|0:|0:|81:// ******************************************************************************|78:// https://learn.microsoft.com/ru-ru/windows/win32/winmsg/lowlevelkeyboardproc|96:function lowlevelkeyboardproc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;|3:var|33: tagKLHS:tagKBDLLHOOKSTRUCT; |5:begin|26: if nCode < HC_ACTION then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|11: exit; |7: end;|1: |15: isNext:=true; |48: tagKLHS:= tagKBDLLHOOKSTRUCT(pointer(lParam)^);|32: VirtualKeyCode:=tagKLHS.vkCode;|29: ScanCode:= tagKLHS.scanCode;|16: MsgID:= wParam;|0:|0:|71: _hi_OnEvent(hiClass.onHook, int2Str(MsgID) + int2Str(tagKLHS.vkCode));|2: |15: if isNext then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|10: end |5: else|8: begin|17: result := 1;|7: end;|4:end;|0:|0:|0:|81:// ******************************************************************************|36:procedure THiAsmClass.doNotCallNext;|5:begin|18: isNext:= false;|4:end;|0:|0:|82:// ****************************************************************************** |29:procedure THiAsmClass.vkCode;|8:begin |33: dtInteger(dt, VirtualKeyCode);|4:end;|0:|0:|82:// ****************************************************************************** |29:procedure THiAsmClass.skCode;|8:begin |27: dtInteger(dt, ScanCode);|4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.MouseX;|8:begin |31: dtInteger(dt, MousePoint.x);|4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.MouseY;|5:begin|31: dtInteger(dt, MousePoint.y);|4:end;|0:|0:|81:// ******************************************************************************|32:procedure THiAsmClass.MessageID;|5:begin|24: dtInteger(dt, MsgID); |4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.doHook;|3:var|18: idHook:integer;|16: lpfn:pointer;|14: hmod:hinst;|20: dwThreadId:dword;|5:begin|31: if HHook > 0 then // installed|8: begin|69: _hi_OnEvent(hiClass.onError, 3); // попытка повторной установки|6: end|5: else|10: begin |39: case ReadInteger(_Data, HookID) of|17: WH_MOUSE_LL:|16: begin |35: idHook:= WH_MOUSE_LL; // 14|34: lpfn:= @lowlevelmouseproc;|31: hmod:= 0; // hInstance;|23: dwThreadId:= 0;|13: end; |20: WH_KEYBOARD_LL:|11: begin|38: idHook:= WH_KEYBOARD_LL; // 13|37: lpfn:= @lowlevelkeyboardproc;|17: hmod:= 0;|23: dwThreadId:= 0;|13: end; |7: end;|3: |91: //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-setwindowshookexa|59: HHook := SetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);|105: // Если функция выполняется успешно, возвращаемое значение является дескриптором процедуры перехватчика.|134: // Если функция завершается сбоем, возвращается значение NULL. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.|28: if HHook = 0 then // Error|55: _hi_OnEvent(hiClass.onError, 0) // ошибка установки|5: else|58: _hi_OnEvent(hiClass.onError, 1); // успешно установлен|3: |48:// ShowMessage(SysErrorMessage(GetLastError)); |57:// 1404 (0x57C) Недопустимый дескриптор перехватчика. |5: end;|4:end;|0:|0:|81:// ******************************************************************************|93:// https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-unhookwindowshookex|68://Если функция выполняется успешно, возвращается ненулевое значение.|138://Если функция выполняется неудачно, возвращается нулевое значение. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.|31:procedure THiAsmClass.doUnHook;|4:var |12: stat:bool;|5:begin|35: stat:= UnhookWindowsHookEx(HHook);|14: if stat then |7: begin|53: _hi_OnEvent(hiClass.onError, 2); // успешно удален|13: HHook:= 0;|6: end;|4:end;|0:|0:|81:// ******************************************************************************|31:constructor THiAsmClass.Create;|5:begin|18: inherited Create;|17: hiClass := self;|4:end;|0:|0:|81:// ******************************************************************************|31:destructor THiAsmClass.Destroy;|5:begin|29: UnhookWindowsHookEx(HHook); |19: inherited Destroy;|4:end;|0:|4:end.| link(onHook ,14423304:doAdd,[]) link(onError ,14705005:doWork1,[(774,69)]) } Add(Button,10846028,609,175) { Left=5 Top=90 Caption="clear" link(onClick,14076654:doEvent1,[(795,181)(795,69)]) } Add(Memo,16480506,861,112) { Left=165 Top=430 Width=180 ScrollBars=2 } Add(HubEx,7720006,672,56) { link(onEvent,11918827:doHook ,[]) } Add(Button,2031431,609,133) { Left=5 Top=60 Caption="unhook" link(onClick,15542803:doEvent1,[]) } Add(Hub,14076654,812,63) { link(onEvent1,14423304:doClear,[]) link(onEvent2,16480506:doClear,[(844,76)(844,125)]) } Add(InlineCode,8980810,714,287) { WorkPoints=#69:doHook = Устанавливает процедуру перехватчика в цепочку перехватчиков|80:doUnHook = Удаляет процедуру перехватчика, установленную в цепочке перехватчиков|104:doNotCallNext = Запретить передачу сведений о перехватчике в следующую процедуру в цепочке перехватчиков| EventPoints=#40:onHook = Происходит при каждом перехвате|103:onError = (0)Ошибка установки, (1)Попытка повторной установки, (2)Успешно установлен, (3)Успешно удален|36:onWheelDelta = Прокрутка колеса мыши|51:onMouseMove = Перемещении мыши, в потоке координаты|0:| VarPoints=#35:MessageID = Идентификатор сообщения|52:MouseX = Координаты X курсора в экранных координатах|52:MouseY = Координаты Y курсора в экранных координатах|55:vkCode = Код виртуального ключа в диапазоне от 1 до 254|43:skCode = Код аппаратного сканирования ключа| DataPoints=#54:HookID = Тип перехватчика (14 - мышь, 13 - клавиатура)| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Kol,Share,Debug,Windows;|0:|4:type|28: THiAsmClass = class(TDebug)|8: private|3: |7: public|20: HookID:THI_Event;|4: |20: onHook:THI_Event;|21: onError:THI_Event;|26: onWheelDelta:THI_Event;|29: onMouseMove:THI_Event; |4: |47: procedure MessageID(var dt:TData; idx:word);|44: procedure MouseX(var dt:TData; idx:word);|44: procedure MouseY(var dt:TData; idx:word);|44: procedure vkCode(var dt:TData; idx:word);|44: procedure skCode(var dt:TData; idx:word);|4: |49: procedure doHook(var _Data:TData; Index:word);|51: procedure doUnHook(var _Data:TData; Index:word);|56: procedure doNotCallNext(var _Data:TData; Index:word);|4: |22: constructor Create;|35: destructor Destroy; override; |4:end;|0:|24:type // WH_KEYBOARD_LL|120: tagKBDLLHOOKSTRUCT = record // https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/ns-winuser-kbdllhookstruct|17: vkCode: dword;|19: scanCode: dword;|16: flags: dword;|15: time: dword;|26: dwExtraInfo: ^Cardinal;|4:end;|1: |21:type // WH_MOUSE_LL|117: tagMSLLHOOKSTRUCT = record //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/ns-winuser-msllhookstruct|20: pt:TPoint; // x,y|19: mouseData:Dword;|15: flags:Dword;|14: time:Dword;|24: dwExtraInfo:^Cardinal|6:end; |0:|17:const |132: WH_KEYBOARD_LL = 13; // Устанавливает процедуру перехватчика, которая отслеживает события ввода с клавиатуры низкого уровня. |134: WH_MOUSE_LL = 14; // Устанавливает процедуру перехватчика, которая отслеживает события ввода с помощью мыши низкого уровня. |39:///////////////////////////////////////|16: HC_ACTION = 0;|41://///////////////////////////////////// |39: WM_KEYDOWN = $0100; // 256|39: WM_KEYUP = $0101; // 257|39: WM_SYSKEYDOWN = $0104; // 260|60: WM_SYSKEYUP = $0105; // 261 нету, WM_KEYUP ??? |74://///////////////////////////////////// также как и всех ***BUTTONDBLCLK |47: WM_LBUTTONDOWN = $0201; // 513 левая|39: WM_LBUTTONUP = $0202; // 514|39: WM_LBUTTONDBLCLK = $0203; // 515|48: WM_RBUTTONDOWN = $0204; // 516 правая|39: WM_RBUTTONUP = $0205; // 517|41: WM_RBUTTONDBLCLK = $0206; // 518 |49: WM_MBUTTONDOWN = $0207; // 519 средняя|41: WM_MBUTTONUP = $0208; // 520 |39: WM_MBUTTONDBLCLK = $0209; // 521|49: WM_XBUTTONDOWN = $020B; // 523 боковые|39: WM_XBUTTONUP = $020C; // 524|42: WM_XBUTTONDBLCLK = $020D; // 525 |0:|39: WM_MOUSEMOVE = $0200; // 512|39: WM_MOUSEWHEEL = $020A; // 522|0:|4:var |16: HHook:THandle;|22: hiClass:THiAsmClass;|16: MsgID:integer;|18: isNext:bool; |20: MousePoint:TPoint;|24: VirtualKeyCode: dword;|18: ScanCode: dword;|0:|80:// #############################################################################|15:implementation |0:|0:|81:// ******************************************************************************|74://https://learn.microsoft.com/ru-ru/windows/win32/winmsg/lowlevelmouseproc|127:function lowlevelmouseproc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; //wParam:integer, lParam:integer|8:var |28: tagMLHS:tagMSLLHOOKSTRUCT;|16: ptr:^SmallInt;|18: w1, w2:SmallInt;|7: |5:begin|108:// Если значение nCode меньше нуля, процедура перехватчика должна передать сообщение функции CallNextHookEx |79:// без дальнейшей обработки и возвратить значение, возвращаемое CallNextHookEx.|25:if nCode < HC_ACTION then|6: begin|54: result := CallNextHookEx(HHook,nCode,wParam,lParam);|8: exit; |5: end;|1: |14: isNext:=true;|1: |48: tagMLHS := tagMSLLHOOKSTRUCT(pointer(lParam)^);|25: ptr:=@tagMLHS.mouseData;|21: w1:= SmallInt(ptr^);|30: //ptr:= ptr + 1; // only fpc?|13: Inc(ptr, 1);|21: w2:= SmallInt(ptr^);|0:|17: MsgID:= wParam; |24: MousePoint:=tagMLHS.pt;|0:|16: case MsgID of |16: WM_MOUSEMOVE: |7: begin|85: _hi_OnEvent(hiClass.onMouseMove, int2Str(MousePoint.x)+'|'+int2Str(MousePoint.y));|6: end;|16: WM_MOUSEWHEEL:|7: begin|41: _hi_OnEvent(hiClass.onWheelDelta, w2);|6: end;|5: end;|0:|59: _hi_OnEvent(hiClass.onHook, int2Str(MsgID) + int2Str(w2));|0:|89: //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-callnexthookex |15: if isNext then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|10: end |5: else|8: begin|17: result := 1;|7: end;|4:end;|0:|0:|81:// ******************************************************************************|78:// https://learn.microsoft.com/ru-ru/windows/win32/winmsg/lowlevelkeyboardproc|96:function lowlevelkeyboardproc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;|3:var|33: tagKLHS:tagKBDLLHOOKSTRUCT; |5:begin|26: if nCode < HC_ACTION then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|11: exit; |7: end;|1: |15: isNext:=true; |48: tagKLHS:= tagKBDLLHOOKSTRUCT(pointer(lParam)^);|32: VirtualKeyCode:=tagKLHS.vkCode;|29: ScanCode:= tagKLHS.scanCode;|16: MsgID:= wParam;|0:|0:|71: _hi_OnEvent(hiClass.onHook, int2Str(MsgID) + int2Str(tagKLHS.vkCode));|2: |15: if isNext then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|10: end |5: else|8: begin|17: result := 1;|7: end;|4:end;|0:|0:|0:|81:// ******************************************************************************|36:procedure THiAsmClass.doNotCallNext;|5:begin|18: isNext:= false;|4:end;|0:|0:|82:// ****************************************************************************** |29:procedure THiAsmClass.vkCode;|8:begin |33: dtInteger(dt, VirtualKeyCode);|4:end;|0:|0:|82:// ****************************************************************************** |29:procedure THiAsmClass.skCode;|8:begin |27: dtInteger(dt, ScanCode);|4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.MouseX;|8:begin |31: dtInteger(dt, MousePoint.x);|4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.MouseY;|5:begin|31: dtInteger(dt, MousePoint.y);|4:end;|0:|0:|81:// ******************************************************************************|32:procedure THiAsmClass.MessageID;|5:begin|24: dtInteger(dt, MsgID); |4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.doHook;|3:var|18: idHook:integer;|16: lpfn:pointer;|14: hmod:hinst;|20: dwThreadId:dword;|5:begin|31: if HHook > 0 then // installed|8: begin|69: _hi_OnEvent(hiClass.onError, 3); // попытка повторной установки|6: end|5: else|10: begin |39: case ReadInteger(_Data, HookID) of|17: WH_MOUSE_LL:|16: begin |35: idHook:= WH_MOUSE_LL; // 14|34: lpfn:= @lowlevelmouseproc;|31: hmod:= 0; // hInstance;|23: dwThreadId:= 0;|13: end; |20: WH_KEYBOARD_LL:|11: begin|38: idHook:= WH_KEYBOARD_LL; // 13|37: lpfn:= @lowlevelkeyboardproc;|17: hmod:= 0;|23: dwThreadId:= 0;|13: end; |7: end;|3: |91: //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-setwindowshookexa|59: HHook := SetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);|105: // Если функция выполняется успешно, возвращаемое значение является дескриптором процедуры перехватчика.|134: // Если функция завершается сбоем, возвращается значение NULL. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.|28: if HHook = 0 then // Error|55: _hi_OnEvent(hiClass.onError, 0) // ошибка установки|5: else|58: _hi_OnEvent(hiClass.onError, 1); // успешно установлен|3: |48:// ShowMessage(SysErrorMessage(GetLastError)); |57:// 1404 (0x57C) Недопустимый дескриптор перехватчика. |5: end;|4:end;|0:|0:|81:// ******************************************************************************|93:// https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-unhookwindowshookex|68://Если функция выполняется успешно, возвращается ненулевое значение.|138://Если функция выполняется неудачно, возвращается нулевое значение. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.|31:procedure THiAsmClass.doUnHook;|4:var |12: stat:bool;|5:begin|35: stat:= UnhookWindowsHookEx(HHook);|14: if stat then |7: begin|53: _hi_OnEvent(hiClass.onError, 2); // успешно удален|13: HHook:= 0;|6: end;|4:end;|0:|0:|81:// ******************************************************************************|31:constructor THiAsmClass.Create;|5:begin|18: inherited Create;|17: hiClass := self;|4:end;|0:|0:|81:// ******************************************************************************|31:destructor THiAsmClass.Destroy;|5:begin|29: UnhookWindowsHookEx(HHook); |19: inherited Destroy;|4:end;|0:|4:end.| link(onHook ,6051734:doCompare,[]) link(onError ,3330681:doWork2,[]) } Add(Label,13909255,609,245) { Left=5 Top=145 Width=60 Height=17 Caption="выкл. ПКМ" } Add(Button,9575875,609,287) { Left=5 Top=165 Data=Integer(14) link(onClick,8980810:doHook ,[]) } Add(If_else,6051734,798,287) { Op2=Integer(5160) link(onTrue,4587909:doWork2,[]) link(onFalse,2435823:doCompare,[]) } Add(If_else,2435823,854,294) { Op2=Integer(5170) link(onTrue,10188033:doEvent1,[]) } Add(PopupMenuEx,3208102,938,301) { Menu=#5:menu1|5:menu2|1:(|5:menu2|1:)|5:menu3|5:menu4|1:-|5:menu5| Bitmaps=[] } Add(Hub,15542803,658,133) { OutCount=3 link(onEvent1,11918827:doUnHook ,[(692,139)(692,69)]) link(onEvent2,8980810:doUnHook ,[(692,146)(692,300)]) link(onEvent3,8906191:doUnHook ,[(683,153)(683,440)]) } Add(InlineCode,8906191,714,427) { WorkPoints=#69:doHook = Устанавливает процедуру перехватчика в цепочку перехватчиков|80:doUnHook = Удаляет процедуру перехватчика, установленную в цепочке перехватчиков|104:doNotCallNext = Запретить передачу сведений о перехватчике в следующую процедуру в цепочке перехватчиков| EventPoints=#40:onHook = Происходит при каждом перехвате|103:onError = (0)Ошибка установки, (1)Попытка повторной установки, (2)Успешно установлен, (3)Успешно удален|36:onWheelDelta = Прокрутка колеса мыши|51:onMouseMove = Перемещении мыши, в потоке координаты|0:| VarPoints=#35:MessageID = Идентификатор сообщения|52:MouseX = Координаты X курсора в экранных координатах|52:MouseY = Координаты Y курсора в экранных координатах|55:vkCode = Код виртуального ключа в диапазоне от 1 до 254|43:skCode = Код аппаратного сканирования ключа| DataPoints=#54:HookID = Тип перехватчика (14 - мышь, 13 - клавиатура)| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Kol,Share,Debug,Windows;|0:|4:type|28: THiAsmClass = class(TDebug)|8: private|3: |7: public|20: HookID:THI_Event;|4: |20: onHook:THI_Event;|21: onError:THI_Event;|26: onWheelDelta:THI_Event;|29: onMouseMove:THI_Event; |4: |47: procedure MessageID(var dt:TData; idx:word);|44: procedure MouseX(var dt:TData; idx:word);|44: procedure MouseY(var dt:TData; idx:word);|44: procedure vkCode(var dt:TData; idx:word);|44: procedure skCode(var dt:TData; idx:word);|4: |49: procedure doHook(var _Data:TData; Index:word);|51: procedure doUnHook(var _Data:TData; Index:word);|56: procedure doNotCallNext(var _Data:TData; Index:word);|4: |22: constructor Create;|35: destructor Destroy; override; |4:end;|0:|24:type // WH_KEYBOARD_LL|120: tagKBDLLHOOKSTRUCT = record // https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/ns-winuser-kbdllhookstruct|17: vkCode: dword;|19: scanCode: dword;|16: flags: dword;|15: time: dword;|26: dwExtraInfo: ^Cardinal;|4:end;|1: |21:type // WH_MOUSE_LL|117: tagMSLLHOOKSTRUCT = record //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/ns-winuser-msllhookstruct|20: pt:TPoint; // x,y|19: mouseData:Dword;|15: flags:Dword;|14: time:Dword;|24: dwExtraInfo:^Cardinal|6:end; |0:|17:const |132: WH_KEYBOARD_LL = 13; // Устанавливает процедуру перехватчика, которая отслеживает события ввода с клавиатуры низкого уровня. |134: WH_MOUSE_LL = 14; // Устанавливает процедуру перехватчика, которая отслеживает события ввода с помощью мыши низкого уровня. |39:///////////////////////////////////////|16: HC_ACTION = 0;|41://///////////////////////////////////// |39: WM_KEYDOWN = $0100; // 256|39: WM_KEYUP = $0101; // 257|39: WM_SYSKEYDOWN = $0104; // 260|60: WM_SYSKEYUP = $0105; // 261 нету, WM_KEYUP ??? |74://///////////////////////////////////// также как и всех ***BUTTONDBLCLK |47: WM_LBUTTONDOWN = $0201; // 513 левая|39: WM_LBUTTONUP = $0202; // 514|39: WM_LBUTTONDBLCLK = $0203; // 515|48: WM_RBUTTONDOWN = $0204; // 516 правая|39: WM_RBUTTONUP = $0205; // 517|41: WM_RBUTTONDBLCLK = $0206; // 518 |49: WM_MBUTTONDOWN = $0207; // 519 средняя|41: WM_MBUTTONUP = $0208; // 520 |39: WM_MBUTTONDBLCLK = $0209; // 521|49: WM_XBUTTONDOWN = $020B; // 523 боковые|39: WM_XBUTTONUP = $020C; // 524|42: WM_XBUTTONDBLCLK = $020D; // 525 |0:|39: WM_MOUSEMOVE = $0200; // 512|39: WM_MOUSEWHEEL = $020A; // 522|0:|4:var |16: HHook:THandle;|22: hiClass:THiAsmClass;|16: MsgID:integer;|18: isNext:bool; |20: MousePoint:TPoint;|24: VirtualKeyCode: dword;|18: ScanCode: dword;|0:|80:// #############################################################################|15:implementation |0:|0:|81:// ******************************************************************************|74://https://learn.microsoft.com/ru-ru/windows/win32/winmsg/lowlevelmouseproc|127:function lowlevelmouseproc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; //wParam:integer, lParam:integer|8:var |28: tagMLHS:tagMSLLHOOKSTRUCT;|16: ptr:^SmallInt;|18: w1, w2:SmallInt;|7: |5:begin|108:// Если значение nCode меньше нуля, процедура перехватчика должна передать сообщение функции CallNextHookEx |79:// без дальнейшей обработки и возвратить значение, возвращаемое CallNextHookEx.|25:if nCode < HC_ACTION then|6: begin|54: result := CallNextHookEx(HHook,nCode,wParam,lParam);|8: exit; |5: end;|1: |14: isNext:=true;|1: |48: tagMLHS := tagMSLLHOOKSTRUCT(pointer(lParam)^);|25: ptr:=@tagMLHS.mouseData;|21: w1:= SmallInt(ptr^);|30: //ptr:= ptr + 1; // only fpc?|13: Inc(ptr, 1);|21: w2:= SmallInt(ptr^);|0:|17: MsgID:= wParam; |24: MousePoint:=tagMLHS.pt;|0:|16: case MsgID of |16: WM_MOUSEMOVE: |7: begin|85: _hi_OnEvent(hiClass.onMouseMove, int2Str(MousePoint.x)+'|'+int2Str(MousePoint.y));|6: end;|16: WM_MOUSEWHEEL:|7: begin|41: _hi_OnEvent(hiClass.onWheelDelta, w2);|6: end;|5: end;|0:|59: _hi_OnEvent(hiClass.onHook, int2Str(MsgID) + int2Str(w2));|0:|89: //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-callnexthookex |15: if isNext then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|10: end |5: else|8: begin|17: result := 1;|7: end;|4:end;|0:|0:|81:// ******************************************************************************|78:// https://learn.microsoft.com/ru-ru/windows/win32/winmsg/lowlevelkeyboardproc|96:function lowlevelkeyboardproc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;|3:var|33: tagKLHS:tagKBDLLHOOKSTRUCT; |5:begin|26: if nCode < HC_ACTION then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|11: exit; |7: end;|1: |15: isNext:=true; |48: tagKLHS:= tagKBDLLHOOKSTRUCT(pointer(lParam)^);|32: VirtualKeyCode:=tagKLHS.vkCode;|29: ScanCode:= tagKLHS.scanCode;|16: MsgID:= wParam;|0:|0:|71: _hi_OnEvent(hiClass.onHook, int2Str(MsgID) + int2Str(tagKLHS.vkCode));|2: |15: if isNext then|8: begin|57: result := CallNextHookEx(HHook,nCode,wParam,lParam);|10: end |5: else|8: begin|17: result := 1;|7: end;|4:end;|0:|0:|0:|81:// ******************************************************************************|36:procedure THiAsmClass.doNotCallNext;|5:begin|18: isNext:= false;|4:end;|0:|0:|82:// ****************************************************************************** |29:procedure THiAsmClass.vkCode;|8:begin |33: dtInteger(dt, VirtualKeyCode);|4:end;|0:|0:|82:// ****************************************************************************** |29:procedure THiAsmClass.skCode;|8:begin |27: dtInteger(dt, ScanCode);|4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.MouseX;|8:begin |31: dtInteger(dt, MousePoint.x);|4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.MouseY;|5:begin|31: dtInteger(dt, MousePoint.y);|4:end;|0:|0:|81:// ******************************************************************************|32:procedure THiAsmClass.MessageID;|5:begin|24: dtInteger(dt, MsgID); |4:end;|0:|0:|81:// ******************************************************************************|29:procedure THiAsmClass.doHook;|3:var|18: idHook:integer;|16: lpfn:pointer;|14: hmod:hinst;|20: dwThreadId:dword;|5:begin|31: if HHook > 0 then // installed|8: begin|69: _hi_OnEvent(hiClass.onError, 3); // попытка повторной установки|6: end|5: else|10: begin |39: case ReadInteger(_Data, HookID) of|17: WH_MOUSE_LL:|16: begin |35: idHook:= WH_MOUSE_LL; // 14|34: lpfn:= @lowlevelmouseproc;|31: hmod:= 0; // hInstance;|23: dwThreadId:= 0;|13: end; |20: WH_KEYBOARD_LL:|11: begin|38: idHook:= WH_KEYBOARD_LL; // 13|37: lpfn:= @lowlevelkeyboardproc;|17: hmod:= 0;|23: dwThreadId:= 0;|13: end; |7: end;|3: |91: //https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-setwindowshookexa|59: HHook := SetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);|105: // Если функция выполняется успешно, возвращаемое значение является дескриптором процедуры перехватчика.|134: // Если функция завершается сбоем, возвращается значение NULL. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.|28: if HHook = 0 then // Error|55: _hi_OnEvent(hiClass.onError, 0) // ошибка установки|5: else|58: _hi_OnEvent(hiClass.onError, 1); // успешно установлен|3: |48:// ShowMessage(SysErrorMessage(GetLastError)); |57:// 1404 (0x57C) Недопустимый дескриптор перехватчика. |5: end;|4:end;|0:|0:|81:// ******************************************************************************|93:// https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-unhookwindowshookex|68://Если функция выполняется успешно, возвращается ненулевое значение.|138://Если функция выполняется неудачно, возвращается нулевое значение. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.|31:procedure THiAsmClass.doUnHook;|4:var |12: stat:bool;|5:begin|35: stat:= UnhookWindowsHookEx(HHook);|14: if stat then |7: begin|53: _hi_OnEvent(hiClass.onError, 2); // успешно удален|13: HHook:= 0;|6: end;|4:end;|0:|0:|81:// ******************************************************************************|31:constructor THiAsmClass.Create;|5:begin|18: inherited Create;|17: hiClass := self;|4:end;|0:|0:|81:// ******************************************************************************|31:destructor THiAsmClass.Destroy;|5:begin|29: UnhookWindowsHookEx(HHook); |19: inherited Destroy;|4:end;|0:|4:end.| link(onHook ,7306711:doCompare,[]) link(onError ,3330681:doWork3,[(774,440)]) } Add(Label,7717945,609,385) { Left=5 Top=200 Width=118 Height=17 Caption="замена [insert] на [Esc]" } Add(Button,8323453,609,427) { Left=5 Top=225 Data=Integer(13) link(onClick,8906191:doHook ,[]) } Add(If_else,7306711,798,427) { Op2=Integer(25645) link(onTrue,5308299:doEvent1,[]) link(onFalse,3632556:doCompare,[]) } Add(If_else,3632556,854,434) { Op2=Integer(25745) link(onTrue,9831407:doEvent1,[]) } Add(KeyEvent,2061080,987,427) { Code=27 } Add(HubEx,4587909,917,287) { Angle=3 link(onEvent,8980810:doNotCallNext ,[(921,270)(702,270)(702,307)]) } Add(Hub,10188033,896,294) { link(onEvent1,4587909:doWork3,[(921,300)]) link(onEvent2,3208102:doPopupHere,[]) } Add(HubEx,14705005,770,112) { link(onEvent,16480506:doAdd,[]) } Add(HubEx,3330681,770,294) { Angle=3 link(onEvent,14705005:doWork3,[]) } Add(Hub,5308299,931,427) { link(onEvent1,12541952:doWork2,[(956,433)(956,412)]) link(onEvent2,2061080:doPressDown,[]) } Add(HubEx,12541952,917,406) { Angle=2 link(onEvent,8906191:doNotCallNext ,[(702,412)(702,447)]) } Add(Hub,9831407,896,434) { link(onEvent1,12541952:doWork3,[(921,440)]) link(onEvent2,2061080:doPressUp,[]) }