| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnKeyBlocker;
- {* |<PRE>
- ================================================================================
- * 软件名称:不可视工具组件包
- * 单元名称:通过键盘钩子屏蔽系统键的组件
- * 单元作者:匿名
- * 移 植:刘啸 (liuxiao@cnpack.org)
- * 备 注:此组件通过实现键盘钩子来屏蔽某些系统键,但 Ctrl+Alt+Del 组合键可能
- * 因为系统自身处理原因而无法屏蔽。
- * 开发平台:PWinXP + Delphi 7.0 (Build 8.1)
- * 兼容测试:PWin2003 + Delphi 7.0 (Build 8.1)
- * 本 地 化:该单元中无字符串资源
- * 单元标识:$Id$
- * 修改记录:2008.10.24 v1.1
- * 加入一简陋事件
- * 2008.05.29 v1.0
- * 移植单元
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- SysUtils, Classes, windows, ShlObj, Registry, Shellapi, Messages;
- type
- TCnBlockKeyEvent = procedure(VirtualKey: Cardinal) of object;
- TCnKeyBlocker = class(TComponent)
- private
- FBCAD: Boolean;
- FBAT: Boolean;
- FBCE: Boolean;
- FEnabled: Boolean;
- FBAE: Boolean;
- FBCR: Boolean;
- FBCK: Boolean;
- FBP: Boolean;
- FBS: Boolean;
- FCKC: Cardinal;
- FBWA: Boolean;
- FBCAE: Boolean;
- FOnBlockKey: TCnBlockKeyEvent;
- procedure SetBCAD(const Value: Boolean);
- procedure SetBAT(const Value: Boolean);
- procedure SetBCE(const Value: Boolean);
- procedure SetEnabled(const Value: Boolean);
- procedure SetBAE(const Value: Boolean);
- procedure SetBCK(const Value: Boolean);
- procedure SetBCR(const Value: Boolean);
- procedure SetBP(const Value: Boolean);
- procedure SetBS(const Value: Boolean);
- procedure SetBWA(const Value: Boolean);
- procedure SetBCAE(const Value: Boolean);
- protected
- procedure UpdateKeyBlock;
- procedure DoBlock(VirtualKey: Cardinal);
- property BlockCtrlAltDelete: Boolean read FBCAD write SetBCAD;
- {* 是否屏蔽 Ctrl+Alt+Delete 键,此属性可能无法工作,暂时不开放}
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- published
- property BlockAltTab: Boolean read FBAT write SetBAT;
- {* 是否屏蔽 Alt+Tab 键}
- property BlockCtrlEsc: Boolean read FBCE write SetBCE;
- {* 是否屏蔽 Ctrl+Esc 键}
- property BlockAltEsc: Boolean read FBAE write SetBAE;
- {* 是否屏蔽 Alt+Esc 键}
- property BlockCtrlEnter: Boolean read FBCR write SetBCR;
- {* 是否屏蔽 Ctrl+Enter 键}
- property BlockSleep: Boolean read FBS write SetBS;
- {* 是否屏蔽 Sleep 休眠键}
- property BlockPower: Boolean read FBP write SetBP;
- {* 是否屏蔽 Power 电源键}
- property BlockWinApps: Boolean read FBWA write SetBWA;
- {* 是否屏蔽 Windows 键}
- property BlockCtrlAltEnter: Boolean read FBCAE write SetBCAE;
- {* 是否屏蔽 Ctrl+Alt+Enter 键}
- property CustomKeyCode: Cardinal read FCKC write FCKC default 0;
- {* 自定义的屏蔽键}
- property BlockCustomKey: Boolean read FBCK write SetBCK;
- {* 是否屏蔽自定义键}
- property Enabled: Boolean read FEnabled write SetEnabled default False;
- {* 是否使能屏蔽功能}
- property OnBlockKey: TCnBlockKeyEvent read FOnBlockKey write FOnBlockKey;
- {* 屏蔽键时触发的事件,由于复杂性,参数中只指明虚拟键,并且由于挂接机制本身
- 的机制,此事件无 Sender。}
- end;
- implementation
- const
- LLKHF_ALTDOWN = KF_ALTDOWN shr 8;
- WH_KEYBOARD_LL = 13;
- type
- PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
- KBDLLHOOKSTRUCT = packed record
- vkCode: DWORD;
- scanCode: DWORD;
- flags: DWORD;
- Time: DWORD;
- dwExtraInfo: DWORD;
- end;
- var
- hhkNTKeyboard: HHOOK = 0;
- aBCAD: Boolean = False;
- aBWA: Boolean = False;
- aBCE: Boolean = False;
- aBAT: Boolean = False;
- aBAE: Boolean = False;
- aBCR: Boolean = False;
- aBCAE: Boolean = False;
- aBP: Boolean = False;
- aaBS: Boolean = False;
- aBCK: Boolean = False;
- aCKC: Cardinal = 0;
- FKeyBlocker: TCnKeyBlocker = nil;
- { TCnKeyBlocker }
- constructor TCnKeyBlocker.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FKeyBlocker := Self;
- end;
- procedure EnableCTRLALTDEL(YesNo: Boolean);
- const
- sRegPolicies = '\Software\Microsoft\Windows\CurrentVersion\Policies';
- begin
- with TRegistry.Create do
- try
- RootKey := HKEY_CURRENT_USER;
- if OpenKey(sRegPolicies + '\System\', True) then
- begin
- case YesNo of
- False:
- begin
- WriteInteger('DisableTaskMgr', 1); //任务管理
- WriteInteger('DisableLockWorkstation', 1); //用户锁定计算机
- WriteInteger('DisableChangePassword', 1); //用户更改口令
- end;
- True:
- begin
- WriteInteger('DisableTaskMgr', 0);
- WriteInteger('DisableLockWorkstation', 0);
- WriteInteger('DisableChangePassword', 0);
- end;
- end;
- end;
- CloseKey;
- if OpenKey(sRegPolicies + '\Explorer\', True) then
- begin
- case YesNo of
- False:
- begin
- WriteInteger('NoChangeStartMenu', 1); //开始菜单
- WriteInteger('NoClose', 1); // 关闭系统菜单
- WriteInteger('NoLogOff', 1); //注销菜单
- WriteInteger('NoRun', 1); //运行菜单
- WriteInteger('NoSetFolders', 1); //设置菜单
- end;
- True:
- begin
- WriteInteger('NoChangeStartMenu', 0);
- WriteInteger('NoClose', 0);
- WriteInteger('NoLogOff', 0);
- WriteInteger('NoRun', 0);
- end;
- end;
- end;
- CloseKey;
- finally
- Free;
- end;
- end;
- function LowLevelKeyboardFunc(nCode: INTEGER; w_Param: WPARAM;
- l_Param: LPARAM): LRESULT; stdcall;
- var
- boolKey: Boolean;
- p: PKBDLLHOOKSTRUCT;
- const
- VK_SLEEP = $5F;
- VK_POWER = $5E;
- begin
- boolKey := False;
- p := nil;
- if nCode = HC_ACTION then
- begin
- case w_Param of
- WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP:
- begin
- p := PKBDLLHOOKSTRUCT(l_Param);
- //---------!-~------------------------------------------------
- { if ((GetAsyncKeyState(VK_RBUTTON) and $8000) <> 0) then boolKey := True;
- if (CHAR(p.vkCode) >= '!') and (CHAR(p.vkCode) <= '~') and
- ((GetKeyState(VK_CONTROL) and $8000) <> 0) then boolKey := True;
- if (p.vkCode = VK_SPACE) and
- ((GetKeyState(VK_CONTROL) and $8000) <> 0) then boolKey := True; }
- //---------F1-F12 ----------------------------------------------
- { if (p.vkCode = VK_F1) or (p.vkCode = VK_F2) or (p.vkCode = VK_F3) or
- (p.vkCode = VK_F4) or (p.vkCode = VK_F5) or (p.vkCode = VK_F6) or
- (p.vkCode = VK_F7) or (p.vkCode = VK_F8) or (p.vkCode = VK_F9) or
- (p.vkCode = VK_F10) or (p.vkCode = VK_F11) or (p.vkCode = VK_F12) then
- boolKey := True;
- if ((p.vkCode = VK_F1) or (p.vkCode = VK_F2) or (p.vkCode = VK_F3) or
- (p.vkCode = VK_F4) or (p.vkCode = VK_F5) or (p.vkCode = VK_F6) or
- (p.vkCode = VK_F7) or (p.vkCode = VK_F8) or (p.vkCode = VK_F9) or
- (p.vkCode = VK_F10) or (p.vkCode = VK_F11) or (p.vkCode = VK_F12)) and
- (((GetKeyState(VK_MENU) and $8000) <> 0) or ((GetKeyState(VK_CONTROL) and $8000) <> 0)
- or ((GetKeyState(VK_SHIFT)and$8000) <> 0)) then
- boolKey := True; }
- //-------系统热键---------------------------------------------
- //WIN(Left or Right)+APPS
- if aBWA then
- begin
- if (p.vkCode = VK_LWIN) or (p.vkCode = VK_RWIN) or (p.vkCode = VK_APPS) then
- boolKey := True;
- end;
- //CTRL+ESC
- if aBCE then
- begin
- if (p.vkCode = VK_ESCAPE) and ((GetKeyState(VK_CONTROL) and $8000) <> 0) then
- boolKey := True;
- end;
- //ALT+TAB
- if aBAT then
- begin
- if (p.vkCode = VK_TAB) and ((GetAsyncKeyState(VK_MENU) and $8000) <> 0) then
- boolKey := True;
- end;
- //ALT+ESC
- if aBAE then
- begin
- if (p.vkCode = VK_ESCAPE) and ((p.flags and LLKHF_ALTDOWN) <> 0) then
- boolKey := True;
- end;
- //CTRL+ENTER
- if aBCR then
- begin
- if (p.vkCode = VK_RETURN) and ((GetKeyState(VK_CONTROL) and $8000) <> 0) then
- boolKey := True;
- end;
- //CTRL+ALT+ENTR
- if aBCAE then
- begin
- if (p.vkCode = VK_RETURN) and ((p.flags and LLKHF_ALTDOWN) <> 0)
- and ((GetKeyState(VK_CONTROL) and $8000) <> 0) then
- boolKey := True;
- end;
- //POWER
- if aBP then
- begin
- if (p.vkCode = VK_POWER) then
- boolKey := True;
- end;
- //SLEEP
- if aaBS then
- begin
- if (p.vkCode = VK_SLEEP) then
- boolKey := True;
- end;
- //Custom
- if aBCK then
- begin
- if (p.vkCode = aCKC) then
- boolKey := True;
- end;
- //如果有其他要屏闭的键,添加在此处
- end;
- end;
- end;
- //捕获这些组合键,按键消息由自己处理,必须返回 1
- if boolKey and (p <> nil) then
- begin
- FKeyBlocker.DoBlock(p.vkCode);
- Result := 1;
- Exit;
- end;
- //其他的按键,交由别的线程处理(过滤)
- Result := CallNextHookEx(0, nCode, w_Param, l_Param);
- end;
- destructor TCnKeyBlocker.Destroy;
- begin
- Enabled := False;
- FKeyBlocker := nil;
- inherited Destroy;
- end;
- procedure TCnKeyBlocker.DoBlock(VirtualKey: Cardinal);
- begin
- if Assigned(FOnBlockKey) then
- FOnBlockKey(VirtualKey);
- end;
- procedure TCnKeyBlocker.SetBAE(const Value: Boolean);
- begin
- FBAE := Value;
- aBAE := FBAE;
- end;
- procedure TCnKeyBlocker.SetBAT(const Value: Boolean);
- begin
- FBAT := Value;
- aBAT := FBAT;
- end;
- procedure TCnKeyBlocker.SetBCAD(const Value: Boolean);
- begin
- FBCAD := Value;
- aBCAD := FBCAD;
- end;
- procedure TCnKeyBlocker.SetBCAE(const Value: Boolean);
- begin
- FBCAE := Value;
- aBCAE := FBCAE;
- end;
- procedure TCnKeyBlocker.SetBCE(const Value: Boolean);
- begin
- FBCE := Value;
- aBCE := FBCE;
- end;
- procedure TCnKeyBlocker.SetBCK(const Value: Boolean);
- begin
- FBCK := Value;
- aBCK := FBCK;
- end;
- procedure TCnKeyBlocker.SetBCR(const Value: Boolean);
- begin
- FBCR := Value;
- aBCR := FBCR;
- end;
- procedure TCnKeyBlocker.SetBP(const Value: Boolean);
- begin
- FBP := Value;
- aBP := FBP;
- end;
- procedure TCnKeyBlocker.SetBS(const Value: Boolean);
- begin
- FBS := Value;
- aaBS := FBS;
- end;
- procedure TCnKeyBlocker.SetBWA(const Value: Boolean);
- begin
- FBWA := Value;
- aBWA := FBWA;
- end;
- procedure TCnKeyBlocker.SetEnabled(const Value: Boolean);
- begin
- FEnabled := Value;
- UpdateKeyBlock;
- end;
- procedure TCnKeyBlocker.UpdateKeyBlock;
- begin
- if csDesigning in ComponentState then
- Exit;
- case FEnabled of
- True:
- begin
- if hhkNTKeyboard <> 0 then
- Exit;
- hhkNTKeyboard := SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardFunc, HInstance, 0);
- if FBCAD then
- begin
- EnableCTRLALTDEL(False);
- SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
- end;
- end;
- False:
- begin
- if hhkNTKeyboard = 0 then
- Exit;
- UnhookWindowsHookEx(hhkNTKeyboard); // 卸载钩子
- EnableCTRLALTDEL(True);
- SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
- hhkNTKeyboard := 0;
- end;
- end;
- end;
- end.
|