Systemweiten Hotkey registrieren (kein Tastatur Hook)

    • VB.NET

    Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von VB.neter0101.

      Hallo Mike,
      Erstmal danke für den Code hat mir sehr geholfen :D
      Aber: Ich nutze das ganze für GTA bzw möchte es dafür nutzen.
      Ich lasse das ganze über ne Case laufen wie im beispiel
      Drinne steht dann

      VB.NET-Quellcode

      1. TextBox1.Text = "Aktuelle Wanteds" SendKeys.Send("t") SendKeys.Send("/ow") SendKeys.Send("{Enter}")

      habe das ganze auf einem Windows xp Rechner installiert. Wenn ich dort die Befehle getestet habe (im Editor den Text anzeigen lassen ging alles). Aber auf Windows 7 führt er einige befehle nach drücken der richtigen taste immer wieder aus.
      Weißt du wodran das liegen kann
      Gruß Paule
      für ControlKeys musst du Key_NONE ersetzen, die Konstanten musst du wohl im Internet gucken oder z.B. hier:
      [VB.NET] Systemweiten Hotkey registrieren (kein Tastatur Hook)
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---
      Hi
      habe mal eine vereinfachende Bedienung dafür geschrieben, auch wenn der Code dafür komplizierter ist. Alles was der Code tut ist, RegisterHotKey und UnregisterHotKey zu kapseln und über IDisposable die HotKeys zu verwalten, statt über die id. Zusätzlich gibt's noch eine weitere Klasse, die die Bedienung aus dem Code heraus vereinfachen soll.
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Imports System.Runtime.InteropServices
      2. Imports System.ComponentModel
      3. Friend Class NativeMethods
      4. #Region "Modifiers"
      5. 'API-Deklarationen
      6. <DllImport("user32")> _
      7. Private Shared Function RegisterHotKey(ByVal handle As IntPtr, ByVal id As Integer, ByVal modifiers As ModifierKeys, ByVal vkey As Keys) As Boolean
      8. End Function
      9. <DllImport("user32")> _
      10. Private Shared Function UnregisterHotKey(ByVal handle As IntPtr, ByVal id As Integer) As Boolean
      11. End Function
      12. 'Wrappen die API-Aufrufe eleganter
      13. Public Shared Function RegisterHotkey(ByVal window As IWin32Window, ByVal keyData As Keys) As IDisposable
      14. Return RegisterHotkey(window, ModifierKeys.None, keyData)
      15. End Function
      16. Public Shared Function RegisterHotKey(ByVal window As IWin32Window, ByVal modifiers As ModifierKeys, ByVal keyData As Keys) As IDisposable
      17. Static idv As Integer = 0
      18. Dim cid As Integer = Threading.Interlocked.Increment(idv) - 1 'Threadsicher inkrementieren und den alten Wert als Hotkey-ID verwenden
      19. Dim handle As IntPtr = If(window Is Nothing, IntPtr.Zero, window.Handle)
      20. 'Bei Fehlschlag Fehler ausgeben
      21. If Not RegisterHotKey(handle, cid, modifiers Or MapKeyModifiers(keyData), keyData And Keys.KeyCode) Then
      22. ThrowLastWin32Error()
      23. End If
      24. 'Handle registrieren, das bei einem IDisposable.Dispose-Aufruf den Hotkey wieder freigibt
      25. Return New DelegateDisposable(Sub()
      26. If Not UnregisterHotKey(handle, cid) Then
      27. ThrowLastWin32Error()
      28. End If
      29. End Sub)
      30. End Function
      31. 'ModifierKeys in Keys abbilden und umgekehrt, Keys enthaelt nicht alle benoetigten Modifizierer
      32. Public Shared Function MapKeyModifiers(ByVal modifiers As Keys) As ModifierKeys
      33. Dim md As ModifierKeys = ModifierKeys.None
      34. If (modifiers And Keys.Alt) = Keys.Alt Then md = md Or ModifierKeys.Alt
      35. If (modifiers And Keys.Control) = Keys.Control Then md = md Or ModifierKeys.Control
      36. If (modifiers And Keys.Shift) = Keys.Shift Then md = md Or ModifierKeys.Shift
      37. Return md
      38. End Function
      39. Public Shared Function MapModifierKeys(ByVal modifiers As ModifierKeys) As Keys
      40. Dim md As Keys = Keys.None
      41. If (modifiers And ModifierKeys.Alt) = ModifierKeys.Alt Then md = md Or Keys.Alt
      42. If (modifiers And ModifierKeys.Control) = ModifierKeys.Control Then md = md Or Keys.Control
      43. If (modifiers And ModifierKeys.Shift) = ModifierKeys.Shift Then md = md Or Keys.Shift
      44. Return md
      45. End Function
      46. Private Shared Sub ThrowLastWin32Error()
      47. Throw New Win32Exception(Marshal.GetLastWin32Error())
      48. End Sub
      49. #End Region
      50. End Class
      51. 'Moegliche Hotkey-Modifizierer
      52. Public Enum ModifierKeys
      53. None = 0
      54. Alt = 1
      55. Control = 2
      56. Shift = 4
      57. Windows = 8
      58. NoRepeat = &H4000
      59. End Enum
      60. Public Class HotkeyHandler
      61. Implements IDisposable
      62. 'Tritt ein, sobald ein registrierter Hotkey aufgerufen wird
      63. Public Event HotkeyPressed As EventHandler(Of KeyEventArgs)
      64. 'ordnet Hotkeys ihrem Handle zu (wird zur Bereitstellung und Freigabe von RegisterHotKey benoetigt, sodass
      65. 'mehrfache Besetzungen zu einem einzigen Handle pro HotkeyHandler-Instanz gruppiert werden)
      66. Private _values As IDictionary(Of HotkeyDescription, HotkeyHandle)
      67. Private _window As IWin32Window 'Das Control, das die Informationen empfaengt oder Nothing, sofern direkt an die Nachrichtenschleife weitergeleitet werden soll
      68. Private _disposed As Boolean
      69. Private _count As Integer
      70. Private _filter As HotkeyFilter
      71. Public Sub New()
      72. Me.New(Nothing)
      73. End Sub
      74. Public Sub New(ByVal window As IWin32Window)
      75. _values = New Dictionary(Of HotkeyDescription, HotkeyHandle)()
      76. _window = window
      77. _filter = New HotkeyFilter(Me)
      78. End Sub
      79. Public Function RegisterHotkey(ByVal hotkey As Keys) As IDisposable
      80. Return RegisterHotkey(hotkey, ModifierKeys.None)
      81. End Function
      82. 'Registriert den angegebenen Hotkey mit den angegebenen Modifizierern
      83. Public Function RegisterHotkey(ByVal hotkey As Keys, ByVal modifiers As ModifierKeys) As IDisposable
      84. If _disposed Then Throw New ObjectDisposedException(Me.GetType().Name)
      85. Dim descr As New HotkeyDescription(hotkey And Keys.KeyCode, modifiers Or NativeMethods.MapKeyModifiers(hotkey))
      86. Dim handle As HotkeyHandle = Nothing
      87. If Not _values.TryGetValue(descr, handle) Then
      88. handle = New HotkeyHandle(NativeMethods.RegisterHotKey(_window, descr.Modifiers, descr.Keys))
      89. _values.Add(descr, handle)
      90. End If
      91. _filter.Enabled = True 'Nachrichtenfilter erst dann aktivieren, wenn Hotkeys verfuegbar sind
      92. _count += 1
      93. Return New DelegateDisposable(Sub()
      94. If Not handle.Release() Then _values.Remove(descr)
      95. _count -= 1
      96. If _count = 0 Then _filter.Enabled = False 'Nachrichtenfilter freigeben, wenn nicht mehr benoetigt
      97. End Sub)
      98. End Function
      99. 'Uebertraegt den Hotkey und fuehrt ihn aus
      100. Private Sub SendKey(ByVal description As HotkeyDescription)
      101. OnHotkeyPressed(New KeyEventArgs(NativeMethods.MapModifierKeys(description.Modifiers) Or description.Keys))
      102. End Sub
      103. 'Ruft das HotkeyPressed-Ereignis auf, sobald ein Hotkey gedrueckt wurde
      104. Protected Overridable Sub OnHotkeyPressed(ByVal e As KeyEventArgs)
      105. RaiseEvent HotkeyPressed(Me, e)
      106. End Sub
      107. Protected Overridable Sub Dispose(ByVal disposing As Boolean)
      108. If Not Me._disposed Then
      109. 'alle Handles freigeben
      110. For Each k As HotkeyHandle In _values.Values
      111. k.Delete()
      112. Next
      113. _filter.Dispose()
      114. End If
      115. Me._disposed = True
      116. End Sub
      117. 'Bei fehlendem Dispose-Aufruf trotzdem freigeben
      118. Protected Overrides Sub Finalize()
      119. Dispose(False)
      120. MyBase.Finalize()
      121. End Sub
      122. Public Sub Dispose() Implements IDisposable.Dispose
      123. Dispose(True)
      124. GC.SuppressFinalize(Me)
      125. End Sub
      126. 'Beschreibung der Hotkeys und Modifizierern
      127. Private Structure HotkeyDescription
      128. Private _keys As Keys
      129. Private _modifiers As ModifierKeys
      130. Public Sub New(ByVal keys As Keys, ByVal modifiers As ModifierKeys)
      131. _keys = keys
      132. _modifiers = modifiers
      133. End Sub
      134. Public ReadOnly Property Keys As Keys
      135. Get
      136. Return _keys
      137. End Get
      138. End Property
      139. Public ReadOnly Property Modifiers As ModifierKeys
      140. Get
      141. Return _modifiers
      142. End Get
      143. End Property
      144. Public Overrides Function GetHashCode() As Integer
      145. Return _keys.GetHashCode() Xor _modifiers.GetHashCode()
      146. End Function
      147. Public Overrides Function Equals(ByVal obj As Object) As Boolean
      148. Return obj IsNot Nothing AndAlso TypeOf obj Is HotkeyDescription AndAlso Equals(DirectCast(obj, HotkeyDescription))
      149. End Function
      150. Public Overloads Function Equals(ByVal value As HotkeyDescription) As Boolean
      151. Return value.Modifiers = Modifiers AndAlso value.Keys = Keys
      152. End Function
      153. End Structure
      154. Private NotInheritable Class HotkeyHandle
      155. Private _count As Integer
      156. Private _handle As IDisposable
      157. Public Sub New(ByVal handle As IDisposable)
      158. _handle = handle
      159. End Sub
      160. Public Sub Allocate() 'Hotkey registrieren
      161. System.Threading.Interlocked.Increment(_count)
      162. End Sub
      163. 'Hotkey wieder freigeben und zurueckgeben, ob das Freigeben dazu gefuehrt hat, dass der Hotkey geloescht wird
      164. Public Function Release() As Boolean
      165. Dim cv As Integer = System.Threading.Interlocked.Decrement(_count)
      166. If cv < 0 Then
      167. _count = 0
      168. Throw New InvalidOperationException("Cannot release unallocated hotkey handle.")
      169. ElseIf cv = 0 Then
      170. Delete()
      171. Return False
      172. End If
      173. Return True
      174. End Function
      175. 'Hotkey vollstaendig freigeben (entweder, da alle Anforderungen wieder freigegeben wurden oder, weil das Handle geschlossen wurde)
      176. Public Sub Delete()
      177. _handle.Dispose()
      178. End Sub
      179. End Class
      180. 'hoert die Nachrichtenschleife ab und informiert den HotkeyHandler ueber auftretende WM_HOTKEY-Ereignisse
      181. Private NotInheritable Class HotkeyFilter
      182. Implements IMessageFilter
      183. Implements IDisposable
      184. Private Const WM_HOTKEY As Integer = &H312
      185. Private _disposed, _enabled As Boolean
      186. Private _handler As HotkeyHandler
      187. Public Sub New(ByVal handler As HotkeyHandler)
      188. _handler = handler
      189. End Sub
      190. Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
      191. If m.Msg = WM_HOTKEY AndAlso m.HWnd = If(_handler._window Is Nothing, IntPtr.Zero, _handler._window.Handle) Then
      192. Dim cv As Integer = m.LParam.ToInt32()
      193. _handler.SendKey(New HotkeyDescription(CType((cv >> 16) And &HFFFF, Keys), CType(cv And &HFFFF, ModifierKeys)))
      194. End If
      195. Return False
      196. End Function
      197. Public Property Enabled As Boolean
      198. Get
      199. Return _enabled
      200. End Get
      201. Set(ByVal value As Boolean)
      202. If _disposed Then Throw New ObjectDisposedException(Me.GetType().Name)
      203. If _enabled <> value Then
      204. _enabled = value
      205. If value Then
      206. Application.AddMessageFilter(Me)
      207. Else
      208. Application.RemoveMessageFilter(Me)
      209. End If
      210. End If
      211. End Set
      212. End Property
      213. Public Sub Dispose() Implements IDisposable.Dispose
      214. If Not _disposed Then
      215. Enabled = False
      216. _disposed = True
      217. End If
      218. End Sub
      219. End Class
      220. End Class
      221. 'eine einfache IDisposable-Implementierung, die bei Dispose den angegebenen Delegaten aufruft. Ungeeignet fuer Finalisierung
      222. Friend Class DelegateDisposable
      223. Implements IDisposable
      224. Private _disposed As Boolean
      225. Private _handler As Action
      226. Public Sub New(ByVal handler As Action)
      227. _handler = handler
      228. End Sub
      229. Public Sub Dispose() Implements IDisposable.Dispose
      230. If Not _disposed Then
      231. _disposed = True
      232. _handler()
      233. _handler = Nothing
      234. End If
      235. End Sub
      236. End Class

      Der HotKeyHandler vereinfacht entsprechend die Bedienung:

      VB.NET-Quellcode

      1. Private WithEvents _hotkeyHandler As HotkeyHandler
      2. Private _stepCounter As Integer
      3. Private Sub Form_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
      4. _hotkeyHandler.Dispose() 'wieder freigeben, sobald die Form geschlossen wird (sollte auch durch Finalisierung freigegeben werden)
      5. End Sub
      6. Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      7. _hotkeyHandler = New HotkeyHandler(Me)
      8. _hotkeyHandler.RegisterHotkey(Keys.Control Or Keys.W) 'Hotkey Strg+W registrieren
      9. _hotkeyHandler.RegisterHotkey(Keys.Control Or Keys.S) 'Hotkey Strg+S registrieren
      10. End Sub
      11. Private Sub _hotkeyHandler_HotkeyPressed(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles _hotkeyHandler.HotkeyPressed
      12. 'irgendwie auf Strg+W und Strg+S reagieren, Verwendung hier nat. unglaublich sinnvoll
      13. If e.KeyData = (Keys.Control Or Keys.W) Then
      14. _stepCounter += 1
      15. ElseIf e.KeyData = (Keys.Control Or Keys.S) Then
      16. _stepCounter -= 1
      17. End If
      18. _stepCounterDisplay.Text = _stepCounter.ToString() '_stepCounterDisplay waere ein Label
      19. End Sub


      Gruß
      ~blaze~
      Hallo, hier das ganze mal für WPF:

      VB.NET-Quellcode

      1. Imports System.Windows.Interop
      2. Imports System.Windows.Forms
      3. Imports System.Runtime.InteropServices
      4. Class MainWindow
      5. <DllImport("User32.dll")> _
      6. Private Shared Function RegisterHotKey(<[In]> hWnd As IntPtr, <[In]> id As Integer, <[In]> fsModifiers As UInteger, <[In]> vk As UInteger) As Boolean
      7. End Function
      8. <DllImport("User32.dll")> _
      9. Private Shared Function UnregisterHotKey(<[In]> hWnd As IntPtr, <[In]> id As Integer) As Boolean
      10. End Function
      11. Private _source As HwndSource
      12. Private Const HOTKEY_ID As Integer = 9000
      13. Private Const HOTKEY_2ID As Integer = 9001
      14. Protected Overrides Sub OnSourceInitialized(e As EventArgs)
      15. MyBase.OnSourceInitialized(e)
      16. Dim helper = New WindowInteropHelper(Me)
      17. _source = HwndSource.FromHwnd(helper.Handle)
      18. _source.AddHook(AddressOf HwndHook)
      19. RegisterHotKey()
      20. End Sub
      21. Protected Overrides Sub OnClosed(e As EventArgs)
      22. _source.RemoveHook(AddressOf HwndHook)
      23. _source = Nothing
      24. UnregisterHotKey()
      25. MyBase.OnClosed(e)
      26. End Sub
      27. Private Sub RegisterHotKey()
      28. Dim helper = New WindowInteropHelper(Me)
      29. Const VK_F10 As UInteger = &H79
      30. Const VK_BACK As UInteger = 8
      31. If Not RegisterHotKey(helper.Handle, HOTKEY_ID, Nothing, VK_F10) Then
      32. 'Fehler
      33. End If
      34. If Not RegisterHotKey(helper.Handle, HOTKEY_2ID, Nothing, VK_BACK) Then
      35. 'Fehler
      36. End If
      37. End Sub
      38. Private Sub UnregisterHotKey()
      39. Dim helper = New WindowInteropHelper(Me)
      40. UnregisterHotKey(helper.Handle, HOTKEY_ID)
      41. End Sub
      42. Private Function HwndHook(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
      43. Const WM_HOTKEY As Integer = &H312
      44. Select Case msg
      45. Case WM_HOTKEY
      46. Select Case wParam.ToInt32()
      47. Case HOTKEY_ID
      48. OnHotKeyPressed()
      49. handled = True
      50. Case HOTKEY_2ID
      51. OnHotKey2Pressed()
      52. handled = True
      53. End Select
      54. Exit Select
      55. End Select
      56. Return IntPtr.Zero
      57. End Function
      58. Private Sub OnHotKey2Pressed()
      59. MessageBox.Show("Back wurde gedrückt")
      60. End Sub
      61. Private Sub OnHotKeyPressed()
      62. MessageBox.Show("F10 wurde gedrückt")
      63. End Sub
      64. End Class


      Keine Ahnung, ob das einfach geht, aber so geht es.
      Hier findet ihr alle Keys: msdn.microsoft.com/en-us/library/ms927178.aspx
      Mfg
      Vincent

      Hi,

      ich würde gerne die Taste "Druck|S-Abf" für eine Screenshot / Support-Funktion,
      in meiner Anwendung verwenden.

      Leider bekomme ich diese Taste nicht in Deinen Code eingebunden. :whistling:

      VB.NET-Quellcode

      1. RegisterHotKey(Me.Handle, 3, Key_NONE, Keys.Print)
      2. RegisterHotKey(Me.Handle, 4, Key_NONE, Keys.PrintScreen)


      Kann mir hier jemand helfen?


      Gruß

      Marcel
      Wie kann ich diese Systemweiten Änderungen auch wieder rückgängig machen?? :)
      Ich habe den Code mal in C# überführt, vielleicht ist das hilfreich für den ein oder anderen:

      C#-Quellcode

      1. using System;
      2. using System.Collections.Generic;
      3. using System.ComponentModel;
      4. using System.Data;
      5. using System.Drawing;
      6. using System.Linq;
      7. using System.Runtime.InteropServices;
      8. using System.Text;
      9. using System.Threading.Tasks;
      10. using System.Windows.Forms;
      11. namespace KeysAbfangenVonForm
      12. {
      13. public partial class Form1 : Form
      14. {
      15. [DllImport("user32.dll")]
      16. private static extern int RegisterHotKey(IntPtr hWnd, int id, int fsModifier, int vk);
      17. [DllImport("user32.dll")]
      18. private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
      19. private const int Key_NONE = 0x0000;
      20. private const int WM_HOTKEY = 0x312;
      21. protected override void WndProc(ref Message m)
      22. {
      23. // die messages auswerten
      24. if (m.Msg == WM_HOTKEY)
      25. {
      26. // hier wird entschieden welcher hotkey es war
      27. // einfach die übergebene id auswerten
      28. switch (m.WParam.ToInt32())
      29. {
      30. case 1:
      31. {
      32. MessageBox.Show("Sie haben die Tab-Taste gedrückt!");
      33. break;
      34. }
      35. case 2:
      36. {
      37. MessageBox.Show("Sie haben die 1 gedrückt!");
      38. break;
      39. }
      40. }
      41. }
      42. base.WndProc(ref m);
      43. }
      44. public Form1()
      45. {
      46. InitializeComponent();
      47. }
      48. private void Form1_Load(object sender, EventArgs e)
      49. {
      50. // die tab taste abfangen
      51. RegisterHotKey(this.Handle, 1, Key_NONE, 0x9); // Tab Code (HEX)
      52. RegisterHotKey(this.Handle, 2, Key_NONE, 0x31); // D1 (Taste 1) Code (HEX)
      53. // Wichtige Ressource:
      54. // https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.keys?view=netframework-4.8
      55. }
      56. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      57. {
      58. UnregisterHotKey(this.Handle, 1);
      59. UnregisterHotKey(this.Handle, 2);
      60. }
      61. }
      62. }

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB.neter0101“ ()