By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,379 Members | 3,035 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,379 IT Pros & Developers. It's quick & easy.

Low Level Keyboard Hooks in C#

P: n/a
Hi!
I need to prevent Task-Switching in my App, so I tried to implement a
low level keyboard hook in a extra class. But it seems that the
Parameters are not passed correctly to my Hook function. Similar
Examples in VB .NET work correctly.

Heres the Source Code:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;

public class LowLevelKeyboardHook :IDisposable
{
[DllImport("user32.dll")]
private static extern int SetWindowsHookExA(int IDHook, IntPtr lpfn,
int hMod,
int dwThreadID);

[DllImport("user32.dll")]
private static extern int UnhookWindowsHookEx(int hHook);

[DllImport("user32.dll")]
private static extern int CallNextHookEx(int hHook, int nCode, int
wParam, ref KBDLLHOOKSTRUCT lParam);

private delegate int LowLevelKeyboardProc(int nCode, int wParam,
KBDLLHOOKSTRUCT lParam);

public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}

private const int WH_KEYBOARD_LL = 13;
private int intLLKey;

public LowLevelKeyboardHook()
{
intLLKey = SetWindowsHookExA(WH_KEYBOARD_LL, new
LowLevelKeyboardProc(WindowKeyHook).Method.MethodH andle.GetFunctionPointer(),
System.Runtime.InteropServices.Marshal.GetHINSTANC E(System.Reflection.Assembly.GetExecutingAssembly( ).GetModules()[0]).ToInt32(),
0);
}

public int WindowKeyHook(int nCode, int wParam, KBDLLHOOKSTRUCT
lParam)
{
bool killKey = false;

if(killKey)
{
return 1;
}
else
{
return 0;
}
}

public void Dispose()
{
UnhookWindowsHookEx(intLLKey);
}
}
[b:2c1b8f9cf8]and the VB-Code, which worked[/b:2c1b8f9cf8]

Public Class frmMain
Inherits System.Windows.Forms.Form

Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As
LowLevelKeyboardProcDelegate, ByVal hMod As Integer, ByVal dwThreadId
As Integer) As Integer
Declare Function UnhookWindowsHookEx Lib "user32" Alias
"UnhookWindowsHookEx" (ByVal hHook As Integer) As Integer
Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode As
Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As
Integer
Declare Function CallNextHookEx Lib "user32" Alias
"CallNextHookEx" (ByVal hHook As Integer, ByVal nCode As Integer,
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer

Const WH_KEYBOARD_LL = 13

Structure KBDLLHOOKSTRUCT
Dim vkCode As Integer
Dim scanCode As Integer
Dim flags As Integer
Dim time As Integer
Dim dwExtraInfo As Integer
End Structure

Dim intLLKey As Integer

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.lblInfo = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'lblInfo
'
Me.lblInfo.Location = New System.Drawing.Point(16, 16)
Me.lblInfo.Name = "lblInfo"
Me.lblInfo.Size = New System.Drawing.Size(216, 88)
Me.lblInfo.TabIndex = 0
Me.lblInfo.Text = "Alt-Tab, Alt-Esc, Ctrl-Esc, and the Windows
key are disabled. Ctrl-Alt-Del and Al" & _
"t-F4 are still enabled. Close the application to reset the
keyboard. While this " & _
"program is running, the low-level keyboard effect is
global."
'
'frmMain
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(248, 118)
Me.Controls.AddRange(New System.Windows.Forms.Control()
{Me.lblInfo})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedDialog
Me.MaximizeBox = False
Me.MinimizeBox = False
Me.Name = "frmMain"
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScree n
Me.Text = "LowLevel Keyboard Hook"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf
LowLevelKeyboardProc,
System.Runtime.InteropServices.Marshal.GetHINSTANC E(System.Reflection.Assembly.GetExecutingAssembly. GetModules()(0)).ToInt32(),
0)
End Sub

