| 
| Autor | Beitrag |  
| dYnAm1c 
          Beiträge: 16
 
 
 
 
 | 
Verfasst: So 03.07.11 02:59 
 
Hallo,
 ich programmiere im moment ein Programm mit Systemweiten Hotkeys für ein Spiel.
 Da das Spiel anscheinend Direct Input verwendet und die Hotkeys deswegen nicht Ingame funktionieren,
 musste ich statt registerHotKey die Funktion "SetWindowsHookEx" und "WH_KEYBOARD_LL"
 nehmen und einen Low Level Hook programmieren.
 Im moment sieht das ganze so aus:
 												| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
 52:
 53:
 54:
 55:
 56:
 57:
 58:
 
 | typetagKBDLLHOOKSTRUCT = record
 vkCode: DWORD;
 scanCode: DWORD;
 flags: DWORD;
 time: DWORD;
 dwExtraInfo: DWORD;
 end;
 TKbdDLLHookStruct = tagKBDLLHOOKSTRUCT;
 PKbdDLLHookStruct = ^TKbdDLLHookStruct;
 
 var
 Form1: TForm1;
 HookHandle: Cardinal = 0;
 WindowHandle: Cardinal = 0;
 
 
 function InstallHook(Hwnd: Cardinal): Boolean; stdcall;
 begin
 Result := False;
 if HookHandle = 0 then begin
 HookHandle := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, hInstance, 0);
 WindowHandle := Hwnd;
 Result := HookHandle <> 0;
 end;
 end;
 
 
 function LowLevelKeyboardProc(nCode: Integer; wParam: wParam; lParam: lParam): LRESULT; stdcall;
 begin
 if (Form1.Visible = True) AND (Form3.Visible = False) then begin
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD7) then
 Form1.Button1.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD8) then
 Form1.Button2.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD4) then
 Form1.Button3.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD5) then
 Form1.Button4.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD1) then
 Form1.Button5.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD2) then
 Form1.Button6.Click;
 Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
 end;
 if (Form1.Visible = False) AND (Form3.Visible = True) then begin
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD7) then
 Form3.Button1.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD9) then
 Form3.Button2.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD5) then
 Form3.Button3.Click;
 if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = VK_NUMPAD2) then
 Form3.Button4.Click;
 Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
 
 end;
 end;
 |  Wie man sieht benutze ich für die Hotkeys im moment die Nummernfeld Tasten.
 Allerdings würde ich vom User die Tasten gerne selber festlegen wollen, allerdings weiß
 ich nicht wie ich da vorgehen soll, wär also nett wenn jemand was wüsste    MfG |  |  |  
| Boldar 
          Beiträge: 1555
 Erhaltene Danke: 70
 
 Win7 Enterprise 64bit, Win XP SP2
 Turbo Delphi
 
 | 
Verfasst: So 03.07.11 08:11 
 
Nimm doch statt den keycodes einfach eine variable. Es gibt da auch so eine Komponente für, wo man hotkeys eingeben kann als User.
 Aber hier würde das dann zunächst so aussehen:
 		                       Delphi-Quelltext 
 									| 1:2:
 
 | if (nCode >= 0) and (wParam = WM_KEYDOWN) and (PKbdDLLHookStruct(lParam)^.vkCode = Hotkey1) thenForm1.Button1.Click;
 |  mit hotkey1 als globaler Variable.
 Aber Systemweit wird das so eh nicht klappen. Die Callback-Funktion Lowlevelkeyboardproc muss aus einer dll kommen, und du brauchst IPC. Lies dazu dieses Tutorial. Deine Callback liegt ja in deiner Exe, der Hook wird aber in den anderen Prozessen ausgeführt. Dort ist deine Funktion aber garnicht vorhanden.
 mfg Boldar |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: So 03.07.11 09:11 
 
	  |  Boldar hat folgendes geschrieben  : |  	  | Aber Systemweit wird das so eh nicht klappen. Die Callback-Funktion Lowlevelkeyboardproc muss aus einer dll kommen, und du brauchst IPC. | 
 Das stimmt nicht... Dass sich dieser Mythos immer noch hartnäckig hält... Probiere es einfach mal aus...    Andere Hooktypen (wie die Nicht-Lowlevel-Verson) müssen in der Tat in einer DLL untergebracht werden. Denn diese werden z.B. im Fall von WH_KEYBOARD und WH_MOUSE vom Fenstermanager aufgerufen, da hier erst die Messages an die Zielanwendung abgefangen werden. Daher braucht man eine DLL-Funktion, da es ein anderer Prozess ist.
 Die Lowlevel-Hooks für Maus und Tastatur hingegen werden vom System selbst quasi auf Treiberebene verwaltet. Deshalb ist hier keine DLL nötig. |  |  |  
