模仿VS编译器的Spy++

MySpy++

说明:

本例利用MFC模仿VS编译器的SPY++,通过捕捉工具,随着光标的移动可以获取到当前窗口的句柄、标题、类名、尺寸。

 

最终结果:

 

步骤:

1.打开资源视图-》Dialog,对对话框进行如下修改。

解析:

“搜索条件”是组合框,Group Box,可以任意拖动,选定包含区域。

“搜索条件”下面的文字和“句柄”、“标题”等都是Stati  Text.

“捕捉工具图标”是picture control,同时还要改变相应的属性。Type选择Icon,Image选择对应的图标ID。

 

2.将要用到的资源(图标图、光标图)加载进来,或放入程序文件下的res文件。再放入到对应的变量中。

//加载捕捉工具移动前后的图标和光标

         m_hNewIcon = AfxGetApp()->LoadIconW(IDI_ICON_BLANK);

         m_hSpyIcon = AfxGetApp()->LoadIconW(IDI_ICON_TARGET);

         m_hTargetCursor = AfxGetApp()->LoadCursorW(IDC_CRS_TARGET);

注意:在MFC中,要用AfxGetApp()去调用方式,不可以直接LoadIcon。

 

3捕捉工具。鼠标按下后图标、光标变化。

CRect rtTarget;

m_picTarget.GetWindowRect(&rtTarget);

ScreenToClient(&rtTarget);

SetCapture();

if (rtTarget.PtInRect(point))

{

           m_picTarget.SetIcon(m_hNewIcon);

           ::SetCursor(m_hTargetCursor);

           ::SetCapture(m_hWnd);

           bisDown = TRUE;

         }

首先要获取picture control的大小,并判断光标是否在该区域。利用函数PtInRect()。

m_picTarget.GetWindowRect(&rtTarget);

           rtTarget.PtInRect(point)

注意:

(1)一定要把屏幕坐标转换成客户区坐标。ScreenToClient(&rtTarget);

(2)SetCapture();作用:是将当前所有消息都交给当前窗口使用。

(3) ::双冒号,代表是全局函数,参数有相应的窗口句柄,等同于在WIN32的函数。

然后,把图标改成另一个空白图标,把光标改成圆形的光标。

 

4光标移动过程,找对应窗口的句柄。(有句柄就可以为所欲为了)

获取光标的位置:GetCursorPos(&ptMouse)

通过光标位置获取窗口句柄:hMyWnd=::WindowFromPoint(ptMouse);

5.鼠标弹起后的操作。

//捕捉结束后,把捕捉还原

m_picTarget.SetIcon(m_hSpyIcon);

ReleaseCapture();

         bisDown = FALSE;

还原图标,同时还要释放ReleaseCapture(),而bisDown = FALSE是将光标还原,不再获取对应窗口的句柄。

注意:消息可以在类向导处添加。如:鼠标左键单击void CSpyDlg::OnLButtonDown(UINT nFlags, CPoint point)、鼠标移动void CSpyDlg::OnMouseMove(UINT nFlags, CPoint point)等消息。

 

以上的捕捉图标的难点就这些。下面的都是调用对应的API就可以完成了。

 

获取句柄并显示在编辑框中:

hMyWnd=::WindowFromPoint(ptMouse);       

SetDlgItemText(IDC_EDT_HANDLE, str);

 

标题:

int nLen = ::GetWindowTextLength(hMyWnd);

if (nLen)

{

           TCHAR* buf = new TCHAR[nLen + 1];

           ::GetWindowText(hMyWnd, buf, nLen + 1);

           SetDlgItemText(IDC_EDT_TITAL, buf);

           delete[] buf;

           buf = NULL;

}

 

类名:

TCHAR* buf = new TCHAR[MAX_PATH];

if (buf)

{

           ::GetClassNameW(hMyWnd, buf, MAX_PATH);

           SetDlgItemText(IDC_EDT_CLASS, buf);

           delete[] buf;

           buf = NULL;

}

 

尺寸:

CString str;

str.Format(L"(%d X %d)", rt.right-rt.left, rt.bottom-rt.top);

SetDlgItemText(IDC_EDT_SIZE, str);

 

注意:

(1)在边框中,可以显示文字、数字,但只能一次填入。要利用Format()进行格式转化,可以是十六进制、十进制、字符串等。记住:Format()是类CString的方法。

(2)尺寸处,可以不将屏幕坐标转化成客户区坐标,利用右下角坐标减去左上角坐标,可以获取窗口的高、宽。

