VCpp程序获取其它程序控件句柄并进行操控

⌚Time: 2023-02-01 13:21:53

👨‍💻Author: Jack Ge

以编辑框Edit为例子,让一个程序获取其它程序的编辑框里面的文本或者设置里面的文本。

首先新建一个测试程序窗体,加入两个编辑框,作为窗体控件

建立另一个程序,控制测试程序

首先需要获取目标窗体的句柄

可用的函数有:FindWindowEx和GetWindow

FindWindowEx是FindWindow函数的扩展,使用它检索一个窗口的句柄


HWND FindWindowExA(

  [in, optional] HWND   hWndParent,

  [in, optional] HWND   hWndChildAfter,

  [in, optional] LPCSTR lpszClass,

  [in, optional] LPCSTR lpszWindow

);

hWndParent  要搜索其子窗口的父窗口的句柄。如果 hwndParent 为 NULL,则该函数使用桌面窗口作为父窗口。 函数在桌面的子窗口之间搜索。

hWndChildAfter  子窗口的句柄。 搜索从 Z 顺序中的下一个子窗口开始。 子窗口必须是 hwndParent 的直接子窗口,而不仅仅是子窗口。如果 hwndChildAfter 为 NULL,则搜索从 hwndParent 的第一个子窗口开始。

lpszClass   如果 lpszClass 是字符串,则指定窗口类名。 类名可以是注册到 RegisterClass 或 RegisterClassEx 的任何名称,也可以是预定义的控件类名称

lpszWindow  窗口名称 (窗口的标题) 。 如果此参数为 NULL,则所有窗口名称都匹配

如果函数成功,则返回值是具有指定类和窗口名称的窗口的句柄。如果函数失败,则返回值为 NULL。

Z 序:一个重叠窗口的堆,每个窗口在Z 序中 都有唯一一个位置。一个窗口的Z 序 ,指明了该窗口在重叠窗口堆中的位置。这个窗口堆 是沿着一个虚拟的轴——“ Z 轴”,从屏幕上垂直向屏幕外延伸。 Z 序顶部的窗口覆盖 Z 序中的其他窗口。 Z 序底部的窗口被 Z 序中的其他窗口覆盖。

GetWindow检索具有指定关系 (Z-Order 或所有者) 到指定窗口的窗口的句柄


HWND GetWindow(

  [in] HWND hWnd,

  [in] UINT uCmd

);

hWnd    窗口的句柄。 检索的窗口句柄相对于此窗口,具体取决于 uCmd 参数的值。



uCmd    

GW_CHILD

如果指定的窗口是父窗口,则检索的句柄标识 Z 顺序顶部的子窗口;否则,检索的句柄为 NULL。 该函数仅检查指定窗口的子窗口。 它不检查后代窗口。

GW_ENABLEDPOPUP

检索的句柄标识指定窗口拥有的已启用弹出窗口, (搜索使用 GW_HWNDNEXT) 找到的第一个此类窗口;否则,如果没有启用的弹出窗口,则检索的句柄是指定窗口的句柄。

GW_HWNDFIRST

检索的句柄标识 Z 顺序中最高类型的窗口。

如果指定的窗口是最顶层的窗口,则句柄将标识最顶部的窗口。 如果指定的窗口是顶级窗口,则句柄标识顶级窗口。 如果指定的窗口是子窗口,则句柄标识同级窗口。

GW_HWNDLAST

检索的句柄标识 Z 顺序中最低类型的窗口。

如果指定的窗口是最顶层的窗口,则句柄将标识最顶部的窗口。 如果指定的窗口是顶级窗口,则句柄标识顶级窗口。 如果指定的窗口是子窗口,则句柄标识同级窗口。

GW_HWNDNEXT

检索的句柄按 Z 顺序标识指定窗口下方的窗口。

如果指定的窗口是最顶层的窗口,则句柄将标识最顶部的窗口。 如果指定的窗口是顶级窗口,则句柄标识顶级窗口。 如果指定的窗口是子窗口,则句柄标识同级窗口。

GW_HWNDPREV

检索的句柄按 Z 顺序标识指定窗口上方的窗口。

