在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控件上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM