首先需要说明要在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等很多软件都是采用类似的操作来选择窗口的。
|