如果指定的窗口是最顶层的窗口,则句柄将标识最顶部的窗口。 如果指定的窗口是顶级窗口,则句柄标识顶级窗口。 如果指定的窗口是子窗口,则句柄标识同级窗口。

GW_OWNER

检索的句柄标识指定窗口的所有者窗口(如果有)。 有关详细信息,请参阅 拥有的 Windows。



如果函数成功,则返回值为窗口句柄。 如果不存在具有指定窗口与指定窗口的指定关系,则返回值为 NULL。

可以选用GetWindow获取指定窗体名称的句柄,查找目标窗体“Mainwindow”,通过FindWindow函数,指定窗体类名或者窗体名称都可以得到窗体句柄


    HWND htestWindow = ::FindWindow(NULL,L"Mainwindow");

    if(htestWindow == NULL){

        MessageBox(L"查找目标窗体失败!",L"",MB_OK);

        return;

    }

获取窗体类名?

msvc有个工具spy++,工具,Spy++,可以通过它的搜索功能,直接查找某个窗体的类名

得到它的所有子窗体(控件),通过GetWindow函数,可以遍历得到所有子窗体


    //首先通过GW_CHILD参数得到一个最上层子窗体的句柄,之后使用GW_HWNDNEXT参数遍历同级窗体

    htestWindow = ::GetWindow(htestWindow, GW_CHILD);

    //遍历所有子控件并打印窗体类名称

    while (htestWindow)

    {

        WCHAR windowClassName[1024] = {0};

        //获取窗体类名字

        GetClassName(htestWindow,windowClassName,sizeof(windowClassName)-1);

        MessageBox(windowClassName);

        //得到下一个子窗体

        htestWindow = ::GetWindow(htestWindow, GW_HWNDNEXT);

    }

编辑控件的窗体类名字为Edit,可以将获取到的窗体类名字与它比对,相同则得到了所需的控件,通过向它发送WM_SETTEXT消息,设置它的文本内容


    //首先通过GW_CHILD参数得到一个最上层子窗体的句柄,之后使用GW_HWNDNEXT参数遍历同级窗体

    htestWindow = ::GetWindow(htestWindow, GW_CHILD);

    while (htestWindow)

    {

        WCHAR windowClassName[1024] = {0};

        //获取窗体类名字

        GetClassName(htestWindow,windowClassName,sizeof(windowClassName)-1);

        //MessageBox(windowClassName);

        //比对窗体类名

        if(!wcscmp(L"Edit",windowClassName)){

            ::SendMessage(htestWindow,WM_SETTEXT,NULL,(LPARAM)L"123设置文本成功!");

        }

        //得到下一个子窗体

        htestWindow = ::GetWindow(htestWindow, GW_HWNDNEXT);

    }

获取编辑控件的文本也是一样的道理,遍历子窗体,查找对应的控件,发送消息


    HWND htestWindow = ::FindWindow(NULL,L"Mainwindow");

    if(htestWindow == NULL){

        MessageBox(L"查找目标窗体失败!",L"",MB_OK);

        return;

    }

    htestWindow = ::GetWindow(htestWindow, GW_CHILD);

    //遍历所有子控件并打印窗体类名称

    while (htestWindow)

    {

        WCHAR windowClassName[1024] = {0};

        GetClassName(htestWindow,windowClassName,sizeof(windowClassName)-1);

        //MessageBox(windowClassName);

        if(!wcscmp(L"Edit",windowClassName)){

            WCHAR messageGet[1024] = {0};

            //获取编辑控件文本内容

            ::SendMessage(htestWindow,WM_GETTEXT,(WPARAM)(sizeof(messageGet)-1),(LPARAM)messageGet);

            MessageBox(messageGet);

        }

        htestWindow = ::GetWindow(htestWindow, GW_HWNDNEXT);

    }

演示

或者使用FindWindow获取窗体


HWND hWnd = FindWindow(NULL, L"其他程序窗口标题");

再通过GetDlgItem


HWND hCtrl = GetDlgItem(hWnd, 控件ID);

来直接获取窗体内的控件句柄,其中的控件ID通过SPY++获取,对于目标窗口,右键属性就可以找到子控件ID

之后通过SendMessage()函数或PostMessage()函数向控件发送消息,以实现控制操作。


SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM)L"要设置的文本值");