Private Sub frmMain_Closing(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
UnhookWindowsHookEx(intLLKey)
End Sub

Private Function LowLevelKeyboardProc(ByVal nCode As Integer,
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
Dim blnEat As Boolean = False

Debug.WriteLine(nCode.ToString())

Select Case wParam
Case 256, 257, 260, 261
'Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key
blnEat = ((lParam.vkCode = 9) AndAlso (lParam.flags =
32)) Or _
((lParam.vkCode = 27) AndAlso (lParam.flags = 32))
Or _
((lParam.vkCode = 27) AndAlso (lParam.flags = 0))
Or _
((lParam.vkCode = 91) AndAlso (lParam.flags = 1))
Or _
((lParam.vkCode = 92) AndAlso (lParam.flags = 1))
End Select

If blnEat = True Then
Return 1
Else
Return CallNextHookEx(0, nCode, wParam, lParam)
End If
End Function
Friend WithEvents lblInfo As System.Windows.Forms.Label
End Class

hopefully somebody can help me!
thanks daFritz

----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 15 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
intLLKey = SetWindowsHookExA(WH_KEYBOARD_LL, new
LowLevelKeyboardProc(WindowKeyHook).Method.Method Handle.GetFunctionPointer(),
System.Runtime.InteropServices.Marshal.GetHINSTAN CE(System.Reflection.Assembly.GetExecutingAssembly ().GetModules()[0]).ToInt32(),
0);


The second parameter should be a delegate, just like in the VB.NET
code. GetFunctionPointer() will not work as expected.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #2

P: n/a
From what it looks like, you are trying to prevent OS
keyboard messaged from being processed by your app?

you might try to take a look at using the IMessageFilter
interface. This is a clean, totally managed way to do
this. When the keyboard event fires, the interfaces
PreFilterMessage function gets fired. you can then just
return the value of your killKey bool.

-----Original Message-----
Hi!
I need to prevent Task-Switching in my App, so I tried to implement alow level keyboard hook in a extra class. But it seems that theParameters are not passed correctly to my Hook function. SimilarExamples in VB .NET work correctly.

Heres the Source Code:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;

public class LowLevelKeyboardHook :IDisposable
{
[DllImport("user32.dll")]
private static extern int SetWindowsHookExA (int IDHook, IntPtr lpfn,int hMod,
int dwThreadID);

[DllImport("user32.dll")]
private static extern int UnhookWindowsHookEx(int hHook);
[DllImport("user32.dll")]
private static extern int CallNextHookEx (int hHook, int nCode, intwParam, ref KBDLLHOOKSTRUCT lParam);

private delegate int LowLevelKeyboardProc(int nCode, int wParam,KBDLLHOOKSTRUCT lParam);

public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}

private const int WH_KEYBOARD_LL = 13;
private int intLLKey;

public LowLevelKeyboardHook()
{
intLLKey = SetWindowsHookExA (WH_KEYBOARD_LL, newLowLevelKeyboardProc (WindowKeyHook).Method.MethodHandle.GetFunctionPoi nter(),System.Runtime.InteropServices.Marshal.GetHINSTAN CE (System.Reflection.Assembly.GetExecutingAssembly
().GetModules()[0]).ToInt32(),0);
}

public int WindowKeyHook(int nCode, int wParam, KBDLLHOOKSTRUCTlParam)
{
bool killKey = false;

if(killKey)
{
return 1;
}
else
{
return 0;
}
}

public void Dispose()
{
UnhookWindowsHookEx(intLLKey);
}
}
[b:2c1b8f9cf8]and the VB-Code, which worked[/b:2c1b8f9cf8]

Public Class frmMain
Inherits System.Windows.Forms.Form

Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn AsLowLevelKeyboardProcDelegate, ByVal hMod As Integer, ByVal dwThreadIdAs Integer) As Integer
Declare Function UnhookWindowsHookEx Lib "user32" Alias"UnhookWindowsHookEx" (ByVal hHook As Integer) As Integer
Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode AsInteger, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) AsInteger
Declare Function CallNextHookEx Lib "user32" Alias
"CallNextHookEx" (ByVal hHook As Integer, ByVal nCode As Integer,ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
Const WH_KEYBOARD_LL = 13

Structure KBDLLHOOKSTRUCT
Dim vkCode As Integer
Dim scanCode As Integer
Dim flags As Integer
Dim time As Integer
Dim dwExtraInfo As Integer
End Structure

Dim intLLKey As Integer

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer. InitializeComponent()

'Add any initialization after the InitializeComponent() call
End Sub

'Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing AsBoolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows FormDesigner
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.lblInfo = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'lblInfo
'
Me.lblInfo.Location = New System.Drawing.Point (16, 16) Me.lblInfo.Name = "lblInfo"
Me.lblInfo.Size = New System.Drawing.Size(216, 88)
Me.lblInfo.TabIndex = 0
Me.lblInfo.Text = "Alt-Tab, Alt-Esc, Ctrl-Esc, and the Windowskey are disabled. Ctrl-Alt-Del and Al" & _
"t-F4 are still enabled. Close the application to reset thekeyboard. While this " & _
"program is running, the low-level keyboard effect isglobal."
'
'frmMain
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(248, 118)
Me.Controls.AddRange(New System.Windows.Forms.Control(){Me.lblInfo})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedDialo g
Me.MaximizeBox = False
Me.MinimizeBox = False
Me.Name = "frmMain"
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScre en
Me.Text = "LowLevel Keyboard Hook"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e AsSystem.EventArgs) Handles MyBase.Load
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOfLowLevelKeyboardProc,
System.Runtime.InteropServices.Marshal.GetHINSTAN CE (System.Reflection.Assembly.GetExecutingAssembly.G etModules
()(0)).ToInt32(),0)
End Sub