| dYnAm1c  
          Beiträge: 16
 
 
 
 
 | 
Verfasst: So 03.07.11 10:48 
 
Das mit der Komponente für HotKeys zu machen habe ich mir auch schon überlegt, nur mit welchem
Variablentypen soll ich die denn abspeichern?
 |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: So 03.07.11 11:11 
 
Das ist natürlich eine ganz schwierige Frage, wenn du in dem Record ja siehst, dass vkCode als DWORD deklariert ist... |  |  |  
| dYnAm1c  
          Beiträge: 16
 
 
 
 
 | 
Verfasst: So 03.07.11 12:29 
 
Ok das klappt schonmal. Nurnoch eine kleine Frage, kann ich in die HotKey Komponente noch weitere HotKeys eintragen?
Im moment sind da ja nur die vorgegebenen drin. Kobinationen aus CTRL + 1 sind da z.B. gar nicht drin und Numpad Tasten ebenfalls nicht.
 |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: So 03.07.11 13:07 
 
Du kannst dir auch ein Edit nehmen und das selbst implementieren was du brauchst. |  |  |  
| dYnAm1c  
          Beiträge: 16
 
 
 
 
 | 
Verfasst: So 03.07.11 13:16 
 
Also kann ich bei der HotKey Komponente keine weiteren Einträge hinzufügen?
 Und wenn das nicht geht könnte ich statt Edit aber auch einfach eine ComboBox nehmen?
 Ist ja praktisch das gleiche wie Edit nur das man schon vorgegebene Auswahlen kann.
Edit:  Also ich hab mal ein bisschen rumprobiert und erstmal ist das dabei rausgekommen:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 
 | private
 const
 VK_1 = $31;
 VK_CONTROL = $11;
 
 var
 Form2: TForm2;
 HotKeyNR1: DWORD;
 
 procedure TForm2.Button1Click(Sender: TObject);
 begin
 
 case ComboBox1.ItemIndex of
 0: HotKeyNR1 := VK_1;
 
 end;
 |  Das ganze funktioniert auch, allerdings wollte ich ja auch HotKeys welche sich z.B. aus zwei Tasten zusammensetzten. Ist das in einem Hook überhaupt möglich? Meine Variante die ich probiert hat klappt auf jedenfall nicht:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 
 | procedure TForm2.Button1Click(Sender: TObject);begin
 
 case ComboBox1.ItemIndex of
 0: HotKeyNR1 := VK_CONTROL + VK_1;
 
 end;
 |  |  |  |  
| dYnAm1c  
          Beiträge: 16
 
 
 
 
 | 
Verfasst: Mo 04.07.11 20:29 
 |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: Mo 04.07.11 22:24 
 
Du kannst nicht zwei Tasten exakt gleichzeitig herunterdrücken. Es kommt immer einer der Tastendrücke zuerst an...
 Wenn also Z und X als Tastenkombination gedrückt wird, bekommst du zuerst WM_KEYDOWN (das steht in wParam drin, siehe Doku) für Z, dann WM_KEYDOWN für X, dann je einmal WM_KEYUP für die beiden Tasten...
 |  |  |  
| dYnAm1c  
          Beiträge: 16
 
 
 
 
 | 
Verfasst: Di 05.07.11 00:49 
 
Und wie genau kann ich das dann anders umsetzen? |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: Di 05.07.11 09:35 
 
Wie meinst du das? Du bekommst die Tastenaktionen doch alle.    Du musst dir doch nur speichern, dass die erste herunter gedrückt wurde. Und wenn die zweite vor dem Loslassen der ersten auch gedrückt wurde, hast du die Kombination. |  |  |  |