问题似乎解决了,我长出了一个口气,上面的pMsg.ParamL就是VirtualKey Code虚拟键码,就等于OnKeyDown中的Key那个参数。
得到虚拟键码就好办了,然后我为了监视工作跟加一目了然,当然是把这个键码转换成字符串,比如键码91就得到WIN这个字符串(这个 WIN 让我吃尽苦头,后面会详细解释原因的),27就得到ESC....等等。工作太繁琐,那以前的那个KeySpy来看,哈哈,它定义了长的常量数组,都写好了,照搬过来。成了,这里我说明一下,先开始不知道那段汇编是干吗的,于是照搬。
这段汇编
{asm
in al, 60h
mov Key, al
end; }
实际上是KeySpy用来监视键盘的核心,它用一个Timer去查询当前键盘中的扫描码,就是当前被按下的那些键,而我呢?弄巧成拙了,把它当成将虚拟键码转换成扫描码的过程,当然也可以这么用,因为当时这个键确实被按下了。后来我把KeySpy中的这段汇编给去掉了,改成我的MapVirtualKey函数,看它的定义--MapVirtualKey(虚拟键码,标志):扫描码; 一看就知道返回值是以虚拟键码为前提的。KeySpy一被这样改就变成了DoNothing控件。而我的控件可不是用这原理哦,嘿嘿,因为我在调用MapVirtualKey之前已经得到正确的虚拟键码了!!
关于Win的烦恼篇:
(抱歉,有点灌水嫌疑,请正在看的朋友耐心点),用了SetWindowsHookex(WH_JOURNALRECORD, KeyBoardHook, Hinstance, 0);和MapVirtualKey蛮以为可以高枕无忧乐,98和2000都可以用,哈哈!!完事咯!!我马上编了一个例子来测试它,它工作的非常好。突然,我莫名其妙的按下了WIN键,再按其它的键,发现它已经失效了,就是只要我按下了WIN,这个钩子就不起作用了。我开始查错。。。。调试。。。查错。。。。。(叮叮光光,修理它),还是不行,不论怎样避免都不行,看来是机制问题。没办法查帮助,现在看来帮助真是个好东西啊,打开帮助看WH_JOURNALRECORD这种HOOK的说明,下面引用引起这问题的一段帮助中的原文说明:
If the user presses CTRL+ESC or CTRL+ALT+DEL during journal playback, the system stops the playback, unhooks the journal playback procedure, and posts a WM_CANCELJOURNAL message to the journaling application.
看明白了吧?只要用户按了CTRL+ESC or CTRL+ALT+DEL ,所有的journal playback 都会被UnHook掉,CTRL+ESC =WIN键,气死我了!!!
哎,没办法,看来我在这条路上是死定了。。。。。(后记:这个问题也已经被我解决,不过方法吗,不值得提倡和推广,所以就不拿出来丢丑了)
procedure Register;
begin
RegisterComponents('WalkSlowly', [TExKeySpy]);
end;
{ TExKeySpy }
constructor TExKeySpy.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabled := False;
FOwnerWin := 0;
FForm := TForm(AOwner);
if FForm <> nil then
begin
FOldFormMethod := FForm.WindowProc;
OwnerHandle := FForm.Handle;
FForm.WindowProc := Win_Proc;
end;
end;
destructor TExKeySpy.Destroy;
begin
inherited Destroy;
if FEnabled then
begin
UnHookWindowsHookEx(hNextHookProc);
hNextHookProc := 0;
end;
end;
function KeyBoardHook(iCode: Integer; wParam: wParam;
lParam: lParam): LRESULT; stdcall;
const _KeyPressMask = $80000000;
var
pMsg: PEventMsg;
recOK: Integer;
begin
recOK := 1;
Result := 0;
if iCode < 0 then
Result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam)
else
if iCode = HC_SYSMODALON then
recOK := 0
else
if iCode = HC_SYSMODALOFF then
recOK := 1
else
if ((recOK > 0) and (iCode = HC_ACTION)) then
begin
pMsg := pEventMsg(lParam);
if ((pMsg.Message = WM_KEYDOWN) or (pMsg.Message = WM_SYSKEYDOWN)) then
PostMessage(OwnerHandle, WM_KEYSPY, pMsg.paramL, pMsg.paramH)
end;
end;
procedure DisableKeyHook;
begin
UnHookWindowsHookEx(hNextHookProc);
hNextHookProc := 0;
end;
function EnableKeyHook: Boolean;
begin
Result := False;
if hNextHookProc <> 0 then Exit;
hNextHookProc := SetWindowsHookex(WH_JOURNALRECORD, KeyBoardHook, Hinstance, 0);
Result := hNextHookProc <> 0;
end;
procedure TExKeySpy.SetEnabled(Value: Boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
if FEnabled then
EnableKeyHook
else
DisableKeyHook;
end;
end;
procedure TExKeySpy.Win_Proc(var Message: TMessage);
begin
if (csDesigning in ComponentState) then
FOldFormMethod(Message)
else
case Message.Msg of
WM_KEYSPY: WM_GETKEY(Message);
else
FOldFormMethod(Message);
end;
end;
procedure TExKeySpy.WM_GETKEY(var Message: TMessage);
var
Key, OldKey: Byte;
KeyStr: string;
Point: TPoint;
begin
GetCursorPos(Point);
Key := Message.WParam;
OldKey := Key;
{asm
in al, 60h
mov Key, al //这就是那一段让人头疼了一段时间的汇编
end; }
Key := MapVirtualKey(Key, 0);
if Key = 91 then //处理WIN健
begin
//省略若干字
end;
if Key = 170 then
Key := 84;
if Key = 182 then
Key := 85;
if Key = 250 then
Key := 186;
if Key <= 88 then
begin
if GetKeyState(VK_Shift) < 0 then
KeyStr := StrPas(HiButtonName[Key])
else
KeyStr := StrPas(LowButtonName[Key]);
if (GetKeyState(vk_Capital) = 1) and (Length(KeyStr) = 1) then
KeyStr := UpperCase(KeyStr);
end
else
begin
if (Key - 128 > 0) and (Key - 128 < 88) then
begin
if GetKeyState(VK_Shift) < 0 then
KeyStr := StrPas(HiButtonName[Key - 128])
else
KeyStr := StrPas(LowButtonName[Key - 128]);
if (GetKeyState(vk_Capital) = 1) and (Length(KeyStr) = 1) then
KeyStr := UpperCase(KeyStr);
end;
end;
if (GetKeyState(VK_NUMLOCK) = 1) and (OldKey >= 96) and (OldKey <= 105) then
KeyStr := Inttostr(OldKey - 96);