title: How to trap keypress event in MSword using VSTO?
body: <p>I am new to VSTO VB.Net programming. and I am developing a word application level Addin and want to trap keypress event. I have tried various codes of hooking but none is working. I want to use application level hook using <code>WH_KEYBOARD</code> instead of <code>WH_KEYBOARD_LL</code>. The following code which I have tried traps just one key stroke after that it stops. Moreover I could not understand where to put trap the keystrokes. How would I use the following for handling key events.</p>
  
  <pre><code>Public Event KeyDown As KeyEventHandler
  
  Public Event KeyPress As KeyPressEventHandler
  
  Public Event KeyUp As KeyEventHandler
  </code></pre>
  
  <p>The code that I am using is </p>
  
  <pre><code>Imports System.ComponentModel
  
  Imports System.Windows.Forms
  
  Imports System.Runtime.InteropServices
  
  Public Class KeyBoardHook
      Inherits Component
      Dim PredictString As String
  
  #Region "     keyboardHook"
      Private Declare Auto Function LoadLibrary Lib "kernel32" (ByVal lpFileName As String) As IntPtr
      Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hhk As IntPtr) As Boolean
      Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
      ByVal lpfn As KeyboardProc, ByVal hmod As IntPtr, ByVal dwThreadId As Integer) As IntPtr
      Private Delegate Function KeyboardProc(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As IntPtr
      Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As IntPtr, ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As IntPtr
  
      Private Structure KBDLLHOOKSTRUCT
          Public vkCode As Integer
          Public scanCode As Integer
          Public flags As Integer
          Public time As Integer
          Public dwExtraInfo As Integer
      End Structure
  
      'Keyboard Constants
      Private Const HC_ACTION As Integer = 0
      Private Const WM_KEYDOWN As Integer = &amp;H100
      Private Const WM_KEYUP As Integer = &amp;H101
      Private Const WM_SYSKEYDOWN As Integer = &amp;H104
      Private Const WM_SYSKEYUP As Integer = &amp;H105
  
      Private Const WH_KEYBOARD As Integer = 2
      Public hKeyboardHook As IntPtr
  
      Public Event KeyDown As KeyEventHandler
      Public Event KeyPress As KeyPressEventHandler
      Public Event KeyUp As KeyEventHandler
  
      Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Integer
      Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Integer) As Integer
  
      Private Const VK_ALT As Integer = &amp;H12
      Private Const VK_CONTROL As Integer = &amp;H11
      Private Const VK_SHIFT As Integer = 16
  
      &lt;MarshalAs(UnmanagedType.FunctionPtr)&gt; Private callback As KeyboardProc
  
      Public Sub HookKeyboard()
          callback = New KeyboardProc(AddressOf KeyboardCallback)
          Dim hInstance As IntPtr = LoadLibrary("User32")
          hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, callback, hInstance, 0)
          CheckHooked()
      End Sub
  
      Private Function KeyboardCallback(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As IntPtr
          Dim xy As System.Drawing.Point = Cursor.Position()
          Try
              If (Code = HC_ACTION Or Code = 3) Then
                  Dim CapsLock As Boolean = GetKeyState(Keys.CapsLock) = 1
                  Dim shifting As Boolean = False
                  Dim modifiers As Keys
                  If GetAsyncKeyState(VK_CONTROL) &lt;&gt; 0 Then
                      modifiers = modifiers Or Keys.Control
                  End If
                  If GetAsyncKeyState(VK_SHIFT) &lt;&gt; 0 Then
                      modifiers = modifiers Or Keys.Shift
                      shifting = True
                  End If
                  If GetAsyncKeyState(VK_ALT) &lt;&gt; 0 Then
                      modifiers = modifiers Or Keys.Alt
                  End If
                  Static lastKeys As Keys
                  Select Case wParam
                      Case WM_KEYDOWN, WM_SYSKEYDOWN
                          RaiseEvent KeyDown(Me, New KeyEventArgs(DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers))
                          If lastKeys &lt;&gt; (DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers) Then
                              lastKeys = (DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers)
                              If CapsLock AndAlso shifting Then
                                  RaiseEvent KeyPress(Me, New KeyPressEventArgs(Char.ToLower(Chr(lParam.vkCode))))
                              ElseIf Not CapsLock AndAlso shifting Then
                                  RaiseEvent KeyPress(Me, New KeyPressEventArgs(Char.ToUpper(Chr(lParam.vkCode))))
                              ElseIf Not shifting Then
                                  If CapsLock Then
                                      RaiseEvent KeyPress(Me, New KeyPressEventArgs(Char.ToUpper(Chr(lParam.vkCode))))
                                  Else
                                      RaiseEvent KeyPress(Me, New KeyPressEventArgs(Char.ToLower(Chr(lParam.vkCode))))
                                  End If
                              End If
                          End If
                      Case WM_KEYUP, WM_SYSKEYUP
                          If CapsLock AndAlso shifting Then
                              RaiseEvent KeyUp(Me, New KeyEventArgs(DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers))
                          ElseIf Not CapsLock AndAlso shifting Then
                              RaiseEvent KeyUp(Me, New KeyEventArgs(DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers))
                          ElseIf Not shifting Then
                              If CapsLock Then
                                  RaiseEvent KeyUp(Me, New KeyEventArgs(DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers))
                              Else
                                  RaiseEvent KeyUp(Me, New KeyEventArgs(DirectCast(Asc(Chr(lParam.vkCode)), Keys) Or modifiers))
                              End If
                          End If
                          lastKeys = Nothing
                  End Select
              End If
  
              MsgBox("Keypressed is -&gt; " &amp; lParam.vkCode)
              Return CallNextHookEx(hKeyboardHook, Code, wParam, lParam)
          Catch ex As Exception
              MsgBox(ex.Message)
          End Try
      End Function
  
      Private Function keyboardHooked() As Boolean
          Return hKeyboardHook &lt;&gt; IntPtr.Zero
      End Function
  
      Public Sub UnhookKeyboard()
          If keyboardHooked() Then
              UnhookWindowsHookEx(hKeyboardHook)
          End If
      End Sub
  #End Region
      Private Sub CheckHooked()
          If keyboardHooked() Then
              MsgBox("Keyboard hooked")
          Else
              MsgBox("Keyboard hook failed: " &amp; Err.LastDllError)
          End If
      End Sub
  End Class
  </code></pre>