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. IE9,IE10 CSS因Mime类型不匹配而被忽略问题 (转)

    写页面的时候在chrome,fireforks等页面上显示正常,但是换成IE9,IE10之后就完全没有样式了,报错信息是CSS 因 Mime 类型不匹配而被忽略,下面与大家分享下这个问题的相关的回答 ...

  2. [POJ1423]Stirling公式的应用

    Stirling公式: n!约等于sqrt(2*pi*n)*(n/e)^n 另外,e约等于2.71828182845409523... 试了一下发现math库里面并不能像pi一样直接调e但是发现挺好记 ...

  3. bugscan泄露代码解密

    #{文件名:decode key} dekey_dict= {'expback_64pyc_dis.py': 'ef632082c7620cf54876da74a1660bfb9c06eb94549b ...

  4. 列出top中的pid

    #!/usr/bin/env python import os import string #方法1:通过字符串的isdigits来判断 #filelist = os.listdir('/proc') ...

  5. Linux : select()详解 和 实现原理【转】

    转自:http://blog.csdn.net/huntinux/article/details/39289317 原文:http://blog.csdn.net/boboiask/article/d ...

  6. appium===安卓SDK下载很慢的解决办法

    方法一:http://www.apkbus.com/forum.php?mod=viewthread&tid=240851 方法二:http://www.androiddevtools.cn/

  7. IC卡的传输协议(3)【转】

    转自:http://bbs.ednchina.com/BLOG_ARTICLE_172027.HTM 3.终端传输层         本节描述了在终端和 IC 卡之间传输的命令和响应 APDU 的机制 ...

  8. pressmuSpiderr

    #!/usr/bin/env python # encoding: utf-8 import requests from random import choice from lxml import h ...

  9. 【 Tomcat 】后端tomcat获取真实IP

    环境: nginx + tomcat nginx.conf 配置: proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_ad ...

  10. Flex slider使用方法

    1.首先在页面head部位载入jquery库文件和Flexslider插件,以及Flexslider所需的基本css样式文件. <link rel="stylesheet"  ...