C # Hook instance code intercepting keyboard input

Source: Internet
Author: User

I. About this article

Describes how to use hooks in the most popular language. For details about hooks, refer to the following URL:

Http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx

II. Introduction to hooks

Literally, hooks are intended to hook up something. In a program, hooks can be used to process Windows messages in advance.

Example: There is A Form and A TextBox in Form. When we want users to input the TextBox, no matter which key is typed on the keyboard, the TextBox always displays "", in this case, you can use a hook to listen to keyboard messages. First, add a hook to the hook linked list of Windows to listen to keyboard messages. If you press the keyboard, a keyboard message is generated, our Hook intercepts the message before it passes to the TextBox, so that the TextBox displays A "A" and ends the message. In this way, the TextBox always gets "".

Message interception order: since a message is intercepted, there is always a first order, and the hook is added to the hook list to determine the order of message interception. That is to say, the hook added to the linked list first obtains the message.

Interception scope: hooks are divided into thread hooks and global hooks. Thread hooks can only intercept messages of the current thread, and global hooks can intercept messages of the entire system. I think thread hooks should be used whenever possible. Improper use of global hooks may affect other programs.

3. Start


Here is a simple example of a thread hook.

Step 1: declare API functions

Copy codeThe Code is as follows: # region Step 1: declare an API Function
// When using hooks, you must use WindowsAPI functions. Therefore, you must declare these API functions first.

// Install the hook
[DllImport ("user32.dll", CharSet = CharSet. Auto, CallingConvention = CallingConvention. StdCall)]
Public static extern int SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId );

// Uninstall the hook
[DllImport ("user32.dll", CharSet = CharSet. Auto, CallingConvention = CallingConvention. StdCall)]
Public static extern bool UnhookWindowsHookEx (int idHook );

// Continue the next hook
[DllImport ("user32.dll", CharSet = CharSet. Auto, CallingConvention = CallingConvention. StdCall)]
Public static extern int CallNextHookEx (int idHook, int nCode, Int32 wParam, IntPtr lParam );

// Obtain the ID of the current thread
[DllImport ("kernel32.dll")]
Static extern int GetCurrentThreadId ();

# Endregion

Declare the API function and then call it directly.

Step 2: declare and define.

Copy codeThe Code is as follows: # region Step 2: declare and define the delegate
Public delegate int HookProc (int nCode, Int32 wParam, IntPtr lParam );

Static int hKeyboardHook = 0; // If the hKeyboardHook is not 0, the hook is successfully installed.

HookProc KeyboardHookProcedure;
# Endregion

First, explain the delegate. The hook must use A standard hook sub-process. The hook sub-process is A method that handles the operations mentioned in the preceding example to display "A" on the TextBox.

The hooks must be defined according to the HookProc (int nCode, Int32 wParam, IntPtr lParam) structure. The three parameters will get the data about the message.

After the hook is successfully installed using the SetWindowsHookEx function, the handle of the hook sub-process is returned. The hKeyboardHook variable records the returned handle. If the hKeyboardHook is not 0, the hook is successfully installed.

Step 3: Write the hook Program

Copy codeThe Code is as follows: # Step 3 of region: Compile the hook Program
// The Hook process is what the hook is going to do.

Private int KeyboardHookProc (int nCode, Int32 wParam, IntPtr IParam)
{
If (nCode> = 0)
{
TextBox1.Text = "hello, fangqm.cn ";
Return 1;
}
Return CallNextHookEx (hKeyboardHook, nCode, wParam, IParam );
}
# Endregion

Let's write a method and return an int value, which includes three parameters. As shown in the code above, it complies with the hook program standard.

The nCode parameter is the Hook code. The Hook program uses this parameter to determine the task. The value of this parameter depends on the Hook type.

The wParam and lParam parameters contain message information, from which we can extract the required information.

The content of the method can be compiled as needed. We need the TextBox to display "fangqm.cn", and we will write it here. After the Hook intercepts the message, it will call the hook sub-program. After the program ends, it will proceed. How to process the intercepted message depends on the return value of the Child Program. If 1 is returned, the message ends. This message is no longer transmitted until now. If the return value is 0 or the CallNextHookEx function is called, the message returns this hook and continues to be transmitted, that is, to the real receiver of the message.

Step 4: Enable hooks: Install and uninstall hooks
The preparation is complete, and the rest is to load the hook into the hook linked list.
We can write two methods for calling in a proper position in the program. The Code is as follows:

