关于鼠标钩子使用入门

Posted on 2010-12-22 10:58  严武  阅读(889)  评论(0编辑  收藏  举报

1.     MOUSEHOOKSTRUCT 鼠标钩子结构体
  当WH_MOUSE钩子处理的鼠标事件时,该结构包含鼠标信息。
  typedef struct {
  POINT pt;
  HWND hwnd;
  UINT wHitTestCode;
  ULONG_PTR dwExtraInfo;
  } MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;

参数:
  pt : POINT结构对象,保存鼠标在屏幕上的x,y坐标
  hwnd: 接收到鼠标消息的窗口的句柄
  wHitTestCode: hit-test值,详细描述参见WM_NCHITTEST消息
  dwExtraInfo: 指定与本消息联系的额外消息

2.     WM_NCHITTEST 消息
The WM_NCHITTEST message is sent to a window when the cursor moves, or when a mouse button is pressed or released.
    WM_NCHITTEST消息当鼠标移动、按下、松开都会被发送。如果鼠标不被捕获,消息在窗体得到光标之后发出。否则,消息发送到捕获到鼠标的窗体。
    xPos = LOWORD(lParam); // 光标的水平位置(X)
    yPos = HIWORD(lParam); // 光标的垂直位置(Y)

3.     鼠标消息的关系理解
无标题窗口拖动,我们一般是采用:
响应WM_NCHITTEST消息,返回HTCAPTION来实现。
但是,如果在这同时还要处理鼠标的消息,如WM_LBUTTONDOWN、WM_LBUTTONUP、WM_RBUTTONUP、WM_MOUSEMOVE,你会发现,这些消息都收不到了。

因为你在WM_NCHITTEST中处理了鼠标消息,把他定位成HTCAPTION,也就是鼠标在标题栏上,而标题栏属于非客户区(NC);
   非客户区的事件消息都是以WM_NC开头的。也就是说,当你的WM_NCHITTEST返回HTCAPTION时,原来可以用WM_LBUTTONUP处理的消息,你只能用WM_NCLBUTTONUP来处理。
    自然是同时处理WM_NCHITTEST和WM_NCRBUTTONUP,而不处理WM_RBUTTONUP

4.     鼠标钩子的使用
 

 
view plaincopy to clipboardprint?
01.unit Unit1;  
02. 
03.interface 
04. 
05.uses 
06.  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
07.  Dialogs, StdCtrls;  
08. 
09.type 
10.  TForm1 = class(TForm)  
11.    Button1: TButton;  
12.    Memo1: TMemo;  
13.    CheckBox1: TCheckBox;  
14.    RadioButton1: TRadioButton;  
15.    Edit1: TEdit;  
16.    ComboBox1: TComboBox;  
17.    ScrollBar1: TScrollBar;  
18.    procedure FormCreate(Sender: TObject);  
19.    procedure FormDestroy(Sender: TObject);  
20.  private 
21.    { Private declarations } 
22.  public 
23.    { Public declarations } 
24.    procedure ShowMouseHookInfo(LParam: Integer);  
25.  end;  
26. 
27.var 
28.  Form1: TForm1;  
29.  GHHook : HHOOK; // 全局钩子句柄  
30. 
31.implementation 
32. 
33.{$R *.dfm} 
34. 
35.function CallBackMouseHook(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; // 重要  
36.begin 
37.  Result := 0;  
38.  case wParam of 
39.//  WM_LBUTTONDOWN:  
40.    WM_MOUSEMOVE:  
41.    begin 
42.      Form1.ShowMouseHookInfo(lParam);  
43.    end;  
44.  end;  
45.  CallNextHookEx(GHHook, iCode, wParam, lParam);  
46.end;  
47. 
48.{ TForm1 } 
49. 
50.procedure TForm1.ShowMouseHookInfo(LParam: Integer);  
51.const 
52.  SPACE = 32;  
53.var 
54.  psMouseHook : PMouseHookStruct;  
55.  x, y : LongInt;  
56.  hWnd : Integer;  
57.  pcWndText : PChar;  
58.begin 
59.  psMouseHook := PMouseHookStruct(LParam);  
60.  x := psMouseHook^.pt.X;  
61.  y := psMouseHook^.pt.Y;  
62.  Form1.Refresh();  
63.  Canvas.TextOut(SPACE, SPACE, '坐标 : X = ' + IntToStr(x) + ' Y = ' + IntToStr(y));  
64.  hWnd := psMouseHook^.hwnd;  
65.  Canvas.TextOut(SPACE, SPACE * 2, '控件句柄 : ' + IntToStr(hWnd));  
66.  GetMem(pcWndText, 1024);  
67.  GetWindowText(hWnd, pcWndText, 1024);  
68.  Canvas.TextOut(SPACE, SPACE * 3, '控件内容 : ' + StrPas(pcWndText));  
69.  GetClassName(hWnd, pcWndText, 1024);  
70.  Canvas.TextOut(SPACE, SPACE * 4, '控件类名 : ' + StrPas(pcWndText));  
71.  FreeMem(pcWndText);  
72.end;  
73. 
74.procedure TForm1.FormCreate(Sender: TObject);  
75.begin 
76.  GHHook := SetWindowsHookEx(WH_MOUSE, CallBackMouseHook, HInstance, GetCurrentThreadID);  //全局  
77.end;  
78. 
79.procedure TForm1.FormDestroy(Sender: TObject);  
80.begin 
81.  UnhookWindowsHookEx(GHHook)  
82.end;  
83. 
84.end. 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    CheckBox1: TCheckBox;
    RadioButton1: TRadioButton;
    Edit1: TEdit;
    ComboBox1: TComboBox;
    ScrollBar1: TScrollBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ShowMouseHookInfo(LParam: Integer);
  end;

var
  Form1: TForm1;
  GHHook : HHOOK; // 全局钩子句柄

implementation

{$R *.dfm}

function CallBackMouseHook(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; // 重要
begin
  Result := 0;
  case wParam of
//  WM_LBUTTONDOWN:
    WM_MOUSEMOVE:
    begin
      Form1.ShowMouseHookInfo(lParam);
    end;
  end;
  CallNextHookEx(GHHook, iCode, wParam, lParam);
end;

{ TForm1 }

procedure TForm1.ShowMouseHookInfo(LParam: Integer);
const
  SPACE = 32;
var
  psMouseHook : PMouseHookStruct;
  x, y : LongInt;
  hWnd : Integer;
  pcWndText : PChar;
begin
  psMouseHook := PMouseHookStruct(LParam);
  x := psMouseHook^.pt.X;
  y := psMouseHook^.pt.Y;
  Form1.Refresh();
  Canvas.TextOut(SPACE, SPACE, '坐标 : X = ' + IntToStr(x) + ' Y = ' + IntToStr(y));
  hWnd := psMouseHook^.hwnd;
  Canvas.TextOut(SPACE, SPACE * 2, '控件句柄 : ' + IntToStr(hWnd));
  GetMem(pcWndText, 1024);
  GetWindowText(hWnd, pcWndText, 1024);
  Canvas.TextOut(SPACE, SPACE * 3, '控件内容 : ' + StrPas(pcWndText));
  GetClassName(hWnd, pcWndText, 1024);
  Canvas.TextOut(SPACE, SPACE * 4, '控件类名 : ' + StrPas(pcWndText));
  FreeMem(pcWndText);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  GHHook := SetWindowsHookEx(WH_MOUSE, CallBackMouseHook, HInstance, GetCurrentThreadID);  //全局
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnhookWindowsHookEx(GHHook)
end;

end.
 

5.     参考资料
MOUSEHOOKSTRUCT
http://baike.baidu.com/view/2764699.htm
WM_NCHITTEST消息说明
http://blog.csdn.net/zhuzhubin/archive/2009/07/17/4356825.aspx
WM_NCHITTEST后鼠标消息收不到
http://blog.csdn.net/debehe/archive/2009/08/05/4412959.aspx

 

Copyright © 2024 严武
Powered by .NET 9.0 on Kubernetes