全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2784
推到 Plurk!
推到 Facebook!

如何正確捕捉滑鼠及其原理(附範例)

 
Zard
尊榮會員


發表:24
回覆:396
積分:539
註冊:2003-11-26

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-10-25 15:17:39 IP:61.64.xxx.xxx 未訂閱
在Win95, WinNT 的環境下, Microsoft為了避免行程間互相干擾, 對於使用者輸入的部份(如鍵盤, 滑鼠), 是採用一種叫"Local Input State Processing"的方式, 這種技術簡單來說, 就是每個 行程, 執行緒, 認為自已是唯一取得使用者輸入的, 彼此之間並 不互相干擾(其實真正取得使用者輸入的只有 Active的行程或執行緒). 而我們最常用來抓取螢幕座標的 SetCapture , 是以System-Wide 的 型式來實作的, 所以就算滑鼠不在你的程式視窗範圍內, 也可以抓到 座標, 但是當你把滑鼠按鍵放開, 系統會改變滑鼠捕捉權, 使其為 Thread-Local-Wide, 此時就算你沒有使用 ReleaseCapture 來釋放 滑鼠捕捉權, 也無法在視窗範圍外捕捉滑鼠.這是因為 Local Input State Processing 的關係. 若要解決這個問題, 最好的方法就是暫 時把 Local Input State Processing 的功能關閉, 而方式就是掛上 一個 Journal Record Hook, 在Win95, NT 下因為Local Input State Processing 和 Journal Record Hook 會互相干擾, 而Microsoft為了 向下相容性所以當Journal Record Hook 被掛起來時, 就會把 Local Input State Processin 給關閉. 範例貼在下一篇, 此測試程式會把攔截到的滑鼠座標以 Label1 秀出. 測試方法, 首先按下"SetCapture"按鈕, 在程式視窗範圍內, 按下滑鼠 左鍵不放, 將滑鼠移出程式視窗, 此時可以發現, 即使在程式視窗範圍 外還是可以捕捉到滑鼠. 之後把滑鼠左鍵放開, 在移動滑鼠, 可以發現, 在放開滑鼠左鍵後,即使我們沒有呼叫ReleaseCapture, 也無法捕捉到滑 鼠. 接下來我們按下"SetCapture with Journal Record Hook"按鈕, 按下後 首先程式會先呼叫SetCapture, 之後在掛上 Journal Record Hook, 而此 Hook 沒做什麼事, 只是把值傳給下一個Hook(CallNextHookEx), 在我們 按下這按鈕後, 無論怎麼移動滑鼠, 無論有沒有按下滑鼠左鍵, 都可以收 到滑鼠座標.
Zard
尊榮會員


發表:24
回覆:396
積分:539
註冊:2003-11-26

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-10-25 15:20:15 IP:61.64.xxx.xxx 未訂閱
範例:
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;    type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }        Procedure HandleMouseMsg(var msg: TMessage); Message WM_MOUSEMOVE;      public
    { Public declarations }
  end;    var
  Form1: TForm1;
  hJourHook: HHOOK;
  
implementation    {$R *.DFM}    Procedure TForm1.HandleMouseMsg(var msg: TMessage);
begin
  Label1.Caption := Format( 'x=%d, y=%d',
                            [LOWORD(msg.Lparam), HIWORD(msg.Lparam)]);
  Application.ProcessMessages;
end;    Function JournalRecordProc( code: Integer;
                            WParamInfo: WPARAM;
                            LParamInfo: LPARAM): Integer; stdcall;
begin
  Result := CallNextHookEx(hJourHook, code, WParamInfo, LParamInfo);
end;    procedure TForm1.Button1Click(Sender: TObject);
begin
  SetCapture(Handle);
  SetWindowsHookEx(WH_JOURNALRECORD, @JournalRecordProc, HInstance, 0);  
end;    procedure TForm1.Button2Click(Sender: TObject);
begin
  ReleaseCapture();
  UnhookWindowsHookEx(hJourHook);
end;    procedure TForm1.Button3Click(Sender: TObject);
begin
  SetCapture(Handle);
end;    procedure TForm1.Button4Click(Sender: TObject);
begin
  ReleaseCapture();
end;    procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.Caption := 'SetCapture with Journal Record Hook';
  Button2.Caption := 'ReleaseCapture with Journal Record Hook';
  Button3.Caption := 'SetCapture';
  Button4.Caption := 'ReleaseCapture';
end;    end.    
系統時間:2024-06-26 22:13:44
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!