1

I am trying to implement global hotkeys (activated even without focus on the form) in WPF but using VB.NET. There are a lot of examples around using C# but I have tried for hours to convert these and have failed to get anything to work.

I used to have them working in WinForms using RegisterHotkey but there is no Wndproc anymore in WPF...

Basically I just want a hotkey such as Alt+A to run a Private Sub in my code behind.

If anyone could help with this it would be greatly appreciated.

Thanks, Wally

Wally Cloud
  • 81
  • 1
  • 4
  • Possible duplicate of http://stackoverflow.com/questions/2450373/set-global-hotkeys-using-c-sharp ? – Kelly Feb 02 '16 at 13:08

2 Answers2

2

Okay I have done it! Adding a global hotkey using WPF and VB.NET can be done by adding these references (Mainwindow.xmal.vb):

Imports System.Runtime.InteropServices
Imports System.Windows.Interop

Then adding the following to the Code behind:

<DllImport("User32.dll")> _
Private Shared Function RegisterHotKey(<[In]> hWnd As IntPtr, <[In]> id As Integer, <[In]> fsModifiers As UInteger, <[In]> vk As UInteger) As Boolean
End Function

<DllImport("User32.dll")> _
Private Shared Function UnregisterHotKey(<[In]> hWnd As IntPtr, <[In]> id As Integer) As Boolean
End Function

Private _source As HwndSource
Private Const HOTKEY_ID As Integer = 9000

Protected Overrides Sub OnSourceInitialized(e As EventArgs)
    MyBase.OnSourceInitialized(e)
    Dim helper = New WindowInteropHelper(Me)
    _source = HwndSource.FromHwnd(helper.Handle)
    _source.AddHook(AddressOf HwndHook)
    RegisterHotKey()
End Sub

Protected Overrides Sub OnClosed(e As EventArgs)
    _source.RemoveHook(AddressOf HwndHook)
    _source = Nothing
    UnregisterHotKey()
    MyBase.OnClosed(e)
End Sub

Private Sub RegisterHotKey()
    Dim helper = New WindowInteropHelper(Me)
    Const VK_F10 As UInteger = &H79
    Const MOD_CTRL As UInteger = &H2
    ' handle error
    If Not RegisterHotKey(helper.Handle, HOTKEY_ID, MOD_CTRL, VK_F10) Then
    End If
End Sub

Private Sub UnregisterHotKey()
    Dim helper = New WindowInteropHelper(Me)
    UnregisterHotKey(helper.Handle, HOTKEY_ID)
End Sub

Private Function HwndHook(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
    Const WM_HOTKEY As Integer = &H312
    Select Case msg
        Case WM_HOTKEY
            Select Case wParam.ToInt32()
                Case HOTKEY_ID
                    OnHotKeyPressed()
                    handled = True
                    Exit Select
            End Select
            Exit Select
    End Select
    Return IntPtr.Zero
End Function

Private Sub OnHotKeyPressed()
    MsgBox("Hello world!")
End Sub

This is for Ctrl+F10. It can be changed by modifying the following according to Keycodes from here and Key modifiers from here. Just replace the 0x with &H.

    Const VK_F10 As UInteger = &H79
    Const MOD_CTRL As UInteger = &H2

Hope this helps someone. Credit goes to "max" from which the code was converted: Global hotkeys in WPF working from every window

Community
  • 1
  • 1
Wally Cloud
  • 81
  • 1
  • 4
1

there is no Wndproc anymore in WPF...

Actually, there is ;)

For global hotkeys, you can use my NHotkey library, which has bindings for WPF and WinForms. The examples are in C#, but you can easily convert them to VB.NET.

Community
  • 1
  • 1
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • Hello, thanks so much for your reply. I have tried your NHotkey library previously but failed to get it to work, but it seems I gave up too soon. I have tried it just again now however I get the error "Error 5 Argument not specified for parameter 'sender' of 'Private Function OnIncrement(sender As Object, e As NHotkey.HotkeyEventArgs) As Object'." As well as for e..... – Wally Cloud Feb 02 '16 at 07:56
  • @WallyCloud, I don't understand what the error message means in this case, but it should be a `Sub`, not a `Function` – Thomas Levesque Feb 02 '16 at 10:14
  • Hey Thomas, thanks for your help. I had to have a function otherwise it would give the error "Does not return a value". I also tried with the keybinding xaml option "HotkeyManager.RegisterGlobalHotkey but it would only register when the form was in focus. Maybe an issue with how I set up my commands. But anyway :) I managed to find a solution. Thank you! – Wally Cloud Feb 02 '16 at 20:27
  • @WallyCloud, *I had to have a function otherwise it would give the error "Does not return a value"* : there must be something wrong in your code, because the delegate passed to AddOrReplace isn't supposed to return a value... – Thomas Levesque Feb 02 '16 at 20:53