• 在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控件上。
  • 相关阅读:
    oracleDBA-D4
    oracleDBA-D3
    oracleDBA-D2
    大数据架构学习记录
    UBUNTU 安装最新版 nodejs
    datax 单条记录超过大小限制,当前限制为:67108864
    将anaconda中已存在的虚拟环境增加到jupyterlab
    jupyter 启动python3 内核 总是出现错误 ImportError: cannot import name 'create_prompt_application'
    CDH 本地hadoop支持读写 AWS S3a
    hadoop 集群集成jupyterhub 出现的问题
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/5643377.html
Copyright © 2020-2023  润新知