源代码:
对话框的头文件。SpyDlg.h
    CStatic m_picTarget;                //picture变量
    HCURSOR m_hTargetCursor;            //圆形光标                
    BOOL bisDown;                        //标记光标的使用情况
    HICON m_hNewIcon, m_hSpyIcon;        //点击捕捉工具前后,图标的变化

    void GetHandle(HWND &hMyWnd);        //获取句柄
    void GetTitle(HWND &hMyWnd);        //获取标题
    void GetClass(HWND &hMyWnd);        //获取类名
    void GetSize(HWND &hMyWnd,RECT &rt);//获取尺寸

对话框的源文件. SpyDlg.cpp

初始化函数处:

 

  SetIcon(m_hIcon, TRUE);                            // 设置大图标

  SetIcon(m_hIcon, FALSE);                  // 设置小图标

  // TODO:  在此添加额外的初始化代码


  //加载捕捉工具移动前后的图标和光标

  m_hNewIcon = AfxGetApp()->LoadIconW(IDI_ICON_BLANK);

  m_hSpyIcon = AfxGetApp()->LoadIconW(IDI_ICON_TARGET);

  m_hTargetCursor = AfxGetApp()->LoadCursorW(IDC_CRS_TARGET);对话框的源文件. SpyDlg.cpp


//鼠标按下消息
void CSpyDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //当点击捕捉工具时,判断是否在捕捉区域,并改变光标 CRect rtTarget; m_picTarget.GetWindowRect(&rtTarget); ScreenToClient(&rtTarget); if (rtTarget.PtInRect(point)) { m_picTarget.SetIcon(m_hNewIcon); ::SetCursor(m_hTargetCursor); ::SetCapture(m_hWnd); bisDown = TRUE; } CDialogEx::OnLButtonDown(nFlags, point); } //鼠标移动消息 void CSpyDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //当鼠标移动时,找到不同窗口的句柄,并画出外边 POINT ptMouse; RECT rt; HDC hDeskDc; HWND hMyWnd; if (bisDown) { if (GetCursorPos(&ptMouse)) { hMyWnd=::WindowFromPoint(ptMouse); if (hMyWnd) { if (::GetWindowRect(hMyWnd, &rt)) { hDeskDc = ::GetDC(::GetDesktopWindow()); HPEN hPen = CreatePen(PS_SOLID, 5, RGB(0, 0, 255)); HPEN hOldPen = (HPEN)SelectObject(hDeskDc, hPen); //for (int i = 0; i < 10; ++i) //画边 { MoveToEx(hDeskDc, rt.left, rt.top, NULL); LineTo(hDeskDc, rt.right, rt.top); MoveToEx(hDeskDc, rt.right, rt.top, NULL); LineTo(hDeskDc, rt.right, rt.bottom); MoveToEx(hDeskDc, rt.right, rt.bottom, NULL); LineTo(hDeskDc, rt.left, rt.bottom); MoveToEx(hDeskDc, rt.left, rt.bottom, NULL); LineTo(hDeskDc, rt.left, rt.top); Sleep(100); } } } //分别显示窗口的句柄、标题、类名、尺寸 CSpyDlg::GetHandle(hMyWnd); CSpyDlg::GetTitle(hMyWnd); CSpyDlg::GetClass(hMyWnd); CSpyDlg::GetSize(hMyWnd, rt); } } CDialogEx::OnMouseMove(nFlags, point); } //鼠标弹起消息 void CSpyDlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //捕捉结束后,把捕捉还原 m_picTarget.SetIcon(m_hSpyIcon); ReleaseCapture(); bisDown = FALSE; CDialogEx::OnLButtonUp(nFlags, point); }
void CSpyDlg::GetHandle(HWND &hMyWnd) { CString str; if (hMyWnd) { str.Format(L"%08X", hMyWnd); SetDlgItemText(IDC_EDT_HANDLE, str); } else return ; } // void CSpyDlg::GetTitle(HWND &hMyWnd) { int nLen = ::GetWindowTextLength(hMyWnd); if (nLen) { TCHAR* buf = new TCHAR[nLen + 1]; ::GetWindowText(hMyWnd, buf, nLen + 1); SetDlgItemText(IDC_EDT_TITAL, buf); delete[] buf; buf = NULL; } else return ; } void CSpyDlg::GetClass(HWND &hMyWnd) { TCHAR* buf = new TCHAR[MAX_PATH]; if (buf) { ::GetClassNameW(hMyWnd, buf, MAX_PATH); SetDlgItemText(IDC_EDT_CLASS, buf); delete[] buf; buf = NULL; } else return; } void CSpyDlg::GetSize(HWND &hMyWnd,RECT &rt) { CString str; str.Format(L"(%d X %d)", rt.right-rt.left, rt.bottom-rt.top); SetDlgItemText(IDC_EDT_SIZE, str); }

 

posted @ 2017-09-08 19:49  gd_沐辰  阅读(1156)  评论(0编辑  收藏  举报