Home » WPFRSS

Monitor Keys

Hey guys I'm building an application where I need my form to pop up when ctrl+ctrl or some other shortcut is pressed. I need this to happen no matter what window has focus.
Similar to that Google desktop search thing.. which comes preinstalled on Ubuntu.

Soooo do I need to create a service or..?
Could y'all just point me in the right direction? I don't know how to create this type of service.. or any type for that matter.

Dylan
 

4 Answers Found

 

Answer 1

You could google  for keyboard hooks or alternatively try something like this:

Public Class Form1
    Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Integer
    Dim WithEvents Tmr As New Timer
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Tmr.Interval = 100
        Tmr.Start()
    End Sub
    Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Tmr.Tick
        Tmr.Stop()
        If CBool(GetAsyncKeyState(Keys.ControlKey)) And CBool(GetAsyncKeyState(Keys.E)) Then
            MsgBox("Ctrl - E", MsgBoxStyle.SystemModal)
        End If
        Tmr.Start()
    End Sub
End Class
 

Answer 2

Hi Dylan,

Welcome to VB.NET forums!

You also can have a look at keyboard hook in this scenario.

A hook is a point  in the system message-handling mechanism where an application  can install a subroutine to monitor  the message traffic in the system. This is where certain types of messages will be processed before they reach the target window  procedure.   For a detailed introduction on hooks, please refer to
http://msdn.microsoft.com/en-us/library/ms632589(VS.85).aspx

To set a Windows hook, we call the Windows API SetWindowsHookEx from the user32.dll.   This function installs an application-defined hook procedure in the system hook chain associated with the certain hook type.   We use the Windows API CallNextHookEx from the user32.dll to pass the hook information to the next hook procedure in the current hook chain. The Windows API UnhookWindowsHookEx is used to remove a hook procedure installed in a hook chain by the SetWindowsHookEx function.

In order to set a low level mouse and keyboard hook in VB.NET, we P/Invoke Windows API SetWindowsHookEx, CallNextHookEx, UnhookWindowsHookEx, and GetModuleHandle. 

The first parameter of SetWindowsHookEx specifies the type  of hook procedure to be installed.  Here we use WH_KEYBOARD_LL or WH_MOUSE_LL .  
The second parameter is the pointer to the hook procedure. In C# we pass the delegate of the hook callback function to this parameter.  

The third parameter is the handle of the module containing the hook procedure.  Therefore, we call the GetModuleHandle to retrieve the current module handle of the C# hook application.

The fourth parameter specifies the identifier of the thread with which the hook procedure is to be associated.  If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop  as the calling thread.

To conclude the hook procedure, we use CallNextHookEx function to pass the hook information to the next hook procedure in the current hook chain.  

When we want to stop the low level mouse or keyboard hook, we can use the UnhookWindowsHookEx function to remove the hook procedure installed. The parameter is the hook ID we get from the SetWindowsHookEx function.

Take a look at following code snippet. I mainly refer to this article . You can also read following articles for your reference.

How to set a Windows hook in Visual C# .NET
http://support.microsoft.com/kb/318804

Windows Hooks in the .NET Framework
http://msdn.microsoft.com/en-us/magazine/cc188966.aspx

Processing Global Mouse and Keyboard Hooks in C#
http://www.codeproject.com/KB/cs/globalhook.aspx

Global System Hooks in .NET
http://www.codeproject.com/KB/system/globalsystemhook.aspx

Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Public Class Form1
    'Dim mc As MyHook = New MyHook
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Keyboard.HookKeyboard(Me)
    End Sub
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Keyboard.UnhookKeyboard()
    End Sub
