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

来源:互联网 发布:wifi网络手机渗透工具 编辑:程序博客网 时间:2024/05/18 02:33

问:     我用VB的sendkeys编写了一个向其他程序模拟键盘发送字符的工具,因VB编的程序体积太大,我想用Delphi重写,使用SendMessage等API函数,但我想找到一个用鼠标点一下其他进程的窗口便可获得该窗口的线程id和窗口句柄的方法,请指点一下。(使用findwindow获得窗口句柄要输入窗口标题,不好。)

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

原创粉丝点击