禁用鼠标与键盘有两种方法:
- 直接调用禁用API(缺点:按Ctrl+alt+delete,禁用会失效)
① 帮助类
public class BlockHelper
{
private static Logger<BlockHelper> log = new Logger<BlockHelper>();
private const int SE_PRIVILEGE_ENABLED = 0x00000002;
private const int TOKEN_QUERY = 0x00000008;
private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
public static bool off()
{
if (IsAdministrator())
{
BlockInput(true);//锁定鼠标及键盘
return true;
}
else
return false;
}
public static bool on()
{
if (IsAdministrator())
{
BlockInput(false);//解除键盘鼠标锁定
return true;
}
else
return false;
}
/// <summary>
/// 是否是管理员权限
/// </summary>
/// <returns></returns>
public static bool IsAdministrator()
{
WindowsIdentity current = WindowsIdentity.GetCurrent();
WindowsPrincipal windowsPrincipal = new WindowsPrincipal(current);
return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator);
}
[DllImport("user32.dll")]
static extern void BlockInput(bool Block);
}
- 使用钩子(HOOK)截取信息进行处理
钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
函数:HHOOK WINAPI SetWindowsHookEx(
__in int idHook, \钩子类型
__in HOOKPROC lpfn, \回调函数地址
__in HINSTANCE hMod, \实例句柄
__in DWORD dwThreadId); \线程ID
其中ipfn是回调函数
LRESULT CALLBACK HookProc
(
int nCode,
WPARAM wParam,
LPARAM lParam
);
HookProc是回调函数名。
**注:WPARAM,消息响应机制
wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数:
一个是WORD类型的16位整型变量;另一个是LONG类型的32位整型变量。因此根据匈牙利命名法,16位的变量就被命名为wParam, 32位的变量就被命名为lParam。
到了Win32API中,原来的16位变量也被扩展为32位,因此此时wParam和lParam的大小完全相同。
在Win32API的早期,为了保证和Win16API的代码可移植性MS定义了WPARAM和LPARAM两个宏。
当时保留了w前缀的原因一方面是由于WPARAM宏也以W开头,还有也因为要提醒程序员注意到可移植性,当然到了现在Win16早已退出历史舞台,这个前缀也就约定俗成的沿用下来了。**
具体代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HookTest
{
public class HookKeyBoard
{
private enum HookType
{
WH_CALLWNDPROC = 4, //安装在系统将消息发送到目标窗口过程之前监视邮件的挂钩过程。
WH_CALLWNDPROCRET = 12, //安装在目标窗口过程处理完邮件后监视消息的挂钩过程。
WH_CBT = 5, //安装接收对 CBT 应用程序有用的通知的挂钩过程。
WH_DEBUG = 9, //安装用于调试其他挂钩过程的挂钩过程。
WH_FOREGROUNDIDLE = 11, //安装将在应用程序的前景线程即将变为空闲时调用的挂钩过程。此挂钩对于在空闲时间执行低优先级任务非常有用。
WH_GETMESSAGE = 3, //安装用于监视张贴到消息队列的邮件的挂钩过程。
WH_HARDWARE = 8, //安装一个挂接过程, 用于张贴以前由 WH_JOURNALRECORD 挂钩过程记录的消息。
WH_JOURNALPLAYBACK = 1, //安装一个挂接过程, 用于张贴以前由 WH_JOURNALRECORD 挂钩过程记录的消息。
WH_JOURNALRECORD = 0,//安装用于记录张贴到系统消息队列中的输入消息的挂钩过程。
WH_KEYBOARD = 2,//安装监视击键消息的挂钩过程。
WH_MOUSE = 7,//安装监视鼠标消息的挂钩过程。
WH_MSGFILTER = (-1), //安装一个钩子过程, 用于监视对话框、消息框、菜单或滚动条中由于输入事件而生成的消息。
WH_SHELL = 10,//安装接收对 shell 应用程序有用的通知的挂钩过程。
WH_SYSMSGFILTER = 6,//安装一个钩子过程, 用于监视对话框、消息框、菜单或滚动条中由于输入事件而生成的消息。挂钩过程监视与调用线程在同一桌面上的所有应用程序的这些消息。
WH_KEYBOARD_LL = 13,//安装用于监视低级键盘输入事件的挂钩过程。
WH_MOUSE_LL = 14,//安装用于监视低级别鼠标输入事件的挂钩过程。
}
private const int WM_KEYUP = 0X101;
private const int WM_SYSKEYUP = 0X105;
private delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
private int KeyHook;
private int MouseHook;
public event KeyEventHandler keyeventhandler;
[StructLayout(LayoutKind.Sequential)]
private class KeyBoardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
//设置钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);// 钩子类型 回调函数地址 实例句柄 线程ID
//卸载钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook); //要移除的钩子的句柄。此参数是由以前对 SetWindowsHookEx 的调用获取的挂钩句柄。
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name); //获取进程句柄
[DllImport("user32", EntryPoint = "GetMessage")]
public static extern int GetMessage( //调用线程的消息队列里取得一个消息并将其放于指定的结构.此函数可取得与指定窗口联系的消息和由PostThreadMessage寄送的线程消息
out tagMSG lpMsg,//指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
IntPtr hwnd,//取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。
int wMsgFilterMin,//指定被检索的最小消息值的整数。
int wMsgFilterMax//指定被检索的最大消息值的整数。
);
[DllImport("user32", EntryPoint = "DispatchMessage")]
public static extern int DispatchMessage(ref tagMSG lpMsg); //函数将键盘消息转化
[DllImport("user32", EntryPoint = "TranslateMessage")]
public static extern int TranslateMessage(ref tagMSG lpMsg); //函数将消息传给窗体函数去处理
public struct tagMSG
{
public int hwnd;
public uint message;
public int wParam;
public long lParam;
public uint time;
public int pt;
}
public void InstallHook(Form form)
{
if (KeyHook.Equals(0))
{
HookProc hp = new HookProc(KeyMouseHookProc);
KeyHook = SetWindowsHookEx((int)HookType.WH_KEYBOARD_LL,
hp,
GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0);
MouseHook = SetWindowsHookEx((int)HookType.WH_MOUSE_LL, hp,
GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0);
}
if (KeyHook.Equals(0) && MouseHook.Equals(0)) {
Hook_Clear();
throw new Exception("安装钩子失败");
}
}
/// <summary>
/// 自己想要的信息处理
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
private int KeyMouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (keyeventhandler != null && nCode >= 0) {
KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));
if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP)) {
Keys keyData = (Keys)kbh.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
keyeventhandler(this, e);
}
}
return 1;
}
//取消钩子事件
public void Hook_Clear()
{
bool retKeyboard = true;
if (!KeyHook.Equals(0) && !MouseHook.Equals(0))
{
retKeyboard = UnhookWindowsHookEx(KeyHook);
if (retKeyboard) retKeyboard = UnhookWindowsHookEx(MouseHook);
}
//如果去掉钩子失败.
if (!retKeyboard) throw new Exception("UnhookWindowsHookEx failed.");
}
}
}
② 窗体测试
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HookTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private HookKeyBoard hkb = null;
private void Form1_Load(object sender, EventArgs e)
{
DisabledMouseKey();
}
private void DisabledMouseKey()
{
hkb = new HookKeyBoard();
hkb.keyeventhandler += new KeyEventHandler(keyhandler);
hkb.InstallHook(this);
HookKeyBoard.tagMSG Msgs;
while (HookKeyBoard.GetMessage(out Msgs, IntPtr.Zero, 0, 0) > 0)
{
HookKeyBoard.TranslateMessage(ref Msgs);
HookKeyBoard.DispatchMessage(ref Msgs);
}
}
private void EnableMouseKey()
{
hkb.Hook_Clear();
}
/// <summary>
/// 设立一个口子,以防禁用完还得重启
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void keyhandler(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyData.ToString() == "a" || e.KeyData.ToString() == "A")
{
hkb.Hook_Clear();
}
}
}
}