Private Sub frmMain_Closing(ByVal sender As Object, ByVal e AsSystem.ComponentModel.CancelEventArgs) Handles MyBase.Closing UnhookWindowsHookEx(intLLKey)
End Sub

Private Function LowLevelKeyboardProc(ByVal nCode As Integer,ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer Dim blnEat As Boolean = False

Debug.WriteLine(nCode.ToString())

Select Case wParam
Case 256, 257, 260, 261
'Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key
blnEat = ((lParam.vkCode = 9) AndAlso (lParam.flags =32)) Or _
((lParam.vkCode = 27) AndAlso (lParam.flags = 32))Or _
((lParam.vkCode = 27) AndAlso (lParam.flags = 0))Or _
((lParam.vkCode = 91) AndAlso (lParam.flags = 1))Or _
((lParam.vkCode = 92) AndAlso (lParam.flags = 1)) End Select

If blnEat = True Then
Return 1
Else
Return CallNextHookEx(0, nCode, wParam, lParam) End If
End Function
Friend WithEvents lblInfo As System.Windows.Forms.LabelEnd Class

hopefully somebody can help me!
thanks daFritz

----== Posted via Newsfeed.Com - Unlimited-Uncensored- Secure Usenet News==----http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---.

Nov 15 '05 #3

P: n/a
Thanks, the provided links helped a lot understanding Low Level
Hooks;

:wink: daFritz

----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 15 '05 #4

P: n/a
The IMessageFilter is a good idea, but since the alt + tab message (or
similar hotkeys) are directly passed to windows (not over my app) it
won't work for me.

daFritz

----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 15 '05 #5

P: n/a
HookAPI is the API SDK that setup SYSTEM-WIDE hooks for all windows
platform,it could easily hook 32-bit windows system APIs or 32-bit
user-defined DLL, it could be used easily,and what you need to do is
only writing a DLL file named mydll.dll or mydll_9x.dll.

I think it will helpful for you.Please see the detail information at
http://www.programsalon.com/en/hookapi.htm
Nov 15 '05 #6

P: n/a
I have one app that uses Alt-mouseClick commands to enter a special
customization mode. However, due to the KVM I use, all mouse clicks are sent
as Alt-Click messages. This doesn't bother most software. However, it makes
that one certain program unusable (normal commands can't be processed). Does
anyone have any ideas how I could solve this issue? Could I write a program
to translate Alt-Clicks to regular clicks? It sounds like what I need is
similar to the topic of the OP. Thanks!
Regards,
Mountain

"daFritz" <da*****@inext-dot-at.no-spam.invalid> wrote in message
news:3f**********@127.0.0.1...
Hi!
I need to prevent Task-Switching in my App, so I tried to implement a
low level keyboard hook in a extra class. But it seems that the
Parameters are not passed correctly to my Hook function. Similar
Examples in VB .NET work correctly.

Heres the Source Code:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;

public class LowLevelKeyboardHook :IDisposable
{
[DllImport("user32.dll")]
private static extern int SetWindowsHookExA(int IDHook, IntPtr lpfn,
int hMod,
int dwThreadID);

[DllImport("user32.dll")]
private static extern int UnhookWindowsHookEx(int hHook);

[DllImport("user32.dll")]
private static extern int CallNextHookEx(int hHook, int nCode, int
wParam, ref KBDLLHOOKSTRUCT lParam);

private delegate int LowLevelKeyboardProc(int nCode, int wParam,
KBDLLHOOKSTRUCT lParam);

public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}

private const int WH_KEYBOARD_LL = 13;
private int intLLKey;

public LowLevelKeyboardHook()
{
intLLKey = SetWindowsHookExA(WH_KEYBOARD_LL, new
LowLevelKeyboardProc(WindowKeyHook).Method.MethodH andle.GetFunctionPointer()
, System.Runtime.InteropServices.Marshal.GetHINSTANC E(System.Reflection.Assemb
ly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
}

public int WindowKeyHook(int nCode, int wParam, KBDLLHOOKSTRUCT
lParam)
{
bool killKey = false;

if(killKey)
{
return 1;
}
else
{
return 0;
}
}

public void Dispose()
{
UnhookWindowsHookEx(intLLKey);
}
}
[b:2c1b8f9cf8]and the VB-Code, which worked[/b:2c1b8f9cf8]

Public Class frmMain
Inherits System.Windows.Forms.Form

Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As
LowLevelKeyboardProcDelegate, ByVal hMod As Integer, ByVal dwThreadId
As Integer) As Integer
Declare Function UnhookWindowsHookEx Lib "user32" Alias
"UnhookWindowsHookEx" (ByVal hHook As Integer) As Integer
Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode As
Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As
Integer
Declare Function CallNextHookEx Lib "user32" Alias
"CallNextHookEx" (ByVal hHook As Integer, ByVal nCode As Integer,
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer

Const WH_KEYBOARD_LL = 13

Structure KBDLLHOOKSTRUCT
Dim vkCode As Integer
Dim scanCode As Integer
Dim flags As Integer
Dim time As Integer
Dim dwExtraInfo As Integer
End Structure

Dim intLLKey As Integer

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.lblInfo = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'lblInfo
'
Me.lblInfo.Location = New System.Drawing.Point(16, 16)
Me.lblInfo.Name = "lblInfo"
Me.lblInfo.Size = New System.Drawing.Size(216, 88)
Me.lblInfo.TabIndex = 0
Me.lblInfo.Text = "Alt-Tab, Alt-Esc, Ctrl-Esc, and the Windows
key are disabled. Ctrl-Alt-Del and Al" & _
"t-F4 are still enabled. Close the application to reset the
keyboard. While this " & _
"program is running, the low-level keyboard effect is
global."
'
'frmMain
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(248, 118)
Me.Controls.AddRange(New System.Windows.Forms.Control()
{Me.lblInfo})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedDialog
Me.MaximizeBox = False
Me.MinimizeBox = False
Me.Name = "frmMain"
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScree n
Me.Text = "LowLevel Keyboard Hook"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf
LowLevelKeyboardProc,
System.Runtime.InteropServices.Marshal.GetHINSTANC E(System.Reflection.Assemb
ly.GetExecutingAssembly.GetModules()(0)).ToInt32() , 0)
End Sub

Private Sub frmMain_Closing(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
UnhookWindowsHookEx(intLLKey)
End Sub

Private Function LowLevelKeyboardProc(ByVal nCode As Integer,
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
Dim blnEat As Boolean = False

Debug.WriteLine(nCode.ToString())

Select Case wParam
Case 256, 257, 260, 261
'Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key
blnEat = ((lParam.vkCode = 9) AndAlso (lParam.flags =
32)) Or _
((lParam.vkCode = 27) AndAlso (lParam.flags = 32))
Or _
((lParam.vkCode = 27) AndAlso (lParam.flags = 0))
Or _
((lParam.vkCode = 91) AndAlso (lParam.flags = 1))
Or _
((lParam.vkCode = 92) AndAlso (lParam.flags = 1))
End Select

If blnEat = True Then
Return 1
Else
Return CallNextHookEx(0, nCode, wParam, lParam)
End If
End Function
Friend WithEvents lblInfo As System.Windows.Forms.Label
End Class

hopefully somebody can help me!
thanks daFritz

----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption

=---
Nov 15 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.