如何从不同的程序(进程)更改控件的值

时间:2012-02-14 15:38:42

标签: winapi c++builder

我想编写一个程序,它允许我在不同程序的文本框中更改值,或者自动将值从一个程序复制到另一个程序。

我找到了一种在targer程序中获取hWnd到大多数(不知道所有这些)控件的方法,并用鼠标光标指向它们。我做了一个简单的结构,以及它的数组

struct hWndpointer
   {
   HWND hWnd;
   AnsiString text;
   };

hWndpointer tbl[250];

EnumWindowProc和EnumChildWindowProc将窗口的句柄和文本加载到数组中并加载到程序中的列表控件中,这样我就可以单击列表中的项目(或用键盘选择它),光标指向控件(如像期望的那样按钮或文本框...不幸的是有些控件没有文本(或者更确切地说GetWindowText没有返回文本)所以无法识别控件。

问题是: 有没有办法获取/读取控件的名称? 有没有办法获取/读取并设置像'enabled'或'text'或'value'这样的specyfic值?

提前致谢

PS:对不起我的英文;)

2 个答案:

答案 0 :(得分:0)

您可以使用SendMessagePostMessage向其他进程拥有的Windows发送WM_GETTEXTWM_SETTEXTWM_ENABLE。 (SendMessage表示查询,PostMessage表示只写操作)

通常,子ID将用于识别子窗口(特别是在对话框中),但是程序也可以完全依赖于动态HWND值,在这种情况下,您将不得不退回窗口位置区分。

答案 1 :(得分:0)

从Win32 API的角度来看,UI控件没有Names,因此您不能要求API在另一个进程中返回UI控件的Name,因为这样的值不存在。名称严格地是应用程序使用的UI框架的一个特性(在C ++ Builder的情况下为VCL),并且您不能跨过程边界直接访问框架。您需要来自控件拥有的应用程序的合作。

例如,一种方法是让两个应用调用RegisterWindowMessage()来注册自定义窗口消息,然后您的应用可以将该消息发布到另一个应用,指定所需控件的HWND和您自己的HWND作为参数。然后,其他应用可以使用SendMessage()消息Name将控件的HWND返回到您应用的WM_COPYDATA,您可以使用该消息相应地更新您的列表。

在VCL框架中,您可以使用HWND函数将TWinControl*转换为FindControl()指针。如果NULL不属于调用进程,它将返回HWND,否则您可以从其Name属性中复制该值。例如:

const UINT WM_GETCONTROLNAME = RegisterWindowMessage("WM_GetControlName");
const UINT WM_GETCONTROLNAME_RESULT = RegisterWindowMessage("WM_GetControlName_Result");

#include <pshpack1.h>
struct sControlName
{
    HWND hWnd;
    int Length;
    char Value[1];
};
#include <poppack.h>

void __fastcall TMyForm::WndProc(TMessage &Message)
{
    if ((Message.Msg == WM_COPYDATA) && (WM_GETCONTROLNAME_RESULT != 0))
    {
        LPCOPYDATASTRUCT cds = (LPCOPYDATASTRUCT) Message.LParam;
        if (cds->dwData == WM_GETCONTROLNAME_RESULT)
        {
            sControlName *pName = (sControlName*) cds->lpData;
            AnsiString sName(pName->Value, pName->Length);

            // locate pName->hWnd in your list and assign sName to it as needed...

            return;
        }
    }

    TForm::WndProc(Message);
}

void ___fastcall TMyForm::FillList()
{
    ...
    if (WM_GETCONTROLNAME != 0)
    {
        HWND TheControlHWND = ...;
        HWND OtherAppHWND = ...;
        PostMessage(OtherAppHWND, WM_GETCONTROLNAME, (WPARAM)TheControlHWND, (LPARAM)this->Handle);
    }
    ...
}

const UINT WM_GETCONTROLNAME = RegisterWindowMessage("WM_GetControlName");
const UINT WM_GETCONTROLNAME_RESULT = RegisterWindowMessage("WM_GetControlName_Result");

#include <pshpack1.h>
struct sControlName
{
    HWND hWnd;
    int Length;
    char Value[1];
};
#include <poppack.h>

void __fastcall TMyForm::WndProc(TMessage &Message)
{
    if ((Message.Msg == WM_GETCONTROLNAME) && (WM_GETCONTROLNAME != 0) && (WM_GETCONTROLNAME_RESULT != 0))
    {
        HWND hWnd = (HWND) Message.WParam;

        TWinControl *Ctrl = FindControl(hWnd);
        if (Ctrl)
        {
            AnsiString sName = Ctrl->Name;

            std::vector<unsigned char> buffer((sizeof(sControlName) - 1) + sName.Length());
            sControlName *pName = (sControlName*) &buffer[0];

            pName->hWnd = hWnd;
            pName->Length = sName.Length();
            strncpy(pName->Value, sName.c_str(), pName->Length);

            COPYDATASTRUCT cds = {0};
            cds.dwData = WM_GETCONTROLNAME_RESULT;
            cds.cdData = buffer.size();
            cds.lpData = pName;

            SendMessage((HWND)Message.LParam, WM_COPYDATA, (WPARAM)this->Handle, (LPARAM)&cds);
        }

        return;
    }

    TForm::WndProc(Message);
}