Capturing Soft Keys Events in Windows Mobile 6
During the course of a work day I google coding questions or examples at least ten times. The software engineering community is strong and I’ve always gotten the answer or at the very least been lead in the right direction.
It’s not my job to know everything about coding. It’s my job to solve the problem so if I find a solution on the web then I use it.
I recently encountered an issue with capturing soft key events from a Windows Mobile device. I ran across several projects that either didn’t work or the solution was suspect. After a few days of reading and testing applications I created a tailored solution that works for me.
Since I was unable to find an accurate solution to my specific problem I am publishing the finished class. The majority of the code came from Paul Kimmel and this article at developer.com.
http://www.developer.com/net/vb/article.php/10926_2193301_3
His solution is for standard windows and has a few issues. I converted his class to work with Windows Mobile 6 and fixed the bugs and errors that were presented when running the code in the Compact Framework.
I want to give a little something back to the community which I rely on so heavily. Feel free to contact me with any questions by leaving a comment along with your contact information.
The best way to get the code is to copy from the first header down. Paste it in Word so it formats it then cut and paste the code into an empty class in your project.
That is all.
-Jim
---------------- CODE ----------------
'***********************************************************************
'* Class: cKeyBoardHook
'* Description:
'* Encapsulates the keyboard hook functions.
'***********************************************************************
Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Public Class cKeyboardHook
' Passes on the key to be processed by the form.
Public Event ProcessKey(ByVal pKey As Keys)
#Region "P/Invoke Declarations"
<dllimport("coredll.dll", SetLastError:=True)> _
Private Shared Function UnhookWindowsHookEx(ByVal hHook As Integer) as Integer
End Function
<dllimport("coredll.dll")> _
Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, _
ByVal lpfn As KeyboardHookDelegate, _
ByVal hmod As Integer, _
ByVal dwThreadId As Integer) As Integer
End Function
<dllimport("coredll.dll")> _
Private Shared Function GetAsyncKeyState(ByVal vKey As Integer) As Int16
End Function
<dllimport("coredll.dll")> _
Private Shared Function CallNextHookEx(ByVal hHook As Integer, _
ByVal nCode As Integer, _
ByVal wParam As Integer, _
ByVal lParam As KBDLLHOOKSTRUCT) As Integer
End Function
<dllimport("coredll.dll")> _
Private Shared Function GetModuleHandle(ByVal moduleName As String) As Integer
End Function
#End Region
#Region "Structures/Constants"
' Keyboard structure
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 WM_KEYDOWN As Integer = &H100
Private Const WM_KEYUP As Integer = &H101
Private Const WM_SYSKEYDOWN As Integer = &H104
Private Const WM_SYSKEYUP As Integer = &H105
' Virtual Keys
Private Const VK_TAB As Integer = &H9
Private Const VK_CONTROL As Integer = &H11
Private Const VK_ESCAPE As Integer = &H1B
Private Const VK_DELETE As Integer = &H2E
Private Const VK_F1 As Integer = &H70
Private Const VK_F2 As Integer = &H71
Private Const VK_LWIN As Integer = &H5B
Private Const VK_RWIN As Integer = &H5C
Private Const VK_APPS As Integer = &H5D
Private Const VK_OEMC5 As Integer = &HC5
' Common mistake to make this value 13...
Private Const WH_KEYBOARD_LL As Integer = 20
#End Region
#Region "Variables"
Private KeyboardHandle As Integer
#End Region
#Region "Delegates"
Private Delegate Function KeyboardHookDelegate(ByVal Code As Integer, _
ByVal wParam As Integer, _
ByRef lParam As KBDLLHOOKSTRUCT) As Integer
Private callBack As KeyboardHookDelegate
#End Region
#Region "Keyboard Hook Functions"
'********************************************************************************
'* Procedure: HookKeyboard
'* Description:
'* Hooks the keyboard.
'********************************************************************************
Public Function HookKeyboard() As Boolean
Dim iHwnd As Integer = 0
Try
'Assign a function for the callback.
callBack = New KeyboardHookDelegate(AddressOf KeyboardCallback)
'Create the hook, return the handle to the keyboard
KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, _
callBack, _
GetModuleHandle(Nothing), 0)
'If the handle is zero we're in trouble.
If KeyboardHandle = 0 Then
DebugMessage("ERROR - hook unsuccessful.")
Return False
Else
'Double check the hook.
Return CheckHooked()
End If
Catch ex As Exception
MessageBox.Show(String.Format("cKeyBoardHook::HookKeyboard - {0}", ex.Message))
End Try
End Function
'********************************************************************************
'* Procedure: UnhookKeyboard
'* Description:
'* Unhooks the keyboard.
'********************************************************************************
Public Sub UnhookKeyboard()
If (Hooked()) Then
DebugMessage("Keyboard unhooked")
Call UnhookWindowsHookEx(KeyboardHandle)
End If
End Sub
'********************************************************************************
'* Procedure: CheckHooked
'* Description:
'* Checks to see if we have a hook to the keyboard.
'********************************************************************************
Public Function CheckHooked() As Boolean
If (Hooked()) Then
Return True
DebugMessage("Keyboard hooked")
Else
Return False
DebugMessage("Keyboard hook failed: " & Err.LastDllError)
End If
End Function
'********************************************************************************
'* Procedure: KeyboardCallback
'* Description:
'* Delegate function for the keyboard hook to call.
'********************************************************************************
Private Function KeyboardCallback(ByVal Code As Integer, _
ByVal wParam As Integer, _
ByRef lParam As KBDLLHOOKSTRUCT) As Integer
Try
If (Code = HC_ACTION) Then
'Define Key event otherwise it will fire for both KeyUp and KeyDown
If (wParam = WM_KEYUP Or wParam = WM_SYSKEYUP) Then
DebugMessage("Calling IsHooked")
'Pass the structure in.
If (IsHooked(lParam)) Then
'If we processed the key do NOT pass it on.
Return 0
Else
'Not a keystroke we care about so send it on.
Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam)
End If
End If
End If
Catch ex As Exception
MessageBox.Show(String.Format("cKeyBoardHook::KeyboardCallback - {0}", _
ex.Message))
End Try
End Function
'********************************************************************************
'* Procedure: IsHooked
'* Description:
'* Implement this function to trap as many key combinations as you'd like.
'* Return true if you want to block the key, False to pass it on.
'********************************************************************************
Private Function IsHooked(ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
Dim retVal As Boolean = False
Try
'Use GetAsyncKeyState to see if an additional key was pressed.
'I.E. Tab, Shift, Control etc.
'Example:
'If CInt(GetAsyncKeyState(VK_CONTROL)) <> 0 Then
' 'Control Key has been pressed.
'End If
'F1 & F2 are the predefined soft keys for the device.
Select Case Hookstruct.vkCode
Case VK_F1
DebugMessage("F1")
'Send the key on to the application.
RaiseEvent ProcessKey(Keys.F1)
retVal = True
Case VK_F2
DebugMessage("F2")
'Send the key on to the application.
RaiseEvent ProcessKey(Keys.F2)
retVal = True
Case VK_LWIN
'Block left windows key
DebugMessage("Left Windows Key")
retVal = True
Case VK_RWIN
'Block right windows key
DebugMessage("Right Windows Key")
retVal = True
Case VK_APPS
'Block Applications key
DebugMessage("Windows Application Key")
retVal = True
Case VK_OEMC5
'Blocking this key to prevent window launch
DebugMessage("OEM C5")
retVal = True
Case Else
DebugMessage(Hookstruct.vkCode.ToString())
retVal = False
End Select
Return retVal
Catch ex As Exception
MessageBox.Show(String.Format("cKeyBoardHook::IsHooked - {0}", ex.Message))
End Try
End Function
'********************************************************************************
'* Procedure: DebugMessage
'* Description:
'* Post the message to debug or a log.
'********************************************************************************
Private Sub DebugMessage(ByVal Text As String)
Debug.WriteLine(Text)
End Sub
'********************************************************************************
'* Procedure: Hooked
'* Description:
'* Are we hooked?
'********************************************************************************
Public Function Hooked() As Boolean
Hooked = KeyboardHandle <> 0
End Function
#End Region
End Class
0 comments:
Post a Comment