低级键盘钩子屏蔽Win键、Alt+Tab键的响应

该博客介绍了如何使用低级键盘钩子(Low Level Keyboard Hook)来屏蔽Windows操作系统的Win键、Alt+Tab键响应。通过创建DLL动态链接库,并设置全局低级键盘钩子,可以实现在用户按下这些键之前捕获并阻止其系统级响应。文章提供了Delphi语言的示例代码,展示了如何安装和卸载键盘钩子,以及处理键盘事件来禁用特定键的组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

低级键盘钩子屏蔽Win键、Alt+Tab键的响应

 

  如果你是基于Windows操作系统做系统集成的,你可能希望你的最终产品独占系统资源。你希望规范用户行为,比如你不希望用户通过按Ctrl+Alt+Del终止某个进程,或者按下Win键弹出开始菜单,或者按下Alt+Tab组合键切换到别的应用程序。笔者已有相关一篇文章《Win2K/NT下屏蔽Ctrl+Alt+Del的响应》,介绍了如何通过GINA编程接口屏蔽Ctrl+Alt+Del的响应。作为续篇,本文将继续介绍屏蔽Win键和Alt+Tab组合键的方法。    
  由于这些按键的响应是系统级的,我们不可能简单地通过某个程序来控制它们。因此,我们需要使用微软提供的另外一种编程接口——钩子(Hook)。大家可能已经对钩子很了解了(网上有很多介绍钩子技术和应用的文章)。简单来说,钩子是一种通过替换系统提供的标准接口来截获特定的事件(消息),最终达到改变或增强系统默认行为目的的技术。我们现在的任务,就是要在用户按下Win键或Alt+Tab组合键、但系统还没有响应之前截获它们,然后改变系统的默认行为。很显然,我们要做一个全局钩子(钩子函数放在独立的DLL中实现),而且是个低级键盘钩子(Low  Level  Keyboard    hook)。 

  第一步,钩子DLL的实现。我们首先要定义一个全局数据区(记住这是一个全局钩子),如下(放在cpp文件的上头): 

  #pragma  data_seg("mydata") 
  HHOOK            glhHook            =  NULL;                        //  安装的鼠标钩子句柄 
  HINSTANCE    glhInstance    =  NULL;              //  DLL实例句柄 
  #pragma  data_seg() 

  然后在.def文件中声明这个数据区,如下: 
  SECTIONS  
  mydata  READ  WRITE  SHARED 

  当这个DLL被某个进程载入时,程序从WinMain进入,此时我们需要把模块句柄保存下来,如下: 
  glhInstance  =  (HINSTANCE)  hModule; 

  接下去,我们就要定义两个导出函数,以及钩子的处理函数。我们重点看一下这个钩子处理函数(另外两个导出函数比较简单,只是通过调用SetWindowsHookEx和UnhookWindowsHookEx实现安装/卸载钩子函数;只需注意SetWindowsHookEx第一个参数为WH_KEYBOARD_LL,第四个参数为0)。
_________________________________________________________________________________________

DELPHI例程:
和Alt+Esc系统功能键
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
{按键消息的结构,Delphi中也没有,自己定义吧。这也就是我为什么说用C写
这样的程序更好的原因之一。还必须注意的是这个结构在Windows NT 4 sp3以上系统中才能使用}
tagKBDLLHOOKSTRUCT = packed record
  vkCode: DWORD;//虚拟键值
  scanCode: DWORD;//扫描码值(没有用过,我也不懂^_^)
  {一些扩展标志,这个值比较麻烦,MSDN上说得也不太明白,但是
  根据这个程序,这个标志值的第六位数(二进制)为1时,Alt键按下为0}
  flags: DWORD;
  time: DWORD;//消息时间戳
  dwExtraInfo: DWORD;//和消息相关的扩展信息
end;
  KBDLLHOOKSTRUCT = tagKBDLLHOOKSTRUCT;
  PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
//这个是低级键盘钩子的索引值,Delphi中没有,必须自己定义
const WH_KEYBOARD_LL = 13;
//定义一个常量好和上面那个结构中的flags比较而得出Alt键是否按下
const LLKHF_ALTDOWN = $20;
var
  Form1: TForm1;
  hhkLowLevelKybd: HHOOK;
implementation
{
功能:低级键盘钩子的回调函数,在里面过滤消息
参数: nCode   是Hook的标志
     WParam  表示消息的类型
     LParam  是一个指向我们在上面定义的那个结构KBDLLHOOKSTRUCT的指针
返回值:如果不是0的话,Windows就把这个消息丢掉,程序就不会再收到这个消息了。
}
function LowLevelKeyboardProc(nCode: Integer;
  WParam: WPARAM;LParam: LPARAM):LRESULT; stdcall;
var
  fEatKeystroke: BOOL;
  p: PKBDLLHOOKSTRUCT;
begin
  Result := 0;
  fEatKeystroke := FALSE;
  p := PKBDLLHOOKSTRUCT (lParam);
  //nCode值为HC_ACTION时表示WParam和LParam参数包含了按键消息
  if (nCode = HC_ACTION) then
  begin
  //拦截按键消息并测试是否是Ctrl+Esc、Alt+Tab和Alt+Esc功能键
    case wParam of
      WM_KEYDOWN,
      WM_SYSKEYDOWN,
      WM_KEYUP,
      WM_SYSKEYUP:
           fEatKeystroke :=(P.vkCode = VK_Lwin) or (P.vkCode = VK_Rwin)or (P.vkCode = VK_apps)or
          ((p.vkCode = VK_TAB) and ((p.flags and LLKHF_ALTDOWN) <> 0)) or
          ((p.vkCode = VK_ESCAPE) and ((p.flags and LLKHF_ALTDOWN) <> 0)) or
          ((p.vkCode = VK_CLEAR) and ((p.flags and LLKHF_ALTDOWN) <> 0)) or
          ((p.vkCode = VK_ESCAPE) and ((GetKeyState(VK_CONTROL) and $8000) <> 0));
    end;
  end;
  if fEatKeystroke = True then
    Result := 1;
  if nCode <> 0 then
     Result := CallNextHookEx(0, nCode, wParam, lParam);
end;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
  //设置低级键盘钩子
  hhkLowLevelKybd := SetWindowsHookExW(WH_KEYBOARD_LL,
    LowLevelKeyboardProc, Hinstance, 0);
  if hhkLowLevelKybd <> 0 then
    MessageBox(0, '低级键盘钩子设置成功!', '提示', MB_OK);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
  //卸载低级键盘钩子
  if hhkLowLevelKybd <> 0 then
  begin
    UnhookWindowsHookEx(hhkLowLevelKybd);
    MessageBox(0, '低级键盘钩子卸载成功!', '提示', MB_OK);
  end;
end;
end.   




 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值