在windows上写游戏时有时想屏蔽键盘上的某些键,比如"Win"键以防止以弹出开始菜单导致游戏窗口失焦或全屏切出.对于那种没有失焦处理的游戏遇到PK时可能损失是极大的,这对玩家来说是不可接受的.这里我们用Pascal来介绍关键性代码,代码很简单,效果却很好.(代码摘自遥远年代的个人作品中的一部分).
首先我们需要写一个单独的Dll,以实现全局挂钩.
var
hHk:HHOOK;
type
PKBDLLHOOKSTRUCT=^KBDLLHOOKSTRUCT;
KBDLLHOOKSTRUCT=record
vkCode:DWORD;
ScanCode:DWORD;
Flags:DWORD;
Time:DWORD;
dwExtraInfo:DWORD;
end;
function DisableWinKey:Boolean; Stdcall; Export;
begin
if hHk=0 then
begin
hHk:=SetWindowsHookEx(13,@keyHookProc,HInstance,0);
Result:=True;
end
else
Result:=False;
end;
function EnableWinKey:Boolean; Stdcall; Export;
begin
if hHk<>0 then
begin
UnhookWindowsHookEx(hHk);
hHk:=0;
Result:=True;
end
else
Result:=False;
end;
以上实现对键盘Hook,然后关键的地方就是对按键的过滤:
function keyHookProc(nCode:Integer;WParam:WParam;LParam:LParam):LRESULT; Stdcall;
var
p:PKBDLLHOOKSTRUCT;
y:Integer;
begin
if nCode<0 then
Result:=CallNextHookEx(hHk,nCode,WParam,LParam)
else
begin
y:=0;
case WParam of
WM_KEYDOWN,WM_SYSKEYDOWN://按键后判断所按键
begin
p:=PKBDLLHOOKSTRUCT(LParam);
if p^.vkCode=VK_LWIN then
y:=1;
if p^.vkCode=VK_RWIN then
y:=1;
end;
WM_KEYUP,WM_SYSKEYUP://松开按键后判断所按键
begin
p:=PKBDLLHOOKSTRUCT(LParam);
if p^.vkCode=VK_LWIN then
y:=1;
if p^.vkCode=VK_RWIN then
y:=1;
end;
end;
if y=1 then
Result:=1//如果为WIN功能键则屏蔽
else
Result:=CallNextHookEx(hHk,nCode,WParam,LParam);//继续下一个钩子
end
end;
很简单不是吗,接下来导出二个fun
exports
EnableWinKey,
DisableWinKey;
我们编译这个dpr,得到一个dll文件,接下来我们只需要一个host主程序来使用这个dll,这个就自由发挥了,这里给出我的一个简单示例:
首先我们定义导出范式
type
DisableWinKeyProc=function:Boolean;stdcall;
EnableWinKeyProc=function:Boolean;stdcall;
然后声明
DisWinKey:DisableWinKeyProc;
EnaWinKey:EnableWinKeyProc;
const
DllFileName='DisableWinKey.dll';//你自己的dll文件名
接下来我们动态载入Dll
DllHandle:=LoadLibrary(DllFileName);
if DllHandle<>0 then
begin
@DisWinKey:=GetProcAddress(DllHandle,'DisableWinKey');
@EnaWinKey:=GetProcAddress(DllHandle,'EnableWinKey');
end;
OK,现在我们就可以调用,看看效果吧:)
注意Host程序关闭前记得一定要释放,否则Win键不会自动恢复.
EnaWinKey();
FreeLibrary(DllHandle);