前言
一些学生要求上位机程序启动后可以禁用Win组合,防止操作人员无操作或退出程序。
实现思路
首先,我们需要了解键盘PC工作原理,Windows系统的所有操作都是基于消息机制的,也就是说,我们键盘上的每个按钮通常都是Windows底部发送消息,所以如果你想屏蔽按钮或功能,最直接的方法是拦截消息。
先说实现思路,就是用钩子Hook,我们之前讲扫码枪的时候也讲过这个。
钩子原理
钩子是操作系统信息处理的机制。通过钩子,应用程序可以安装一个钩子回调过程来调用系统,以监控系统中的信息队列。在这些信息到达目标窗口之前处理它们。
钩子特点
-
钩函数会降低操作系统的性能,因为它会增加系统处理每个信息的成本。
-
操作系统支持各种类型的钩子,每种类型都提供了其独特的信息处理机制。
-
对于各种类型的钩子,系统保持独立的钩链,钩链是指向用户提供的回调函数钩过程的链表指针。
-
尽量避免大量使用钩子。一般在需要时安装,使用后尽快卸载。
代码实现
下面直接贴代码,主要是在键盘钩处理中添加一些需要截获的信息。
publicclassHook:IDisposable { publicdelegateintHookProc(intnCode,intwParam,IntPtrlParam); staticinthHook=0; publicconstintWH_KEYBOARD_LL=13; HookProcKeyBoardHookProcedure; [StructLayout(LayoutKind.Sequential)] publicclassKeyBoardHookStruct { publicintvkCode; publicintscanCode; publicintflags; publicinttime; publicintdwExtraInfo; } [DllImport("user32.dll")] publicstaticexternintSetWindowsHookEx(intidHook,HookProclpfn,IntPtrhInstance,intthreadId); [DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] publicstaticexternboolUnhookWindowsHookEx(intidHook); [DllImport("user32.dll")] publicstaticexternintCallNextHookEx(intidHook,intnCode,intwParam,IntPtrlParam); [DllImport("kernel32.dll")] publicstaticexternIntPtrGetModuleHandle(stringname); publicvoidStart() { //安装键盘钩 if(hHook==0) { KeyBoardHookProcedure=newHookProc(KeyBoardHookProc); hHook=SetWindowsHookEx(WH_KEYBOARD_LL,KeyBoardHookProcedure,GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),0); /. if(hHook==0) Close(); else { RegistryKeykey=Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System",true); &nsp; if (key == null)//如果该项不存在的话,则创建该项
key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System");
key.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord);
key.Close();
}
}
}
public void Close()
{
bool retKeyboard = true;
if (hHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hHook);
hHook = 0;
}
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
if (key != null)
{
key.DeleteValue("DisableTaskMgr", false);
key.Close();
}
}
public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));
if (kbh.vkCode == 91) // 截获左win(开始菜单键)
return 1;
if (kbh.vkCode == 92)// 截获右win
return 1;
if (kbh.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control) //截获Ctrl+Esc
return 1;
if (kbh.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt) //截获alt+f4
return 1;
if (kbh.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt) //截获alt+tab
return 1;
if (kbh.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Shift) //截获Ctrl+Shift+Esc
return 1;
if (kbh.vkCode == (int)Keys.Space && (int)Control.ModifierKeys == (int)Keys.Alt) //截获alt+空格
return 1;
if (kbh.vkCode == 241) //截获F1
return 1; if (kbh.vkCode == (int)Keys.Control && kbh.vkCode == (int)Keys.Alt && kbh.vkCode == (int)Keys.Delete)
return 1;
if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt + (int)Keys.Delete) //截获Ctrl+Alt+Delete
return 1;
if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Shift) //截获Ctrl+Shift
return 1;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
public void Dispose()
{
Close();
}
}
钩子使用
使用方法也很简单,在窗体初始化的时候,采用无边框并最大化窗体,然后启动钩子。
private Hook hook;
public FrmMain()
{
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.TopMost = true;
hook = new Hook();
hook.Start();
this.FormClosing += new FormClosingEventHandler(FrmMain_FormClosing);
}
在窗体关闭事件里关闭钩子,钩子使用一定要及时关闭。
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
hook.Close();
}
这样运行程序后,如果没有提供关闭程序的入门,似乎就只能重启系统了,大家测试时要注意保存电脑现有程序及文件。
需要相关的资料可以私信我,或者评论区留言