C#键盘鼠标钩子实例
本文实例讲述了c#键盘鼠标钩子的实现方法。分享给大家供大家参考。具体实现方法如下:
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.windows.forms;
using system.runtime.interopservices;
using system.componentmodel;
using system.reflection;
namespace alif.commonapi.windowsapi
{
/// <summary>
/// 用户键盘鼠标钩子
/// </summary>
public class useractivityhook
{
#region windows structure definitions
/// <summary>
/// the point structure defines the x- and y- coordinates of a point.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/rectangl_0tiq.asp
/// </remarks>
[structlayout(layoutkind.sequential)]
private class point
{
/// <summary>
/// specifies the x-coordinate of the point.
/// </summary>
public int x;
/// <summary>
/// specifies the y-coordinate of the point.
/// </summary>
public int y;
}
/// <summary>
/// the mousehookstruct structure contains information about a mouse event passed to a wh_mouse hook procedure, mouseproc.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
/// </remarks>
[structlayout(layoutkind.sequential)]
private class mousehookstruct
{
/// <summary>
/// specifies a point structure that contains the x- and y-coordinates of the cursor, in screen coordinates.
/// </summary>
public point pt;
/// <summary>
/// handle to the window that will receive the mouse message corresponding to the mouse event.
/// </summary>
public int hwnd;
/// <summary>
/// specifies the hit-test value. for a list of hit-test values, see the description of the wm_nchittest message.
/// </summary>
public int whittestcode;
/// <summary>
/// specifies extra information associated with the message.
/// </summary>
public int dwextrainfo;
}
/// <summary>
/// the msllhookstruct structure contains information about a low-level keyboard input event.
/// </summary>
[structlayout(layoutkind.sequential)]
private class mousellhookstruct
{
/// <summary>
/// specifies a point structure that contains the x- and y-coordinates of the cursor, in screen coordinates.
/// </summary>
public point pt;
/// <summary>
/// if the message is wm_mousewheel, the high-order word of this member is the wheel delta.
/// the low-order word is reserved. a positive value indicates that the wheel was rotated forward,
/// away from the user; a negative value indicates that the wheel was rotated backward, toward the user.
/// one wheel click is defined as wheel_delta, which is 120.
///if the message is wm_xbuttondown, wm_xbuttonup, wm_xbuttondblclk, wm_ncxbuttondown, wm_ncxbuttonup,
/// or wm_ncxbuttondblclk, the high-order word specifies which x button was pressed or released,
/// and the low-order word is reserved. this value can be one or more of the following values. otherwise, mousedata is not used.
///xbutton1
///the first x button was pressed or released.
///xbutton2
///the second x button was pressed or released.
/// </summary>
public int mousedata;
/// <summary>
/// specifies the event-injected flag. an application can use the following value to test the mouse flags. value purpose
///llmhf_injected test the event-injected flag.
///0
///specifies whether the event was injected. the value is 1 if the event was injected; otherwise, it is 0.
///1-15
///reserved.
/// </summary>
public int flags;
/// <summary>
/// specifies the time stamp for this message.
/// </summary>
public int time;
/// <summary>
/// specifies extra information associated with the message.
/// </summary>
public int dwextrainfo;
}
/// <summary>
/// the kbdllhookstruct structure contains information about a low-level keyboard input event.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
/// </remarks>
[structlayout(layoutkind.sequential)]
private class keyboardhookstruct
{
/// <summary>
/// specifies a virtual-key code. the code must be a value in the range 1 to 254.
/// </summary>
public int vkcode;
/// <summary>
/// specifies a hardware scan code for the key.
/// </summary>
public int scancode;
/// <summary>
/// specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
/// </summary>
public int flags;
/// <summary>
/// specifies the time stamp for this message.
/// </summary>
public int time;
/// <summary>
/// specifies extra information associated with the message.
/// </summary>
public int dwextrainfo;
}
#endregion
#region windows function imports
/// <summary>
/// the setwindowshookex function installs an application-defined hook procedure into a hook chain.
/// you would install a hook procedure to monitor the system for certain types of events. these events
/// are associated either with a specific thread or with all threads in the same desktop as the calling thread.
/// </summary>
/// <param name="idhook">
/// [in] specifies the type of hook procedure to be installed. this parameter can be one of the following values.
/// </param>
/// <param name="lpfn">
/// [in] pointer to the hook procedure. if the dwthreadid parameter is zero or specifies the identifier of a
/// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link
/// library (dll). otherwise, lpfn can point to a hook procedure in the code associated with the current process.
/// </param>
/// <param name="hmod">
/// [in] handle to the dll containing the hook procedure pointed to by the lpfn parameter.
/// the hmod parameter must be set to null if the dwthreadid parameter specifies a thread created by
/// the current process and if the hook procedure is within the code associated with the current process.
/// </param>
/// <param name="dwthreadid">
/// [in] specifies the identifier of the thread with which the hook procedure is to be associated.
/// if this parameter is zero, the hook procedure is associated with all existing threads running in the
/// same desktop as the calling thread.
/// </param>
/// <returns>
/// if the function succeeds, the return value is the handle to the hook procedure.
/// if the function fails, the return value is null. to get extended error information, call getlasterror.
/// </returns>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
/// </remarks>
[dllimport("user32.dll", charset = charset.auto,
callingconvention = callingconvention.stdcall, setlasterror = true)]
private static extern int setwindowshookex(
int idhook,
hookproc lpfn,
intptr hmod,
int dwthreadid);
/// <summary>
/// the unhookwindowshookex function removes a hook procedure installed in a hook chain by the setwindowshookex function.
/// </summary>
/// <param name="idhook">
/// [in] handle to the hook to be removed. this parameter is a hook handle obtained by a previous call to setwindowshookex.
/// </param>
/// <returns>
/// if the function succeeds, the return value is nonzero.
/// if the function fails, the return value is zero. to get extended error information, call getlasterror.
/// </returns>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
/// </remarks>
[dllimport("user32.dll", charset = charset.auto,
callingconvention = callingconvention.stdcall, setlasterror = true)]
private static extern int unhookwindowshookex(int idhook);
/// <summary>
/// the callnexthookex function passes the hook information to the next hook procedure in the current hook chain.
/// a hook procedure can call this function either before or after processing the hook information.
/// </summary>
/// <param name="idhook">ignored.</param>
/// <param name="ncode">
/// [in] specifies the hook code passed to the current hook procedure.
/// the next hook procedure uses this code to determine how to process the hook information.
/// </param>
/// <param name="wparam">
/// [in] specifies the wparam value passed to the current hook procedure.
/// the meaning of this parameter depends on the type of hook associated with the current hook chain.
/// </param>
/// <param name="lparam">
/// [in] specifies the lparam value passed to the current hook procedure.
/// the meaning of this parameter depends on the type of hook associated with the current hook chain.
/// </param>
/// <returns>
/// this value is returned by the next hook procedure in the chain.
/// the current hook procedure must also return this value. the meaning of the return value depends on the hook type.
/// for more information, see the descriptions of the individual hook procedures.
/// </returns>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
/// </remarks>
[dllimport("user32.dll", charset = charset.auto,
callingconvention = callingconvention.stdcall)]
private static extern int callnexthookex(
int idhook,
int ncode,
int wparam,
intptr lparam);
/// <summary>
/// the callwndproc hook procedure is an application-defined or library-defined callback
/// function used with the setwindowshookex function. the hookproc type defines a pointer
/// to this callback function. callwndproc is a placeholder for the application-defined
/// or library-defined function name.
/// </summary>
/// <param name="ncode">
/// [in] specifies whether the hook procedure must process the message.
/// if ncode is hc_action, the hook procedure must process the message.
/// if ncode is less than zero, the hook procedure must pass the message to the
/// callnexthookex function without further processing and must return the
/// value returned by callnexthookex.
/// </param>
/// <param name="wparam">
/// [in] specifies whether the message was sent by the current thread.
/// if the message was sent by the current thread, it is nonzero; otherwise, it is zero.
/// </param>
/// <param name="lparam">
/// [in] pointer to a cwpstruct structure that contains details about the message.
/// </param>
/// <returns>
/// if ncode is less than zero, the hook procedure must return the value returned by callnexthookex.
/// if ncode is greater than or equal to zero, it is highly recommended that you call callnexthookex
/// and return the value it returns; otherwise, other applications that have installed wh_callwndproc
/// hooks will not receive hook notifications and may behave incorrectly as a result. if the hook
/// procedure does not call callnexthookex, the return value should be zero.
/// </returns>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/callwndproc.asp
/// </remarks>
private delegate int hookproc(int ncode, int wparam, intptr lparam);
/// <summary>
/// the toascii function translates the specified virtual-key code and keyboard
/// state to the corresponding character or characters. the function translates the code
/// using the input language and physical keyboard layout identified by the keyboard layout handle.
/// </summary>
/// <param name="uvirtkey">
/// [in] specifies the virtual-key code to be translated.
/// </param>
/// <param name="uscancode">
/// [in] specifies the hardware scan code of the key to be translated.
/// the high-order bit of this value is set if the key is up (not pressed).
/// </param>
/// <param name="lpbkeystate">
/// [in] pointer to a 256-byte array that contains the current keyboard state.
/// each element (byte) in the array contains the state of one key.
/// if the high-order bit of a byte is set, the key is down (pressed).
/// the low bit, if set, indicates that the key is toggled on. in this function,
/// only the toggle bit of the caps lock key is relevant. the toggle state
/// of the num lock and scroll lock keys is ignored.
/// </param>
/// <param name="lpwtranskey">
/// [out] pointer to the buffer that receives the translated character or characters.
/// </param>
/// <param name="fustate">
/// [in] specifies whether a menu is active. this parameter must be 1 if a menu is active, or 0 otherwise.
/// </param>
/// <returns>
/// if the specified key is a dead key, the return value is negative. otherwise, it is one of the following values.
/// value meaning
/// 0 the specified virtual key has no translation for the current state of the keyboard.
/// 1 one character was copied to the buffer.
/// 2 two characters were copied to the buffer. this usually happens when a dead-key character
/// (accent or diacritic) stored in the keyboard layout cannot be composed with the specified
/// virtual key to form a single character.
/// </returns>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp
/// </remarks>
[dllimport("user32")]
private static extern int toascii(
int uvirtkey,
int uscancode,
byte[] lpbkeystate,
byte[] lpwtranskey,
int fustate);
/// <summary>
/// the getkeyboardstate function copies the status of the 256 virtual keys to the
/// specified buffer.
/// </summary>
/// <param name="pbkeystate">
/// [in] pointer to a 256-byte array that contains keyboard key states.
/// </param>
/// <returns>
/// if the function succeeds, the return value is nonzero.
/// if the function fails, the return value is zero. to get extended error information, call getlasterror.
/// </returns>
/// <remarks>
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp
/// </remarks>
[dllimport("user32")]
private static extern int getkeyboardstate(byte[] pbkeystate);
[dllimport("user32.dll", charset = charset.auto, callingconvention = callingconvention.stdcall)]
private static extern short getkeystate(int vkey);
#endregion
#region windows constants
//values from winuser.h in microsoft sdk.
/// <summary>
/// windows nt/2000/xp: installs a hook procedure that monitors low-level mouse input events.
/// </summary>
private const int wh_mouse_ll = 14;
/// <summary>
/// windows nt/2000/xp: installs a hook procedure that monitors low-level keyboard input events.
/// </summary>
private const int wh_keyboard_ll = 13;
/// <summary>
/// installs a hook procedure that monitors mouse messages. for more information, see the mouseproc hook procedure.
/// </summary>
private const int wh_mouse = 7;
/// <summary>
/// installs a hook procedure that monitors keystroke messages. for more information, see the keyboardproc hook procedure.
/// </summary>
private const int wh_keyboard = 2;
/// <summary>
/// the wm_mousemove message is posted to a window when the cursor moves.
/// </summary>
private const int wm_mousemove = 0x200;
/// <summary>
/// the wm_lbuttondown message is posted when the user presses the left mouse button
/// </summary>
private const int wm_lbuttondown = 0x201;
/// <summary>
/// the wm_rbuttondown message is posted when the user presses the right mouse button
/// </summary>
private const int wm_rbuttondown = 0x204;
/// <summary>
/// the wm_mbuttondown message is posted when the user presses the middle mouse button
/// </summary>
private const int wm_mbuttondown = 0x207;
/// <summary>
/// the wm_lbuttonup message is posted when the user releases the left mouse button
/// </summary>
private const int wm_lbuttonup = 0x202;
/// <summary>
/// the wm_rbuttonup message is posted when the user releases the right mouse button
/// </summary>
private const int wm_rbuttonup = 0x205;
/// <summary>
/// the wm_mbuttonup message is posted when the user releases the middle mouse button
/// </summary>
private const int wm_mbuttonup = 0x208;
/// <summary>
/// the wm_lbuttondblclk message is posted when the user double-clicks the left mouse button
/// </summary>
private const int wm_lbuttondblclk = 0x203;
/// <summary>
/// the wm_rbuttondblclk message is posted when the user double-clicks the right mouse button
/// </summary>
private const int wm_rbuttondblclk = 0x206;
/// <summary>
/// the wm_rbuttondown message is posted when the user presses the right mouse button
/// </summary>
private const int wm_mbuttondblclk = 0x209;
/// <summary>
/// the wm_mousewheel message is posted when the user presses the mouse wheel.
/// </summary>
private const int wm_mousewheel = 0x020a;
/// <summary>
/// the wm_keydown message is posted to the window with the keyboard focus when a nonsystem
/// key is pressed. a nonsystem key is a key that is pressed when the alt key is not pressed.
/// </summary>
private const int wm_keydown = 0x100;
/// <summary>
/// the wm_keyup message is posted to the window with the keyboard focus when a nonsystem
/// key is released. a nonsystem key is a key that is pressed when the alt key is not pressed,
/// or a keyboard key that is pressed when a window has the keyboard focus.
/// </summary>
private const int wm_keyup = 0x101;
/// <summary>
/// the wm_syskeydown message is posted to the window with the keyboard focus when the user
/// presses the f10 key (which activates the menu bar) or holds down the alt key and then
/// presses another key. it also occurs when no window currently has the keyboard focus;
/// in this case, the wm_syskeydown message is sent to the active window. the window that
/// receives the message can distinguish between these two contexts by checking the context
/// code in the lparam parameter.
/// </summary>
private const int wm_syskeydown = 0x104;
/// <summary>
/// the wm_syskeyup message is posted to the window with the keyboard focus when the user
/// releases a key that was pressed while the alt key was held down. it also occurs when no
/// window currently has the keyboard focus; in this case, the wm_syskeyup message is sent
/// to the active window. the window that receives the message can distinguish between
/// these two contexts by checking the context code in the lparam parameter.
/// </summary>
private const int wm_syskeyup = 0x105;
private const byte vk_shift = 0x10;
private const byte vk_capital = 0x14;
private const byte vk_numlock = 0x90;
#endregion
/// <summary>
/// creates an instance of useractivityhook object and sets mouse and keyboard hooks.
/// </summary>
/// <exception cref="win32exception">any windows problem.</exception>
public useractivityhook()
{
start();
}
/// <summary>
/// creates an instance of useractivityhook object and installs both or one of mouse and/or keyboard hooks and starts rasing events
/// </summary>
/// <param name="installmousehook"><b>true</b> if mouse events must be monitored</param>
/// <param name="installkeyboardhook"><b>true</b> if keyboard events must be monitored</param>
/// <exception cref="win32exception">any windows problem.</exception>
/// <remarks>
/// to create an instance without installing hooks call new useractivityhook(false, false)
/// </remarks>
public useractivityhook(bool installmousehook, bool installkeyboardhook)
{
start(installmousehook, installkeyboardhook);
}
/// <summary>
/// destruction.
/// </summary>
~useractivityhook()
{
//uninstall hooks and do not throw exceptions
stop(true, true, false);
}
/// <summary>
/// occurs when the user moves the mouse, presses any mouse button or scrolls the wheel
/// </summary>
public event mouseeventhandler onmouseactivity;
/// <summary>
/// occurs when the user presses a key
/// </summary>
public event keyeventhandler keydown;
/// <summary>
/// occurs when the user presses and releases
/// </summary>
public event keypresseventhandler keypress;
/// <summary>
/// occurs when the user releases a key
/// </summary>
public event keyeventhandler keyup;
/// <summary>
/// stores the handle to the mouse hook procedure.
/// </summary>
private int hmousehook = 0;
/// <summary>
/// stores the handle to the keyboard hook procedure.
/// </summary>
private int hkeyboardhook = 0;
/// <summary>
/// declare mousehookprocedure as hookproc type.
/// </summary>
private static hookproc mousehookprocedure;
/// <summary>
/// declare keyboardhookprocedure as hookproc type.
/// </summary>
private static hookproc keyboardhookprocedure;
/// <summary>
/// installs both mouse and keyboard hooks and starts raising events
/// </summary>
/// <exception cref="win32exception">any windows problem.</exception>
public void start()
{
this.start(true, true);
}
/// <summary>
/// installs both or one of mouse and/or keyboard hooks and starts raising events
/// </summary>
/// <param name="installmousehook"><b>true</b> if mouse events must be monitored</param>
/// <param name="installkeyboardhook"><b>true</b> if keyboard events must be monitored</param>
/// <exception cref="win32exception">any windows problem.</exception>
public void start(bool installmousehook, bool installkeyboardhook)
{
// install mouse hook only if it is not installed and must be installed
if (hmousehook == 0 && installmousehook)
{
// create an instance of hookproc.
mousehookprocedure = new hookproc(mousehookproc);
//install hook
hmousehook = setwindowshookex(
wh_mouse_ll,
mousehookprocedure,
marshal.gethinstance(
assembly.getexecutingassembly().getmodules()[0]),
0);
//if setwindowshookex fails.
if (hmousehook == 0)
{
//returns the error code returned by the last unmanaged function called using platform invoke that has the dllimportattribute.setlasterror flag set.
int errorcode = marshal.getlastwin32error();
//do cleanup
stop(true, false, false);
//initializes and throws a new instance of the win32exception class with the specified error.
throw new win32exception(errorcode);
}
}
// install keyboard hook only if it is not installed and must be installed
if (hkeyboardhook == 0 && installkeyboardhook)
{
// create an instance of hookproc.
keyboardhookprocedure = new hookproc(keyboardhookproc);
//install hook
hkeyboardhook = setwindowshookex(
wh_keyboard_ll,
keyboardhookprocedure,
marshal.gethinstance(
assembly.getexecutingassembly().getmodules()[0]),
0);
//if setwindowshookex fails.
if (hkeyboardhook == 0)
{
//returns the error code returned by the last unmanaged function called using platform invoke that has the dllimportattribute.setlasterror flag set.
int errorcode = marshal.getlastwin32error();
//do cleanup
stop(false, true, false);
//initializes and throws a new instance of the win32exception class with the specified error.
throw new win32exception(errorcode);
}
}
}
/// <summary>
/// stops monitoring both mouse and keyboard events and rasing events.
/// </summary>
/// <exception cref="win32exception">any windows problem.</exception>
public void stop()
{
this.stop(true, true, true);
}
/// <summary>
/// stops monitoring both or one of mouse and/or keyboard events and rasing events.
/// </summary>
/// <param name="uninstallmousehook"><b>true</b> if mouse hook must be uninstalled</param>
/// <param name="uninstallkeyboardhook"><b>true</b> if keyboard hook must be uninstalled</param>
/// <param name="throwexceptions"><b>true</b> if exceptions which occured during uninstalling must be thrown</param>
/// <exception cref="win32exception">any windows problem.</exception>
public void stop(bool uninstallmousehook, bool uninstallkeyboardhook, bool throwexceptions)
{
//if mouse hook set and must be uninstalled
if (hmousehook != 0 && uninstallmousehook)
{
//uninstall hook
int retmouse = unhookwindowshookex(hmousehook);
//reset invalid handle
hmousehook = 0;
//if failed and exception must be thrown
if (retmouse == 0 && throwexceptions)
{
//returns the error code returned by the last unmanaged function called using platform invoke that has the dllimportattribute.setlasterror flag set.
int errorcode = marshal.getlastwin32error();
//initializes and throws a new instance of the win32exception class with the specified error.
throw new win32exception(errorcode);
}
}
//if keyboard hook set and must be uninstalled
if (hkeyboardhook != 0 && uninstallkeyboardhook)
{
//uninstall hook
int retkeyboard = unhookwindowshookex(hkeyboardhook);
//reset invalid handle
hkeyboardhook = 0;
//if failed and exception must be thrown
if (retkeyboard == 0 && throwexceptions)
{
//returns the error code returned by the last unmanaged function called using platform invoke that has the dllimportattribute.setlasterror flag set.
int errorcode = marshal.getlastwin32error();
//initializes and throws a new instance of the win32exception class with the specified error.
throw new win32exception(errorcode);
}
}
}
/// <summary>
/// a callback function which will be called every time a mouse activity detected.
/// </summary>
/// <param name="ncode">
/// [in] specifies whether the hook procedure must process the message.
/// if ncode is hc_action, the hook procedure must process the message.
/// if ncode is less than zero, the hook procedure must pass the message to the
/// callnexthookex function without further processing and must return the
/// value returned by callnexthookex.
/// </param>
/// <param name="wparam">
/// [in] specifies whether the message was sent by the current thread.
/// if the message was sent by the current thread, it is nonzero; otherwise, it is zero.
/// </param>
/// <param name="lparam">
/// [in] pointer to a cwpstruct structure that contains details about the message.
/// </param>
/// <returns>
/// if ncode is less than zero, the hook procedure must return the value returned by callnexthookex.
/// if ncode is greater than or equal to zero, it is highly recommended that you call callnexthookex
/// and return the value it returns; otherwise, other applications that have installed wh_callwndproc
/// hooks will not receive hook notifications and may behave incorrectly as a result. if the hook
/// procedure does not call callnexthookex, the return value should be zero.
/// </returns>
private int mousehookproc(int ncode, int wparam, intptr lparam)
{
// if ok and someone listens to our events
if ((ncode >= 0) && (onmouseactivity != null))
{
//marshall the data from callback.
mousellhookstruct mousehookstruct = (mousellhookstruct)marshal.ptrtostructure(lparam, typeof(mousellhookstruct));
//detect button clicked
mousebuttons button = mousebuttons.none;
short mousedelta = 0;
switch (wparam)
{
case wm_lbuttondown:
//case wm_lbuttonup:
//case wm_lbuttondblclk:
button = mousebuttons.left;
break;
case wm_rbuttondown:
//case wm_rbuttonup:
//case wm_rbuttondblclk:
button = mousebuttons.right;
break;
case wm_mousewheel:
//if the message is wm_mousewheel, the high-order word of mousedata member is the wheel delta.
//one wheel click is defined as wheel_delta, which is 120.
//(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value
mousedelta = (short)((mousehookstruct.mousedata >> 16) & 0xffff);
//todo: x buttons (i havent them so was unable to test)
//if the message is wm_xbuttondown, wm_xbuttonup, wm_xbuttondblclk, wm_ncxbuttondown, wm_ncxbuttonup,
//or wm_ncxbuttondblclk, the high-order word specifies which x button was pressed or released,
//and the low-order word is reserved. this value can be one or more of the following values.
//otherwise, mousedata is not used.
break;
}
//double clicks
int clickcount = 0;
if (button != mousebuttons.none)
if (wparam == wm_lbuttondblclk || wparam == wm_rbuttondblclk) clickcount = 2;
else clickcount = 1;
//generate event
mouseeventargs e = new mouseeventargs(
button,
clickcount,
mousehookstruct.pt.x,
mousehookstruct.pt.y,
mousedelta);
//raise it
onmouseactivity(this, e);
}
//call next hook
return callnexthookex(hmousehook, ncode, wparam, lparam);
}
/// <summary>
/// a callback function which will be called every time a keyboard activity detected.
/// </summary>
/// <param name="ncode">
/// [in] specifies whether the hook procedure must process the message.
/// if ncode is hc_action, the hook procedure must process the message.
/// if ncode is less than zero, the hook procedure must pass the message to the
/// callnexthookex function without further processing and must return the
/// value returned by callnexthookex.
/// </param>
/// <param name="wparam">
/// [in] specifies whether the message was sent by the current thread.
/// if the message was sent by the current thread, it is nonzero; otherwise, it is zero.
/// </param>
/// <param name="lparam">
/// [in] pointer to a cwpstruct structure that contains details about the message.
/// </param>
/// <returns>
/// if ncode is less than zero, the hook procedure must return the value returned by callnexthookex.
/// if ncode is greater than or equal to zero, it is highly recommended that you call callnexthookex
/// and return the value it returns; otherwise, other applications that have installed wh_callwndproc
/// hooks will not receive hook notifications and may behave incorrectly as a result. if the hook
/// procedure does not call callnexthookex, the return value should be zero.
/// </returns>
private int keyboardhookproc(int ncode, int32 wparam, intptr lparam)
{
//indicates if any of underlaing events set e.handled flag
bool handled = false;
//it was ok and someone listens to events
if ((ncode >= 0) && (keydown != null || keyup != null || keypress != null))
{
//read structure keyboardhookstruct at lparam
keyboardhookstruct mykeyboardhookstruct = (keyboardhookstruct)marshal.ptrtostructure(lparam, typeof(keyboardhookstruct));
//raise keydown
if (keydown != null && (wparam == wm_keydown || wparam == wm_syskeydown))
{
keys keydata = (keys)mykeyboardhookstruct.vkcode;
keyeventargs e = new keyeventargs(keydata);
keydown(this, e);
handled = handled || e.handled;
}
// raise keypress
if (keypress != null && wparam == wm_keydown)
{
bool isdownshift = ((getkeystate(vk_shift) & 0x80) == 0x80 ? true : false);
bool isdowncapslock = (getkeystate(vk_capital) != 0 ? true : false);
byte[] keystate = new byte[256];
getkeyboardstate(keystate);
byte[] inbuffer = new byte[2];
if (toascii(mykeyboardhookstruct.vkcode,
mykeyboardhookstruct.scancode,
keystate,
inbuffer,
mykeyboardhookstruct.flags) == 1)
{
char key = (char)inbuffer[0];
if ((isdowncapslock ^ isdownshift) && char.isletter(key)) key = char.toupper(key);
keypresseventargs e = new keypresseventargs(key);
keypress(this, e);
handled = handled || e.handled;
}
}
// raise keyup
if (keyup != null && (wparam == wm_keyup || wparam == wm_syskeyup))
{
keys keydata = (keys)mykeyboardhookstruct.vkcode;
keyeventargs e = new keyeventargs(keydata);
keyup(this, e);
handled = handled || e.handled;
}
}
//if event handled in application do not handoff to other listeners
if (handled)
return 1;
else
return callnexthookex(hkeyboardhook, ncode, wparam, lparam);
}
}
}
希望本文所述对大家的c#程序设计有所帮助。
上一篇: 甲鱼的做法有哪些!
下一篇: IOS代码笔记之下拉选项cell