在Delphi中使用键盘勾子获取键盘输入(译--5月7日)
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日)的更多相关文章
- SQL获取当前日期的年、月、日、时、分、秒数据
SQL Server中获取当前日期的年.月.日.时.分.秒数据: SELECT GETDATE() as '当前日期',DateName(year,GetDate()) as '年',DateName ...
- 在delphi中生成GUID/自动获取临时表名......
什么是 GUID ? 全球唯一标识符 (GUID) 是一个字母数字标识符,用于指示产品的唯一性安装.在许多流行软件应用程序(例如 Web 浏览器和媒体播放器)中,都使用 GUID. GUID 的格式为 ...
- Delphi中三种方法获取Windows任务栏的高度
第一种:需要引用Windows单元 ShowMessage(IntToStr(GetSystemMetrics(SM_CYSCREEN)-GetSystemMetrics(SM_CYFULLSCREE ...
- Delphi中限制文本框(TEdit)只能输入数字
procedure Tform1.Edit1KeyPress(Sender: TObject; var Key: Char);var edt: TEdit; str, strL, strR: stri ...
- javascript获取日期的年,月,日
var date = new Date(strTime); return date.getFullYear()+"-"+(date.getMonth()+1)+"-&qu ...
- 11.IPFS搭建及上传获取数据——2019年12月12日
title: ipfs使用 date: "2019-09-26 10:17:16" tags: ipfs categories: 技术驿站 1.mac安装ipfs--使用npm工具 ...
- .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 ...
- iOS 获取当前时间 年、月、日、周几
NSDate * nowDate = [NSDate new]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSUInteger uni ...
- C# DateTimePicker控件获取他的年,月,日,时,分,秒
CustomFormat属性设置为: yyyy-MM-dd HH:mm:ss 记住还要修改一个属性值,DateFormat属性 可选项改为Custom,默认是Long
随机推荐
- 修复ios上第三方输入法弹出时输入键盘盖住网页没有进行相应滚动从而盖住表单输入框的问题
fixIME(); function fixIME(){ scroll_y = 100; // 如果键盘弹起后 网页window对象的卷起小于此值,说明没有自动卷起 单位:px timer = 50 ...
- struts2学习笔记(三)
一. Struts2 的验证 1). 验证分为两种: > 声明式验证* >> 对哪个 Action 或 Model 的那个字段进行验证 >> 使用什么验证规则 >& ...
- 如何使用SDK在Ubuntu设备(包括仿真器和桌面)上运用应用程序
简介 有三种运行通过SDK创建的应用程序的方式:在桌面上,在联网的Ubuntu设备上,以及在仿真器中.这些方式为互补性方式,因为各有优缺点.您首先将了解如何管理SDK的设备类型,以及哪一个类型用于测试 ...
- [ Python - 6 ] 正则表达式实现计算器功能
要求:禁止使用eval函数.参考网上代码如下: #!_*_coding:utf-8_*_ """用户输入计算表达式,显示计算结果""" im ...
- [ Python - 2 ] 常见内置函数
1. abs(): 绝对值 In [1]: abs(-10) Out[1]: 10 2. all(): 当参数中任何一个值为False时,all() 都为False all(iterable) ...
- WPF中使用WPFMediaKit视频截图案例
前台 代码: <Window x:Class="WpfAppWPFMediaKit.MainWindow" xmlns="http://schemas.micros ...
- WPF拖放功能实现
写在前面:本文为即兴而作,因此难免有疏漏和词不达意的地方.在这里,非常期望您提供评论,分享您的想法和建议. 这是一篇介绍如何在WPF中实现拖放功能的短文. 首先要读者清楚的一件事情是:拖放主要分为拖放 ...
- python变现实现新浪微博登陆
新浪微博的登陆现在是越来越那个了,以前的模拟浏览器登陆新浪微博貌似也越来不管用了 登陆信息由以前的form变成了现在javascript,javascript的加载居然用了一个javascript的函 ...
- Max-heap && Min-heap && push_heap
最大堆:make_heap(vi.begin(),vi.end()) #include <iostream> #include <vector> #include <al ...
- tushare 安装
1.pip install lxml 2.pip install pandas 3.pip install requests 4.pip install lxml 5.pip install tush ...