Thêm các event
Sẽ tiện lợi hơn nếu bạn thêm các event cho lớp để sử dụng như một control. Net đã cung cấp sẵn delegate KeyEventHandler. Nếu bạn cần tìm hiểu về cách tạo event, có thể tham khảo hướng dẫn tại:
Tạo, sử dụng và quản lý Event trong C#.
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
Trong hook procedure, ta sẽ xử lý để kích hoạt event nếu thông điệp tương ứng với event đó xảy ra:
01 | private IntPtr KeyboardHookProc( int nCode, IntPtr wParam, IntPtr lParam) |
05 | KeyboardHookStruct kbStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof (KeyboardHookStruct)); |
07 | if (wParam == (IntPtr)WM_KEYDOWN) |
10 | KeyDown( null , new KeyEventArgs((Keys)kbStruct.VirtualKeyCode)); |
12 | else if (wParam == (IntPtr)WM_KEYUP) |
15 | KeyUp( null , new KeyEventArgs((Keys)kbStruct.VirtualKeyCode)); |
19 | return CallNextHookEx(_hookHandle, nCode, wParam, lParam); |
Ví dụ hoàn chỉnh
Để thực hiện ví dụ này, bạn hãy tạo một dự án Windows Forms Application. Thêm lớpY2KeyboardHook sau vào dự án:
002 | using System.Runtime.InteropServices; |
003 | using System.Diagnostics; |
004 | using System.Windows.Forms; |
005 | using System.Reflection; |
006 | using System.ComponentModel; |
014 | #region Win32 API Functions and Constants |
016 | [DllImport( "user32.dll" , SetLastError = true )] |
017 | private static extern IntPtr SetWindowsHookEx( int idHook, |
018 | KeyboardHookDelegate lpfn, IntPtr hMod, int dwThreadId); |
020 | [DllImport( "user32.dll" , SetLastError = true )] |
021 | private static extern bool UnhookWindowsHookEx(IntPtr hhk); |
023 | [DllImport( "user32.dll" , SetLastError = true )] |
024 | private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, |
025 | IntPtr wParam, IntPtr lParam); |
027 | [DllImport( "kernel32.dll" )] |
028 | private static extern IntPtr GetModuleHandle( string lpModuleName); |
030 | private const int WH_KEYBOARD_LL = 13; |
032 | private const int WM_KEYDOWN = 0x0100; |
033 | private const int WM_KEYUP = 0x101; |
037 | private KeyboardHookDelegate _hookProc; |
038 | private IntPtr _hookHandle = IntPtr.Zero; |
040 | public delegate IntPtr KeyboardHookDelegate( int nCode, IntPtr wParam, IntPtr lParam); |
042 | [StructLayout(LayoutKind.Sequential)] |
043 | public struct KeyboardHookStruct |
045 | public int VirtualKeyCode; |
049 | public int ExtraInfo; |
052 | #region Keyboard Events |
054 | public event KeyEventHandler KeyDown; |
055 | public event KeyEventHandler KeyUp; |
065 | public void Install() |
067 | _hookProc = KeyboardHookProc; |
068 | _hookHandle = SetupHook(_hookProc); |
070 | if (_hookHandle == IntPtr.Zero) |
071 | throw new Win32Exception(Marshal.GetLastWin32Error()); |
073 | private IntPtr SetupHook(KeyboardHookDelegate hookProc) |
075 | IntPtr hInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]); |
077 | return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0); |
080 | private IntPtr KeyboardHookProc( int nCode, IntPtr wParam, IntPtr lParam) |
084 | KeyboardHookStruct kbStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof (KeyboardHookStruct)); |
086 | if (wParam == (IntPtr)WM_KEYDOWN) |
089 | KeyDown( null , new KeyEventArgs((Keys)kbStruct.VirtualKeyCode)); |
091 | else if (wParam == (IntPtr)WM_KEYUP) |
094 | KeyUp( null , new KeyEventArgs((Keys)kbStruct.VirtualKeyCode)); |
098 | return CallNextHookEx(_hookHandle, nCode, wParam, lParam); |
101 | public void Uninstall() |
103 | UnhookWindowsHookEx(_hookHandle); |
Trong tập tin Form1.cs, bạn hãy sửa lại như sau:
02 | using System.Windows.Forms; |
06 | namespace WindowsFormApplication1 |
08 | public partial class Form1 : Form |
10 | Y2KeyboardHook _keyboardHook; |
14 | InitializeComponent(); |
18 | ListBox listBox1 = new ListBox(); |
19 | listBox1.Location = new Point(10, 10); |
20 | listBox1.Size = new Size(200, 200); |
22 | this .Controls.Add(listBox1); |
24 | _keyboardHook = new Y2KeyboardHook(); |
25 | _keyboardHook.Install(); |
27 | _keyboardHook.KeyDown += (sender, e) => |
29 | listBox1.Items.Add( "KeyDown: " + e.KeyCode); |
31 | listBox1.SelectedIndex = listBox1.Items.Count - 1; |
34 | _keyboardHook.KeyUp += (sender, e) => |
36 | listBox1.Items.Add( "KeyUp: " + e.KeyCode); |
38 | listBox1.SelectedIndex = listBox1.Items.Count - 1; |
Đoạn mã mới thêm vào Form1 sẽ thêm một ListBox vào Form, đồng thời tạo ra một đối tượng Y2KeyboardHook và xử lý hai event KeyDown và KeyDown bằng lambda expression. Bạn có thể chuyển sang ứng dụng khác và nhấn phím bất kì, các sự kiện tương ứng sẽ được thêm vào ListBox.
Kết luận
Bạn có thể thấy rằng việc sử dụng hook trong C# rất dễ dàng, tuy nhiên để cải tiến chương trình hook bạn cần phải kiến thức đầy đủ về các hàm Win32 API cần thiết. Dựa vào ví dụ này, bạn có thể viết được một chương trình hook mouse đơn giản. Và hơn nữa là một chương trình có mức tổng quát cao cho phép cài đặt nhiều loại hook khác nhau.
Không có nhận xét nào:
Đăng nhận xét