End Class
Module Keyboard
    <DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
    Public Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
    End Function
    Public Declare Function UnhookWindowsHookEx Lib "user32" _
      (ByVal hHook As Integer) As Integer
    Public Declare Function SetWindowsHookEx Lib "user32" _
      Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
      ByVal lpfn As KeyboardHookDelegate, ByVal hmod As IntPtr, _
      ByVal dwThreadId As Integer) As Integer
    Private Declare Function GetAsyncKeyState Lib "user32" _
      (ByVal vKey As Integer) As Integer
    Private Declare Function CallNextHookEx Lib "user32" _
      (ByVal hHook As Integer, _
      ByVal nCode As Integer, _
      ByVal wParam As Integer, _
      ByVal lParam As KBDLLHOOKSTRUCT) As Integer
    Public Structure KBDLLHOOKSTRUCT
        Public vkCode As Integer
        Public scanCode As Integer
        Public flags As Integer
        Public time As Integer
        Public dwExtraInfo As Integer
    End Structure
    ' Low-Level Keyboard Constants
    Private Const HC_ACTION As Integer = 0
    Private Const LLKHF_EXTENDED As Integer = &H1
    Private Const LLKHF_INJECTED As Integer = &H10
    Private Const LLKHF_ALTDOWN As Integer = &H20
    Private Const LLKHF_UP As Integer = &H80
    ' Virtual Keys
    Public Const VK_TAB As Integer = &H9
    Public Const VK_CONTROL As Integer = &H11
    Public Const VK_ESCAPE As Integer = &H1B
    Public Const VK_DELETE As Integer = &H2E
    Private Const WH_KEYBOARD_LL As Integer = 13
    Public KeyboardHandle As Integer
    ' Implement this function to block as many
    ' key combinations as you'd like
    Public Function IsHooked( _
      ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
        Debug.WriteLine("Hookstruct.vkCode: " & Hookstruct.vkCode)
        Debug.WriteLine(Hookstruct.vkCode = VK_ESCAPE)
        Debug.WriteLine(Hookstruct.vkCode = VK_TAB)
        'MessageBox.Show(Hookstruct.vkCode.ToString)
        If (Hookstruct.vkCode = VK_ESCAPE) And _
          CBool(GetAsyncKeyState(VK_CONTROL) _
          And &H8000) Then
            Call HookedState("Ctrl + Esc blocked")
            Return True
        End If
        If (Hookstruct.vkCode = VK_TAB) And _
          CBool(Hookstruct.flags And _
          LLKHF_ALTDOWN) Then
            Call HookedState("Alt + Tab blockd")
            Return True
        End If
        If (Hookstruct.vkCode = VK_ESCAPE) And _
          CBool(Hookstruct.flags And _
            LLKHF_ALTDOWN) Then
            Call HookedState("Alt + Escape blocked")
            Return True
        End If
        '' disable PrintScreen here
        If (Hookstruct.vkCode = 44) Then
            Call HookedState("Print blocked")
            Return True
        End If
        Return False
    End Function
    Private Sub HookedState(ByVal Text As String)
        Debug.WriteLine(Text)
    End Sub
    Public Function KeyboardCallback(ByVal Code As Integer, _
      ByVal wParam As Integer, _
      ByRef lParam As KBDLLHOOKSTRUCT) As Integer
        If (Code = HC_ACTION) Then
            Debug.WriteLine("Calling IsHooked")
            If (IsHooked(lParam)) Then
                Return 1
            End If
        End If
        Return CallNextHookEx(KeyboardHandle, _
          Code, wParam, lParam)
    End Function
    Public Delegate Function KeyboardHookDelegate( _
      ByVal Code As Integer, _
      ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) _
                   As Integer
    <MarshalAs(UnmanagedType.FunctionPtr)> _
    Private callback As KeyboardHookDelegate
    Public Sub HookKeyboard(ByRef f As Form)
        callback = New KeyboardHookDelegate(AddressOf KeyboardCallback)
        KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, callback, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0)
        MessageBox.Show(KeyboardHandle.ToString)
        Call CheckHooked()
    End Sub
    Public Sub CheckHooked()
        If (Hooked()) Then
            Debug.WriteLine("Keyboard hooked")
        Else
            Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
        End If
    End Sub
    Private Function Hooked() As Boolean
        Hooked = KeyboardHandle <> 0
    End Function
    Public Sub UnhookKeyboard()
        If (Hooked()) Then
            Call UnhookWindowsHookEx(KeyboardHandle)
        End If
    End Sub
End Module


If you have any further issues, feel free to tell us.

Best regards,
Riquel

Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
 

Answer 3

Riquel,

I was looking to this code that you post to create  a hook.

I have 2 comments:

1) In your function 'IsHooked', What you are saying that you are desabling, is in fact what you are enabling to be processed by the application  that has the hook.

2) in your function KeyboardCallback, you are returning the CallNextHookEx only if the application does not process the hooked key ( this may be what is expected in this case ) but for the futur reader of this thread, if you want the key to be forwarded to the application that has the focus, or to any other application that may have a hook on this key, you need to CallNextHookEx for this.

 

Answer 4

Problem:

 Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam)
>>
>> PInvokeStackImbalance was detected
>> Message: A call to PInvoke function
>> 'Utility!Utility.LowLevelKBHook::CallNextHookEx' has unbalanced the
>> stack. This is likely because the managed PInvoke signature does not
>> match the unmanaged target signature. Check that the calling
>> convention and parameters of the PInvoke signature match the target
>> unmanaged signature.

Solution:

Change ByVal to ByRef => 'ByRef lParam As KBDLLHOOKSTRUCT'.

 
 
Search for  Monitor Keys
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter