Delphi通过指点操作获得窗口句柄

Delphi通过指点操作获得窗口句柄

 

首先需要说明要在Delphi 实现Sendkeys功能,应该使用Journal Playback钩子(hook)函数,
而不是使用SendMessage函数。下面我们来介绍如何利用鼠标移动让用户选择窗口,而程序
进一步得到窗口的句柄。Windows API中有一个函数WindowFromPoint,只要知道鼠标的位置
(屏幕坐标),就可以得到该位置所属的窗口的句柄,有了句柄,就可以利用其他的函数得到
更多的信息。如果鼠标在程序的窗口中移动,可以得到MouseMove事件。要想鼠标在窗口外部
移动时,仍能得到鼠标事件,必须使用SetCapture函数。下面这个例子就是利用这两个函数
来实现你所要求的功能。

type
TForm1 = class(TForm)
…………
public
procedure InvertTracker(hwndDest : Integer);
end;
…………
var
Form1: TForm1;
mlngHwndCaptured: Integer;
hWndLast: Integer;
…………
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var pt : TPoint;
begin
if GetCapture() <> 0 then // 处于捕捉状态
begin
pt.X := X;
pt.Y := Y;
ClientToScreen(pt); // 获得鼠标的屏幕位置
// 获得窗口句柄
mlngHwndCaptured := WindowFromPoint(pt);

if hWndLast <> mlngHwndCaptured then
begin
if hWndLast <> 0 then // 使窗口边框加粗
InvertTracker(hWndLast);
InvertTracker(mlngHwndCaptured);
hWndLast := mlngHwndCaptured;
end
end;
// 显示坐标和窗口句柄
Caption := ‘X: ‘ + IntToStr(x) + ‘, Y: ‘ + IntToStr(y)
+ ‘, hWnd: ‘ + IntToStr(mlngHwndCaptured);
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if SetCapture(handle) <> 0 then // 开始捕捉
Cursor := crUpArrow;
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var strCaption: PChar;
begin
If mlngHwndCaptured <> 0 Then
begin // 获得窗口标题
strCaption := StrAlloc(1000);
GetWindowText(mlngHwndCaptured, strCaption, 1000);
Caption := StrPas(strCaption);
InvalidateRect(0, PRect(0), True);
mlngHwndCaptured := 0;
Cursor := crDefault;
ReleaseCapture;
StrDispose(strCaption);
hWndLast := 0;
end
end;
// 使窗口边框变粗
procedure TForm1.InvertTracker(hwndDest: Integer);
var
hdcDest, hPen, hOldPen, hOldBrush : Integer;
cxBorder, cxFrame, cyFrame, cxScreen, cyScreen, cr : Integer;
rc : TRect;
Const NULL_BRUSH = 5;
Const R2_NOT = 6;
Const PS_INSIDEFRAME = 6;
begin
cxScreen := GetSystemMetrics(0);
cyScreen := GetSystemMetrics(1);
cxBorder := GetSystemMetrics(5);
cxFrame := GetSystemMetrics(32);
cyFrame := GetSystemMetrics(33);
GetWindowRect(hwndDest, rc);

hdcDest := GetWindowDC(hwndDest);

SetROP2(hdcDest, R2_NOT);
cr := clBlack;
hPen := CreatePen(PS_INSIDEFRAME, 3 * cxBorder, cr);

hOldPen := SelectObject(hdcDest, hPen);
hOldBrush := SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
Rectangle(hdcDest, 0, 0, rc.Right – rc.Left, rc.Bottom – rc.Top);
SelectObject(hdcDest, hOldBrush);
SelectObject(hdcDest, hOldPen);

ReleaseDC(hwndDest, hdcDest);
DeleteObject(hPen);
end;
// 将窗口移动到左上角,并减少窗口高度,便于操作
procedure TForm1.FormCreate(Sender: TObject);
begin
Left := 0;
Top :=0;
ClientHeight := 76;
end;

运行该程序时,先在程序窗口内点一下,然后按住鼠标左键不放,移动鼠标,这时你会
看到程序窗口的标题位置不断显示鼠标的当前位置(窗口坐标)和鼠标所在位置的窗口句柄。
同时,被选中的窗口边框加粗,一旦放开左键,则程序窗口的标题就改为所选中窗口的标题。
相信许多人对这种操作方式都会感到熟悉,因为象Spy++(Visual C++)、Magic Mouse、
Capture Professional等很多软件都是采用类似的操作来选择窗口的。

分享到: 更多 (0)