From 864081102a5f252415f41950b3039a896b4ae9c5 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 8 Oct 2012 18:43:29 +0000 Subject: Awkwars's plugins - welcome to our trunk git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Utils.pas/old/hotkeys.pas | 574 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 574 insertions(+) create mode 100644 plugins/Utils.pas/old/hotkeys.pas (limited to 'plugins/Utils.pas/old/hotkeys.pas') diff --git a/plugins/Utils.pas/old/hotkeys.pas b/plugins/Utils.pas/old/hotkeys.pas new file mode 100644 index 0000000000..32f6e201e5 --- /dev/null +++ b/plugins/Utils.pas/old/hotkeys.pas @@ -0,0 +1,574 @@ +{Hotkey and timer related functions} +unit hotkeys; + +interface + +uses windows; + +type + AWKHotKeyProc = function(hotkey:integer):integer; + +function AddProc(aproc:AWKHotKeyProc;ahotkey:integer;global:bool=false):integer; overload; +function AddProc(ahotkey:integer;wnd:HWND;aproc:AWKHotKeyProc ):integer; overload; +function AddProc(ahotkey:integer;wnd:HWND;msg:uint_ptr ):integer; overload; +function DelProc(hotkey:integer ):integer; overload; +function DelProc(hotkey:integer;wnd:HWND):integer; overload; + +procedure InitHotKeys; +procedure FreeHotKeys; + +implementation + +uses messages; + +const + HWND_MESSAGE = HWND(-3); + +var + CurThread:THANDLE; + +type + PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT; + TKBDLLHOOKSTRUCT = record + vkCode :dword; + scanCode :dword; + flags :dword; + time :dword; + dwExtraInfo:dword; + end; + +const + WH_KEYBOARD_LL = 13; + WM_MYMESSAGE = WM_USER +13; + +// const from commctrl module; +const + HOTKEYF_SHIFT = $01; + HOTKEYF_CONTROL = $02; + HOTKEYF_ALT = $04; + HOTKEYF_EXT = $08; + +const + hkAssigned = 1; + hkGlobal = 2; + hkMessage = 4; +const + kbHook:THANDLE=0; + hiddenwindow:HWND=0; + modifiers:dword=0; +const + PageStep = 10; +type + PHKRec = ^THKRec; + THKRec = record + proc :AWKHotKeyProc; // procedure + flags :integer; // options + handle:THANDLE; // thread or window? + atom :TATOM; // hotkey id + hotkey:integer; // hotkey + end; + PHKRecs = ^THKRecs; + THKRecs = array [0..15] of THKRec; + +const + NumRecs:integer=0; + MaxRecs:integer=10; + hkRecs:pHKRecs=nil; + +//----- simpler version of 'common' function ----- + +const + HexDigitChr: array [0..15] of AnsiChar = ('0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'); + +function IntToHex(dst:PAnsiChar;Value:cardinal):PAnsiChar; +var + Digits:integer; +begin + dst[8]:=#0; + Digits:=8; + repeat + Dec(Digits); + dst[Digits]:=HexDigitChr[Value and $F]; + Value:=Value shr 4; + until Digits=0; + result:=dst; +end; + +//----- utils ----- + +function GetAtom(hotkey:dword):dword; +const + HKPrefix = 'awk_'; +var + p:array [0..15] of AnsiChar; +begin + lstrcpya(p,HKPrefix); + IntToHex(p+Length(HKPrefix),hotkey); + result:=GlobalAddAtomA(p); +end; + +function HotKeyDlgToHook(w:cardinal):cardinal; register; +asm + movzx ecx,al + xor al,al + test ah,HOTKEYF_ALT + je @L1 + or al,MOD_ALT +@L1: + test ah,HOTKEYF_CONTROL + je @L2 + or al,MOD_CONTROL +@L2: + test ah,HOTKEYF_SHIFT + je @L3 + or al,MOD_SHIFT +@L3: + test ah,HOTKEYF_EXT + je @L4 + or al,MOD_WIN +@L4: + mov ch,al + mov eax,ecx +{ +begin + result:=w and $FF; + if (w and (HOTKEYF_ALT shl 8))<>0 then result:=result or (MOD_ALT shl 8); + if (w and (HOTKEYF_CONTROL shl 8))<>0 then result:=result or (MOD_CONTROL shl 8); + if (w and (HOTKEYF_SHIFT shl 8))<>0 then result:=result or (MOD_SHIFT shl 8); + if (w and (HOTKEYF_EXT shl 8))<>0 then result:=result or (MOD_WIN shl 8); +} +end; + +function HotKeyHookToDlg(w:cardinal):cardinal; register; +asm + movzx ecx,al + xor al,al + test ah,MOD_ALT + je @L1 + or al,HOTKEYF_ALT +@L1: + test ah,MOD_CONTROL + je @L2 + or al,HOTKEYF_CONTROL +@L2: + test ah,MOD_SHIFT + je @L3 + or al,HOTKEYF_SHIFT +@L3: + test ah,MOD_WIN + je @L4 + or al,HOTKEYF_EXT +@L4: + mov ch,al + mov eax,ecx +{ +begin + result:=w and $FF; + if (w and (MOD_ALT shl 8))<>0 then result:=result or (HOTKEYF_ALT shl 8); + if (w and (MOD_CONTROL shl 8))<>0 then result:=result or (HOTKEYF_CONTROL shl 8); + if (w and (MOD_SHIFT shl 8))<>0 then result:=result or (HOTKEYF_SHIFT shl 8); + if (w and (MOD_WIN shl 8))<>0 then result:=result or (HOTKEYF_EXT shl 8); +} +end; + +//----- Hook ----- + +function FindHotkey(keycode:integer;local:boolean):pointer; +var + i:integer; + p:pHKRec; +begin + i:=NumRecs; + p:=pointer(HKRecs); + while i>0 do + begin + dec(i); + with p^ do + begin + if (flags and hkAssigned)<>0 then + begin + if (local xor ((flags and hkGlobal)<>0)) then + begin + if hotkey=keycode then + begin + if handle<>0 then + begin + if GetFocus=handle then + begin + if (flags and hkMessage)<>0 then + begin + PostMessage(handle,wparam(@proc),keycode,0); + result:=pointer(-1); + end + else + result:=@proc; + exit; + end; + end + else + begin + result:=@proc; + exit; + end; + end; + end; + end; + end; + inc(p); + end; + result:=nil; +end; + +function wmKeyboard_hook(code:integer;wParam:WPARAM;lParam:LPARAM):longint; stdcall; +var + key:dword; + proc:pointer; +begin + if (code=HC_ACTION) and + (lParam>0) and (LoWord(lParam)=1) then + begin + key:=0; + if (GetKeyState(VK_SHIFT ) and $8000)<>0 then key:=key or (MOD_SHIFT shl 8); + if (GetKeyState(VK_CONTROL) and $8000)<>0 then key:=key or (MOD_CONTROL shl 8); + if (GetKeyState(VK_MENU ) and $8000)<>0 then key:=key or (MOD_ALT shl 8); + if (GetKeyState(VK_LWIN ) and $8000)<>0 then key:=key or (MOD_WIN shl 8); + if (GetKeyState(VK_RWIN ) and $8000)<>0 then key:=key or (MOD_WIN shl 8); +// if (GetKeyState(VK_APPS) and $8000)<>0 then +// if (GetKeyState(VK_SLEEP) and $8000)<>0 then + key:=key or (cardinal(wParam) and $FF); + proc:=FindHotkey(key,true); + if proc<>nil then + begin + if proc<>pointer(-1) then + PostMessageA(hiddenwindow,WM_MYMESSAGE,key,windows.lparam(proc)); + result:=1; + exit; + end; + end; + result:=CallNextHookEx(KbHook,code,wParam,lParam); +end; + +function wmKeyboardLL_hook(code:integer;wParam:WPARAM;lParam:LPARAM):integer; stdcall; +const + lastkey:dword=0; +var + mask:dword; + key:dword; + proc:pointer; +begin + if code=HC_ACTION then + begin + case PKBDLLHOOKSTRUCT(lParam)^.vkCode of + VK_MENU, + VK_LMENU, + VK_RMENU: mask:=MOD_ALT shl 8; + VK_LWIN, + VK_RWIN: mask:=MOD_WIN shl 8; + VK_SHIFT, + VK_LSHIFT, + VK_RSHIFT: mask:=MOD_SHIFT shl 8; + VK_CONTROL, + VK_LCONTROL, + VK_RCONTROL: mask:=MOD_CONTROL shl 8; + else + if (PKBDLLHOOKSTRUCT(lParam)^.flags and 128)=0 then + begin + // local only +// maybe process will better choice? + if //(lastkey=0) and + (CurThread=GetWindowThreadProcessId(GetForegroundWindow,nil)) then + begin + key:=PKBDLLHOOKSTRUCT(lParam)^.vkCode or modifiers; + proc:=FindHotkey(key,true); + if proc<>nil then + begin + lastkey:=PKBDLLHOOKSTRUCT(lParam)^.vkCode; + if proc<>pointer(-1) then + PostMessageA(hiddenwindow,WM_MYMESSAGE,key,windows.lparam(proc)); + result:=1; + exit; + end; + end; + end + else if (lastkey<>0) and (lastkey=PKBDLLHOOKSTRUCT(lParam)^.vkCode) then + begin + lastkey:=0; + result :=1; + exit; + end; + mask:=0; + end; + if mask<>0 then + begin + if (PKBDLLHOOKSTRUCT(lParam)^.flags and 128)=0 then + modifiers:=modifiers or mask + else + modifiers:=modifiers and not mask; + end + end; + result:=CallNextHookEx(KbHook,code,wParam,lParam); +end; + +function HiddenWindProc(wnd:HWnd;msg:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + key:dword; +begin + if Msg=WM_HOTKEY then + begin + key:=(lParam shr 16)+((lParam and $FF) shl 8); + result:=lresult(FindHotKey(key,false)); + if result<>0 then + begin + result:=AWKHotKeyProc(result)(HotkeyHookToDlg(key)); + exit; + end; + end + else if Msg=WM_MYMESSAGE then + begin + result:=AWKHotKeyProc(lParam)(HotkeyHookToDlg(wParam)); + exit; + end; + result:=DefWindowProcA(wnd,msg,wparam,lparam); +end; + +procedure DestroyHiddenWindow; +begin + if hiddenwindow<>0 then + begin + DestroyWindow(hiddenwindow); + hiddenwindow:=0; + end; +end; + +procedure CreateHiddenWindow; +var + wnd:HWND; +begin + if hiddenwindow=0 then + begin + wnd:=CreateWindowExA(0,'STATIC',nil,0, + 1,1,1,1,HWND_MESSAGE,0,hInstance,nil); + if wnd<>0 then + begin + SetWindowLongPtrA(wnd,GWL_WNDPROC,LONG_PTR(@HiddenWindProc)); + hiddenwindow:=wnd; + end + end +end; +//----- interface ----- + +function CheckTable(ahotkey:integer;global:bool):integer; +var + tmp:pHKRecs; + i:integer; + p:pHKRec; +begin + if HKRecs=nil then + begin + MaxRecs:=PageStep; + GetMem (HKRecs ,MaxRecs*SizeOf(THKRec)); + FillChar(HKRecs^,MaxRecs*SizeOf(THKRec),0); + NumRecs:=0; + end; + // search existing + i:=0; + p:=pointer(HKRecs); + while i0 then + begin + if (p^.hotkey=ahotkey) and + (((p^.flags and hkGlobal)<>0) xor not global) then + break; + end; + inc(p); + inc(i); + end; + //search empty + if i=NumRecs then + begin + i:=0; + p:=pointer(HKRecs); + while i0 do + begin + dec(i); + if ((p^.flags and hkAssigned)<>0) and (p^.handle=0) then + if p^.hotkey=hotkey then + begin + if (p^.flags and hkGlobal)<>0 then + begin + UnregisterHotKey(hiddenwindow,p^.atom); + GlobalDeleteAtom(p^.atom); + end; + p^.flags:=p^.flags and not hkAssigned; + result:=i; + exit; + end; + inc(p); + end; + result:=0; +end; + +function DelProc(hotkey:integer;wnd:HWND):integer; +var + i:integer; + p:pHKRec; +begin + hotkey:=HotKeyDlgToHook(hotkey); //!! + p:=pointer(HKRecs); + i:=NumRecs; + while i>0 do + begin + dec(i); + if (p^.flags and hkAssigned)<>0 then + if (p^.handle=wnd) {and ((p^.flags and hkGlobal)=0)} then + begin + if (hotkey=0) or (hotkey=p^.hotkey) then + begin + p^.flags:=p^.flags and not hkAssigned; + result:=i; + exit; + end; + end; + inc(p); + end; + result:=0; +end; + +procedure InitHotKeys; +begin + MaxRecs:=10; + GetMem(HKRecs,SizeOf(THKRec)*MaxRecs); + FillChar(HKRecs^,SizeOf(THKRec)*MaxRecs,0); + NumRecs:=0; + CreateHiddenWindow; + kbhook:=SetWindowsHookExA(WH_KEYBOARD_LL,@wmKeyboardLL_hook,hInstance,0); + + if KbHook=0 then + KbHook:=SetWindowsHookExA(WH_KEYBOARD,@wmKeyboard_hook,0,GetCurrentThreadId); +end; + +procedure FreeHotKeys; +var + i:integer; + p:pHKRec; +begin + i:=NumRecs; + p:=pointer(HKRecs); + while i>0 do + begin + dec(i); + if (p^.flags and (hkAssigned or hkGlobal))=(hkAssigned or hkGlobal) then + begin + UnregisterHotKey(hiddenwindow,p^.atom); + GlobalDeleteAtom(p^.atom); + end; + inc(p); + end; + DestroyHiddenWindow; + if kbhook<>0 then + UnhookWindowsHookEx(kbhook); + FreeMem(HKRecs); + HKRecs:=nil; + MaxRecs:=0; + NumRecs:=0; +end; + +initialization + CurThread:=GetCurrentThreadId(); +end. \ No newline at end of file -- cgit v1.2.3