![]() |
Simulierten Hotkey per WMHotKey abfangen?
Hi,
ich habe mir einen Keyboard-Hook mit WMHotKey geschrieben (Anleitung ist ja hier zu finden). Das klappt auch super mit der Tastatur! Alle Registrierten Hooks werden erkannt! Jedoch möchte ich jetzt noch Simulierte Tastendrücke abfangen! Und zwar habe ich das Programm "Girder 4" (IR-Empfänger Programm für PC: ![]() Dies wertet die IR-Signale aus und gibt sie per z.B. SHIFT-B, Escape usw. weiter. Nun reagiert aber WMHotKey auf diese Befehle überhaupt nicht! Kann man das irgendwie lösen? |
Re: Simulierten Hotkey per WMHotKey abfangen?
Zitat:
|
Re: Simulierten Hotkey per WMHotKey abfangen?
Mit Globalen Hotkey per RegisterHotKey per diesen sample Code:
Code:
{
The following example demonstrates registering hotkeys with the system to globally trap keys. Das Folgende Beispiel zeigt, wie man Hotkeys registrieren und darauf reagieren kann, wenn sie gedrückt werden. (systemweit) } unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } id1, id2, id3, id4: Integer; procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} // Trap Hotkey Messages procedure TForm1.WMHotKey(var Msg: TWMHotKey); begin if Msg.HotKey = id1 then ShowMessage('Ctrl + A pressed !'); if Msg.HotKey = id2 then ShowMessage('Ctrl + Alt + R pressed !'); if Msg.HotKey = id3 then ShowMessage('Win + F4 pressed !'); if Msg.HotKey = id4 then ShowMessage('Print Screen pressed !'); end; procedure TForm1.FormCreate(Sender: TObject); // Different Constants from Windows.pas const MOD_ALT = 1; MOD_CONTROL = 2; MOD_SHIFT = 4; MOD_WIN = 8; VK_A = $41; VK_R = $52; VK_F4 = $73; begin // Register Hotkey Ctrl + A id1 := GlobalAddAtom('Hotkey1'); RegisterHotKey(Handle, id1, MOD_CONTROL, VK_A); // Register Hotkey Ctrl + Alt + R id2 := GlobalAddAtom('Hotkey2'); RegisterHotKey(Handle, id2, MOD_CONTROL + MOD_Alt, VK_R); // Register Hotkey Win + F4 id3 := GlobalAddAtom('Hotkey3'); RegisterHotKey(Handle, id3, MOD_WIN, VK_F4); // Globally trap the Windows system key "PrintScreen" id4 := GlobalAddAtom('Hotkey4'); RegisterHotKey(Handle, id4, 0, VK_SNAPSHOT); end; // Unregister the Hotkeys procedure TForm1.FormDestroy(Sender: TObject); begin UnRegisterHotKey(Handle, id1); GlobalDeleteAtom(id1); UnRegisterHotKey(Handle, id2); GlobalDeleteAtom(id2); UnRegisterHotKey(Handle, id3); GlobalDeleteAtom(id3); UnRegisterHotKey(Handle, id4); GlobalDeleteAtom(id4); end; end. { RegisterHotKey fails if the keystrokes specified for the hot key have already been registered by another hot key. Windows NT4 and Windows 2000/XP: The F12 key is reserved for use by the debugger at all times, so it should not be registered as a hot key. Even when you are not debugging an application, F12 is reserved in case a kernel-mode debugger or a just-in-time debugger is resident. } |
Re: Simulierten Hotkey per WMHotKey abfangen?
Hi,
hab jetzt eine Hook mit DLL getestet! Dieser fängt die Simulierten Befehle von Girder ab. Jedoch habe ich zu wenig Erfahrung mit dem ganzen und deswegen habe ich noch ein Frage: Wie kann ich jetzt Kombinationen wie SHIFT+D oder CTRL+D abfangen? Einzelne Tasten wie VK_Escape kann ich ohne Probleme abfangen. Kann mir da noch jemand helfen?
Code:
unit WHookInt;
interface uses Windows, Messages, SysUtils, msxml, Forms, unit2; function SetHook(WinHandle: HWND; MsgToSend: Integer): Boolean; stdcall; export; function FreeHook: Boolean; stdcall; export; function MsgFilterFunc(Code: Integer; wParam, lParam: Longint): Longint stdcall; export; implementation // Memory map file stuff { The CreateFileMapping function creates unnamed file-mapping object for the specified file. } function CreateMMF(Name: string; Size: Integer): THandle; begin Result := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, Size, PChar(Name)); if Result <> 0 then begin if GetLastError = ERROR_ALREADY_EXISTS then begin CloseHandle(Result); Result := 0; end; end; end; { The OpenFileMapping function opens a named file-mapping object. } function OpenMMF(Name: string): THandle; begin Result := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, PChar(Name)); // The return value is an open handle to the specified file-mapping object. end; { The MapViewOfFile function maps a view of a file into the address space of the calling process. } function MapMMF(MMFHandle: THandle): Pointer; begin Result := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0); end; { The UnmapViewOfFile function unmaps a mapped view of a file from the calling process's address space. } function UnMapMMF(P: Pointer): Boolean; begin Result := UnmapViewOfFile(P); end; function CloseMMF(MMFHandle: THandle): Boolean; begin Result := CloseHandle(MMFHandle); end; // Actual hook stuff type TPMsg = ^TMsg; const VK_D = $44; VK_E = $45; VK_F = $46; VK_M = $4D; VK_R = $52; MMFName = 'MsgFilterHookDemo'; type PMMFData = ^TMMFData; TMMFData = record NextHook: HHOOK; WinHandle: HWND; MsgToSend: Integer; end; // global variables, only valid in the process which installs the hook. var MMFHandle: THandle; MMFData: PMMFData; function UnMapAndCloseMMF: Boolean; begin Result := False; if UnMapMMF(MMFData) then begin MMFData := nil; if CloseMMF(MMFHandle) then begin MMFHandle := 0; Result := True; end; end; end; { The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. WH_GETMESSAGE Installs a hook procedure that monitors messages posted to a message queue. For more information, see the GetMsgProc hook procedure. } function SetHook(WinHandle: HWND; MsgToSend: Integer): Boolean; stdcall; var test : boolean; begin if (MMFData = nil) and (MMFHandle = 0) then begin MMFHandle := CreateMMF(MMFName, SizeOf(TMMFData)); if MMFHandle <> 0 then begin MMFData := MapMMF(MMFHandle); if MMFData <> nil then begin MMFData.WinHandle := WinHandle; MMFData.MsgToSend := MsgToSend; MMFData.NextHook := SetWindowsHookEx(WH_GETMESSAGE, MsgFilterFunc, HInstance, 0); if MMFData.NextHook = 0 then UnMapAndCloseMMF else Result := True; end else begin CloseMMF(MMFHandle); MMFHandle := 0; end; end; end; end; { The UnhookWindowsHookEx function removes the hook procedure installed in a hook chain by the SetWindowsHookEx function. } function FreeHook: Boolean; stdcall; begin Result := False; if (MMFData <> nil) and (MMFHandle <> 0) then if UnHookWindowsHookEx(MMFData^.NextHook) then Result := UnMapAndCloseMMF; end; (* GetMsgProc( nCode: Integer; {the hook code} wParam: WPARAM; {message removal flag} lParam: LPARAM {a pointer to a TMsg structure} ): LRESULT; {this function should always return zero} { See help on ==> GetMsgProc} *) function MsgFilterFunc(Code: Integer; wParam, lParam: Longint): Longint; var MMFHandle: THandle; MMFData: PMMFData; Kill: boolean; F: TForm2; begin Result := 0; MMFHandle := OpenMMF(MMFName); if MMFHandle <> 0 then begin MMFData := MapMMF(MMFHandle); if MMFData <> nil then begin if (Code < 0) or (wParam = PM_NOREMOVE) then { The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain. } Result := CallNextHookEx(MMFData.NextHook, Code, wParam, lParam) else begin Kill := False; { Examples } with TMsg(Pointer(lParam)^) do begin // Kill Numbers if (wParam >= 48) and (wParam <= 57) then Kill := True; // Kill Tabulator if (wParam = VK_TAB) then Kill := True; end; if TPMsg(lParam)^.wParam = VK_Escape then begin Kill := True; end; //MessageBox(0,TPMsg(lParam)^.message,'testme',mb_Ok); { Example to disable all the start-Key combinations } // F.Label1.Caption := 'Test';//inttostr(2); //F.Label1.Caption := inttostr(TPMsg(lParam)^.wParam ); case TPMsg(lParam)^.message of // WM_SYSCOMMAND: // The Win Start Key (or Ctrl+ESC) // if TPMsg(lParam)^.wParam = SC_TASKLIST then Kill := True; WM_HOTKEY: case ((TPMsg(lParam)^.lParam and $00FF0000) shr 16) of VK_D, // Win+D ==> Desktop VK_E, // Win+E ==> Explorer VK_F, // Win+F+(Ctrl) ==> Find:All (and Find: Computer) VK_M, // Win+M ==> Minimize all VK_R, // Win+R ==> Run program. VK_F1, // Win+F1 ==> Windows Help VK_PAUSE: // Win+Pause ==> Windows system properties Kill := True; end; end; if Kill then TPMsg(lParam)^.message := WM_NULL; Result := CallNextHookEx(MMFData.NextHook, Code, wParam, lParam) end; UnMapMMF(MMFData); end; CloseMMF(MMFHandle); end; end; initialization begin MMFHandle := 0; MMFData := nil; end; finalization FreeHook; end. |
Re: Simulierten Hotkey per WMHotKey abfangen?
Also ich habe jetzt folgendes Probiert:
Code:
Sinn der Sache ist ein Test um STRG+S per Hook Abfangen zu können. Es geht aber nicht!
if (TPMsg(lParam)^.message) = WM_KEYDOWN then begin
if TPMsg(lParam)^.wParam = VK_CONTROL then begin CTRLPressed := True; end; end; if (TPMsg(lParam)^.message) = WM_KEYUP then begin if TPMsg(lParam)^.wParam = VK_CONTROL then begin CTRLPressed := False; end; end; if (TPMsg(lParam)^.message) = WM_KEYDOWN then begin if TPMsg(lParam)^.wParam = VK_S and CTRLPressed then begin Kill := True; end; end; Kann mir keiner Tipps geben wie das mit Hooks + Tasenkombinationen zu machen ist! |
Re: Simulierten Hotkey per WMHotKey abfangen?
Delphi-Quellcode:
if (GetKeyState(VK_CONTROL)< 0) // CTRL gedrückt then
begin if TPMsg(lParam)^.wParam = vkKeyScan('s') // S-Taste then begin if TPMsg(lParam)^.message = WM_KEYDOWN then// Taste unten begin Messagebox(0, 'Strg + s', 'H O O K', 0); Kill := True; end; end; end; |
Re: Simulierten Hotkey per WMHotKey abfangen?
Danke! geht super!
Nun möchte ich das ganze noch dynamisch machen:
Code:
TempRecord = record
str1: string; str2: string; car1: cardinal; car2: cardinal; car3: cardinal;
Code:
HandleHook : Array[1..2] of TempRecord =
( (str1:'Test1'; str2:'test'; car1:VK_CONTROL; car2:VK_S; car3:0), (str1:'Test2'; str2:'test'; car1:VK_SHIFT; car2:VK_D; car3:0) );
Code:
Nun spricht aber der Hook nur auf den ersten Eintrag an, aber nicht auf den zweiten!?
for i := 0 to High(HandleHook) - 1 do begin
if (GetKeyState(HandleHook[i].car1)< 0) then // Cardinal 1 begin if TPMsg(lParam)^.wParam = HandleHook[i].car2 then // Cardinal 2 begin if TPMsg(lParam)^.message = WM_KEYDOWN then// Taste unten begin Messagebox(0, 'Example', 'H O O K', 0); Kill := True; end; end; end; end; Ich will einen Hook für Speziele Tastenkombinationen machen, die eben per z.B. Girder geschickt werden. Dazu muss ich halt CTRL+E, CTRL+P, SHIFT+E usw extra abfangen können. EDIT: habe das "Problem" gefunden... :angel2: wenn i bei 0 zu zählen anfängt aber das Array erst bei 1 losgeht... :roll: |
Re: Simulierten Hotkey per WMHotKey abfangen?
Hab jetzt alles dynamisch gelöst:
Code:
Hirmit kann ich 1, 2 & 3 Tasten-Codes abfangen.
//ein Tasten Shorcut
if (TPMsg(lParam)^.wParam = HandleHook[i].car3) and (HandleHook[i].car4 = 0) and (HandleHook[i].car5 = 0) then // 1. Cardinal begin if TPMsg(lParam)^.message = WM_KEYDOWN then// Taste unten begin SetForeGroundWIndow(WindowHandle); keybd_event(HandleHook[i].car1, 0, 0, 0); if not (HandleHook[i].car2 = 0) then begin keybd_event(HandleHook[i].car2, 0, 0, 0); keybd_event(HandleHook[i].car1, 0, KEYEVENTF_KEYUP,0); keybd_event(HandleHook[i].car2, 0, KEYEVENTF_KEYUP,0); end else keybd_event(HandleHook[i].car1, 0, KEYEVENTF_KEYUP,0); Messagebox(0, PChar(HandleHook[i].str1), 'H O O K', 0); Kill := True; end; end //zwei Tasten Shorcut else if (GetKeyState(HandleHook[i].car3)< 0) and (HandleHook[i].car4 <> 0) and (HandleHook[i].car5 = 0) then // 1. Cardinal begin if TPMsg(lParam)^.wParam = HandleHook[i].car4 then // 2. Cardinal begin if TPMsg(lParam)^.message = WM_KEYDOWN then// Taste unten begin SetForeGroundWIndow(WindowHandle); keybd_event(HandleHook[i].car1, 0, 0, 0); if not (HandleHook[i].car2 = 0) then begin keybd_event(HandleHook[i].car2, 0, 0, 0); keybd_event(HandleHook[i].car1, 0, KEYEVENTF_KEYUP,0); keybd_event(HandleHook[i].car2, 0, KEYEVENTF_KEYUP,0); end else keybd_event(HandleHook[i].car1, 0, KEYEVENTF_KEYUP,0); Messagebox(0, PChar(HandleHook[i].str1), 'H O O K', 0); Kill := True; end; end; end //drei Tasten Shorcut else if (GetKeyState(HandleHook[i].car3)< 0) and (GetKeyState(HandleHook[i].car4)< 0) then // 1. + 2. Cardinal begin if TPMsg(lParam)^.wParam = HandleHook[i].car5 then // 3. Cardinal begin if TPMsg(lParam)^.message = WM_KEYDOWN then// Taste unten begin SetForeGroundWIndow(WindowHandle); keybd_event(HandleHook[i].car1, 0, 0, 0); if not (HandleHook[i].car2 = 0) then begin keybd_event(HandleHook[i].car2, 0, 0, 0); keybd_event(HandleHook[i].car1, 0, KEYEVENTF_KEYUP,0); keybd_event(HandleHook[i].car2, 0, KEYEVENTF_KEYUP,0); end else keybd_event(HandleHook[i].car1, 0, KEYEVENTF_KEYUP,0); Messagebox(0, PChar(HandleHook[i].str1), 'H O O K', 0); Kill := True; end; end; end; Nun Fange ich z.B. die Tast "ESC" ab. Geht auch super! Mein Problem ist nun wenn ich aus: Abfangen -> Weiterschicken ESC -> Enter Enter -> Enter mache, verfängt sich die Schleife natürlich in eine Endlosschleife wenn ich nun "Esc" drücke! Sinn der Sache ist: Ich habe 3 Programme, Prog1 sendet an Prog2 einen Shortcut. Dieser soll jedoch abgefangen werden und an Prog3 geschickt werden. Muss ich da jetzt jedesmal bevor ich ein keybd_event auslöse den Hook wieder auflösen damit es sich nicht endlos in der Schleife verfängt? EDIT: zusätzlich habe ich herausgefunden, dass die Variable "HandleHook[i]", die Global definiert ist meinen Hook auf nurmehr Lokal verändert! Wie kann ich das noch übergehen, denn die Array HandleHook wird in einer anderen Funktion bei SetHook erst aufgefüllt. |
Re: Simulierten Hotkey per WMHotKey abfangen?
ManOMan.. bin am verzweifeln!
Das mit den Globalen Variabeln und MMF habe ich hinbekommen, aber nicht das Problem dass die MsgFilterFunc auch auf die eigenen keybd_events reagiert! Habe versucht den Hook vor dem Keyboard Event aufzulösen. Das bringt aber auch nichts -> Endlosschleife! z.B. Ich fange vom 1. Programm ein "Up" ab, dass für Programm 2 bestimmt gewesen wäre. Dann sende ich das "Up" an Program 3 das ich zuerst in den Vordergrund geholt habe! Kann mir da nochmal jemand Helfen!?
Code:
//ein Tasten Shorcut z.B. Up -> Up, Esc -> Enter, Enter -> Enter,...
if ((TPMsg(lParam)^.wParam = HandleHook[x].car3) and (HandleHook[x].car4 = 0) and (HandleHook[x].car5 = 0)) then // 1. Cardinal begin if TPMsg(lParam)^.message = WM_KEYDOWN then// Taste unten begin TPMsg(lParam)^.message := WM_NULL; //Originale Message löschen Result := CallNextHookEx(MMFData.NextHook, Code, wParam, lParam); ClearTempArray(HandleHook); //HandleHook[x].car3.. bis car5 auf 0 setzen damit oben nicht mehr auf einen Tastendruck reagiert wird SetForeGroundWIndow(MMFData.ProgramHandle); keybd_event(HandleHook[x].car1, 0, 0, 0); if not (HandleHook[x].car2 = 0) then begin keybd_event(HandleHook[x].car2, 0, 0, 0); keybd_event(HandleHook[x].car1, 0, KEYEVENTF_KEYUP,0); keybd_event(HandleHook[x].car2, 0, KEYEVENTF_KEYUP,0); end else keybd_event(HandleHook[x].car1, 0, KEYEVENTF_KEYUP,0); //Messagebox(0, PChar(HandleHook[x].str1), 'H O O K 1', 0); Kill := True; CopyBackTempArray(); //HandleHook[x].car3.. bis car5 wieder auf Original Shortcut Kombination zurücksetzen Break; end; end .... .. . |
Re: Simulierten Hotkey per WMHotKey abfangen?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:53 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz