http://blog.sina.com.cn/s/blog_502b2e970100949s.html

获取键盘输入以控制无法接受输入焦点的控件
考虑一些游戏,显示图片在TPainBox,但是TPainBox无法获取输入焦点,当用户按下键的时候,没有任何事件产生,我们无法获取光标键以移动战舰,Delphi能够帮助我们做点这一点。
获取键盘输入
大多数Delphi应用程序通过指定的事件处理器有选择地处理输入,这使我们能够捕捉击键并处理鼠标动作。
我们知道只有能够获取焦点的控件才有能力处理用户鼠标或者键盘的输入。只有有焦点的的控件能够接受键盘事件,有一些控件,诸如TImage, TPaintBox, TPanel 和 TLabel 不能够接受焦点。
图形控件主要的用途就是显示图片。
如果你想让不能接受输入焦点的控件能够获取键盘输入,我们必须使用Windows API,勾子、回调函数和消息。
Windows勾子
技术上,一个"hook" 函数是一个回调函数,它能够插入到Windows的消息系统中以使应用程序能够在其它的消息处理过程之前处理消息流。键盘勾子是Windows 勾子类型中的一种,无论什么时候应用程序调用GetMessage或者PeekMessage函数并县存在着WM_KEYUP 或者 WM_KEYDOWN消息需要处理时键盘勾子将被调用。
创建一个键盘勾子来获取一个给定的线程的所有的键盘输入,我们需要调节器用API函数SetWindowsHookEx ,应用程序接受键盘事件时将调用应用程序指定的勾子过程。Windows在按键消息被放置到消息队列之前对每一个按键消息调用你的勾子过程(key up 和 key down)。这个勾子函数能够处理、改变或者丢弃这个按键。勾子能够是全局的或者是本地的。
SetWindowsHookEx 函数的返回值是已被安装的勾子的句柄,在结束之前,应用程序必须调用UnhookWindowsHookEx 函数来释放系统分配给勾子的资源。
键盘勾子例子
做为一个键盘勾子的示例,我们将创建一个带有能接收键盘下按的图形控件的工程,TImage 是从 TGraphicControl派出的,它能够做为我们构想的战争游戏的一个绘图接口,既然TImage 无法接受标准键盘的下按事件,所以,我们将创建一个勾子函数来获取做为我们显示接口控件的所有键盘输入。
TImage处理键盘事件
开始一个新的Delphi工程并把一个 Image 组件放置到窗口上,设置Image1.Align 属性为alClient。这是显示部分,现在必须添加一些代码,首先我们需要一些全局变量:
var
  Form1: TForm1;
  KBHook: HHook; {this intercepts keyboard input}
  cx, cy : integer; {track battle ship's position}
  {callback's declaration}
  function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
implementation
...
我们在form的OnCreate事件中调用SetWindowsHookEx来安装一个勾子。
procedure TForm1.FormCreate(Sender: TObject) ;
begin
{Set the keyboard hook so we
can intercept keyboard input}
KBHook:=SetWindowsHookEx(WH_KEYBOARD,
           {callback —>} @KeyboardHookProc,
                          HInstance,
                          GetCurrentThreadId()) ;
{place the battle ship in
the middle of the screen}
cx := Image1.ClientWidth div 2;
cy := Image1.ClientHeight div 2;
Image1.Canvas.PenPos := Point(cx,cy) ;
end;
在OnDestroy事件中调用UnhookWindowsHookEx 函数释放分配给勾子的资源:
procedure TForm1.FormDestroy(Sender: TObject) ;
begin
  {unhook the keyboard interception}
  UnHookWindowsHookEx(KBHook) ;
end;
最重要的部分是处理键盘输入的KeyboardHookProc回调函数:
function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt) : LongInt;
begin
case WordParam of
  vk_Space: {erase battle ship's path}
   begin
    with Form1.Image1.Canvas do
    begin
     Brush.Color := clWhite;
     Brush.Style := bsSolid;
     Fillrect(Form1.Image1.ClientRect) ;
    end;
   end;
  vk_Right: cx := cx+1;
  vk_Left: cx := cx-1;
  vk_Up: cy := cy-1;
  vk_Down: cy := cy+1;
end; {case}
If cx < 2 then cx := Form1.Image1.ClientWidth-2;
If cx > Form1.Image1.ClientWidth -2 then cx := 2;
If cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
If cy > Form1.Image1.ClientHeight-2 then cy := 2;
with Form1.Image1.Canvas do
begin
  Pen.Color := clRed;
  Brush.Color := clYellow;
  TextOut(0,0,Format('%d, %d',[cx,cy])) ;
  Rectangle(cx-2, cy-2, cx+2,cy+2) ;
end;
Result:=0;
{To prevent Windows from passing the keystrokes
to the target window, the Result value must
be a nonzero value.}
end;
这就是键盘处理代码。
要注意的只有一点:代码这些代码不是只能够使用在处理TImage控件上。

在Delphi中使用键盘勾子获取键盘输入(译--5月7日)的更多相关文章

  1. SQL获取当前日期的年、月、日、时、分、秒数据

    SQL Server中获取当前日期的年.月.日.时.分.秒数据: SELECT GETDATE() as '当前日期',DateName(year,GetDate()) as '年',DateName ...

  2. 在delphi中生成GUID/自动获取临时表名......

    什么是 GUID ? 全球唯一标识符 (GUID) 是一个字母数字标识符,用于指示产品的唯一性安装.在许多流行软件应用程序(例如 Web 浏览器和媒体播放器)中,都使用 GUID. GUID 的格式为 ...

  3. Delphi中三种方法获取Windows任务栏的高度

    第一种:需要引用Windows单元 ShowMessage(IntToStr(GetSystemMetrics(SM_CYSCREEN)-GetSystemMetrics(SM_CYFULLSCREE ...

  4. Delphi中限制文本框(TEdit)只能输入数字

    procedure Tform1.Edit1KeyPress(Sender: TObject; var Key: Char);var edt: TEdit; str, strL, strR: stri ...

  5. javascript获取日期的年,月,日

    var date = new Date(strTime); return date.getFullYear()+"-"+(date.getMonth()+1)+"-&qu ...

  6. 11.IPFS搭建及上传获取数据——2019年12月12日

    title: ipfs使用 date: "2019-09-26 10:17:16" tags: ipfs categories: 技术驿站 1.mac安装ipfs--使用npm工具 ...

  7. .NET 5 Preview 1中的ASP.NET Core更新 (2020年3月16日)

    .NET 5 Preview1现在可用,可以进行评估了! .NET 5将是当前版本. 开始 要在.NET 5.0中开始使用 ASP.NET Core,请安装.NET 5.0 SDK. 如果您使用的是W ...

  8. iOS 获取当前时间 年、月、日、周几

    NSDate * nowDate = [NSDate new]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSUInteger uni ...

  9. C# DateTimePicker控件获取他的年,月,日,时,分,秒

    CustomFormat属性设置为: yyyy-MM-dd HH:mm:ss 记住还要修改一个属性值,DateFormat属性 可选项改为Custom,默认是Long

随机推荐

  1. java 身份证15位转18位

    /** * 根据身份证号获取性别 * * @param pid * 身份证号 * @return 性别 F为女M为男 */ public static String getSexByPid(Strin ...

  2. netty的Udp单播、组播、广播实例+Java的Udp单播、组播、广播实例

    网络上缺乏netty的udp的单播.组播案例,经过一番学习总结之后终于把这两个案例调通,下面把这两个案例的代码放在这里分享一下. 首先推荐博文: http://colobu.com/2014/10/2 ...

  3. Oracle 脚本记录

    给表创建序列或触发器 create or replace procedure p_createseq(tablename in varchar2,key in varchar2) Authid Cur ...

  4. windows注册表存储位置

    win7/8/10 通常情况: HKEY_LOCAL_MACHINE \SYSTEM : \system32\config\system HKEY_LOCAL_MACHINE \SAM : \syst ...

  5. CVE-2016-6662 mysql RCE测试

    参考:http://bobao.360.cn/learning/detail/3027.html ,我尝试第一种方法 1.先修改mysql_hookandroot_lib.c里面的反弹地址和端口: # ...

  6. 创建堆 HeapCreate

    创建额外的堆的原因1.对组件进行保护2.更有效的内存管理3.局部访问4.避免线程同步开销5.快速释放 HeapCreate函数原型:HANDLE WINAPI HeapCreate( _In_ DWO ...

  7. 转: Photoshop cs6 快捷键命令大全

    转自: http://www.cnblogs.com/zhen656/p/4249759.html 工具箱(多种工具共用一个快捷键的可同时按[Shift]加此快捷键选取) 矩形.椭圆选框工具.单行单列 ...

  8. HDU1045(二分图经典建模)

    Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  9. locust===注意事项

    1.安装包在:微盘 2.运行命令是:locust -f load_test.py --host=https://www.baidu.com 3.本地打开的是:http://localhost:8089 ...

  10. Ajax提交数据的data序列化数据提交即可

    jQuery.ajax({ url: "<s:url value="/contractinfo/finanContractInfoMgrAction!saveOrMod.ac ...