Copy codeThe Code is as follows: # Step 4 of region: Enable hook
// Hook Installation
Public void HookStart ()
{
If (hKeyboardHook = 0) // if hKeyboardHook = 0, the hook fails to be installed.
{
// Create a HookProc instance
KeyboardHookProcedure = new HookProc (KeyboardHookProc );
// Set the thread hook
HKeyboardHook = SetWindowsHookEx (2, KeyboardHookProc, IntPtr. Zero, GetCurrentThreadId ());

If (hKeyboardHook = 0)
{
// Terminate the hook
Throw new Exception ("hook Installation failed ");
}
}
}

// Uninstall the hook
Public void HookStop ()
{
Bool retKeyboard = true;
If (hKeyboardHook! = 0)
{
RetKeyboard = UnhookWindowsHookEx (hKeyboardHook );
HKeyboardHook = 0;
}
If (! RetKeyboard)
Throw new Exception ("hook unmounting failed ");

}
# Endregion

The key to installing and uninstalling Hooks is the SetWindowsHookEx and UnhookWindowsHookEx methods.
The SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId) function adds the hook to the hook list and describes the four parameters:
The idHook hook type is used to determine the type of messages that the hook listens to. In the above Code, set it to 2, that is, to listen to keyboard messages and to be thread hooks. If the global hook listens to keyboard messages, set it to 13, set the thread hook to listen to the mouse message to 7, and the global hook to listen to the mouse message to 14.
The address pointer of the lpfn hook sub-program. If the dwThreadId parameter is 0 or is identified by a thread created by another process, lpfn must point to the hook Child Program in the DLL. In addition, lpfn can point to a hook sub-program code of the current process. The entry address of the hook function. This function is called when the hook hooks any message.
Handle Of The hInstance application instance. Identifies the DLL that contains the Child Program referred to by lpfn. If threadId identifies a thread created by the current process and the Child Code is in the current process, hInstance must be NULL. You can easily set the instance handle of this application.
The identifier of the Thread associated with the installed hook child. If the value is 0, the hook sub-program is associated with all threads, that is, the global hook.
In the preceding code, the SetWindowsHookEx method is used to install a thread hook. The GetCurrentThreadId () function is used to obtain the current thread ID. The hook only listens to the keyboard messages of the current thread.
The UnhookWindowsHookEx (int idHook) function is used to unmount a hook. The unmount Hook has nothing to do with the sequence of adding the hook linked list, rather than going in and out later.

4. Install global hooks

The preceding example uses a thread hook. If you want to use a global Hook, the installation of the hook is slightly different. As follows:
SetWindowsHookEx (13, KeyboardHookProcedure,
Marshal. GetHINSTANCE (Assembly. GetExecutingAssembly (). GetModules () [0]), 0)
This statement defines the global hook.
Subprocess Message Processing
You can obtain two parameters wPrama and lParam for message information. How can we convert these two parameters into messages that are easier to understand.
For mouse messages, we can define the following structure:

Copy codeThe Code is as follows: public struct MSG
{
Public Point p;
Public IntPtr HWnd;
Public uint wHitTestCode;
Public int dwExtraInfo;
}

For keyboard messages, we can define the following structure:

Copy codeThe Code is as follows: public struct KeyMSG
{
Public int vkCode;
Public int scanCode;
Public int flags;
Public int time;
Public int dwExtraInfo;
}

Then we can use the following statement to convert lParam data into MSG or KeyMSG structured data in the Child Program.
MSG m = (MSG) Marshal. PtrToStructure (lParam, typeof (MSG ));
KeyMSG m = (KeyMSG) Marshal. PtrToStructure (lParam, typeof (KeyMSG ));

In this way, you can obtain the mouse message or Keyboard Message information more conveniently. For example, p is the mouse coordinate, HWnd is the handle of the mouse click control, and vkCode is the key code.
Note: This statement can be used for thread hooks and global hooks that listen to mouse messages. However, it may cause errors when used for thread hooks that listen to keyboard messages.
If it is a thread hook that listens to keyboard messages, we can determine whether the buttons are pressed or lifted based on the lParam value, and which key is pressed Based on the wParam value.

Copy codeThe Code is as follows: // press the key
Keys keyData = (Keys) wParam;
If (lParam. ToInt32 ()> 0)
{
// Press the keyboard
}
If (lParam. ToInt32 () <0)
{
// Lift the keyboard
}

If it is a global hook that listens to keyboard messages, press or hold the key to determine based on the wParam value.
WParam = 0x100 // press the keyboard
WParam = 0x101 // lift the keyboard

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.