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