如何从多个文本框中获取文本控制另一个程序。 C# WM_GETTEXT

How to get text from multiple textboxes controls another program. C# WM_GETTEXT

我正在尝试从另一个应用程序的多个或特定文本框/控件中获取文本。

我这里的代码有效,它将文本框文本显示为 label2.text。

但它没有从我需要的文本框中读取值。所有文本框 class 名称均为“WindowsForms10.EDIT.app.0.141b42a_r12_ad1”。那么如何阅读特定的框?

另请注意,每次重新打开应用程序时句柄都会更改。但是 class name 没有。

如果有任何解决方案,一个示例会很好。

谢谢

IntPtr Hwnd = FindWindow(null, "Software - Name");

IntPtr Handle = Marshal.AllocHGlobal(100);

int NumText = (int)SendMessage(Hwnd, WM_GETTEXT, (IntPtr)50, Handle);


string Text = Marshal.PtrToStringUni(Handle);
label1.Text = Text;

IntPtr ChildHandle = FindWindowEx(Hwnd, IntPtr.Zero, "WindowsForms10.EDIT.app.0.141b42a_r12_ad1", "");

IntPtr Hndl = Marshal.AllocHGlobal(200);


                NumText = (int)SendMessage(ChildHandle, WM_GETTEXT, (IntPtr)200, Hndl);

            Text = Marshal.PtrToStringUni(Hndl);

                    label2.Text = Text;

在大多数程序中,控件总是布置在相同的 z-order 中。因此,您可以列出所有文本框,按 z-order 对它们进行编号,然后使用它再次查找。

此代码段会将所有文本框的内容放入 label2。

IntPtr Hwnd = FindWindow(null, "Software - Name");

IntPtr Handle = Marshal.AllocHGlobal(100);

int NumText = (int)SendMessage(Hwnd, WM_GETTEXT, (IntPtr)50, Handle);

string Text = Marshal.PtrToStringUni(Handle);
label1.Text = Text;

IntPtr ChildHandle = IntPtr.Zero;

label2.Text = "";

// Loop through all the textboxes that are children of Hwnd.
int childNo = 0;
while ((ChildHandle = FindWindowEx(Hwnd, ChildHandle, "WindowsForms10.EDIT.app.0.141b42a_r12_ad1", "")) != IntPtr.Zero) {
    IntPtr Hndl = Marshal.AllocHGlobal(200);

    NumText = (int)SendMessage(ChildHandle, WM_GETTEXT, (IntPtr)200, Hndl);
    Text = Marshal.PtrToStringUni(Hndl);
    label2.Text += "(Child Number " + childNo + ") " + Text + Environment.NewLine;
    Marshal.FreeHGlobal(Hndl);

    childNo++;
}

一旦确定了所需文本框的编号,就可以更改代码,使其仅读取该文本框中的文本。比如说,数字是 5,你可以这样改变 while 循环:

while ((ChildHandle = FindWindowEx(Hwnd, ChildHandle, "WindowsForms10.EDIT.app.0.141b42a_r12_ad1", "")) != IntPtr.Zero) {
    if (childNo == 5) {
        IntPtr Hndl = Marshal.AllocHGlobal(200);

        NumText = (int)SendMessage(ChildHandle, WM_GETTEXT, (IntPtr)200, Hndl);
        Text = Marshal.PtrToStringUni(Hndl);
        label2.Text = Text;
        Marshal.FreeHGlobal(Hndl);
        break;
    }

    childNo++;
}

要用的东西是控件id。您可以使用 Spy++ 来获取它。

随着程序的执行,转到Visual Studio。在 "Tools" 菜单中是 "Spy++"。如果您的系统是 64 位系统,那么您需要使用 64 位版本的 Spy++,或者对于 32 位系统,请使用 32 位版本。转到 "Search" | "Find Window..."。这将打开一个 "Find Window" 对话框。现在首先,确保程序可见;至少它的相关按钮部分。然后单击 "Finder Tool" 图标(带有圆圈的正方形,看起来像一个目标)。按住鼠标按钮,从 Finder 工具图标拖动到“=”按钮,然后松开鼠标。查找 Window 对话框将填充按钮的句柄和其他数据。点击 "OK"。然后你会得到一个 "Window Properties" window 和一个带有 5 个选项卡的选项卡控件。这五个选项卡是常规、样式、Windows、Class 和处理。在第一个(常规)选项卡的底部附近寻找 "Control ID"。它是一个十六进制值。无论值是什么,每次执行该程序时都可能是该值。在 Windows API 级别,控件通常由控件 id 标识。我们可以在我们的程序中使用 Window 属性 window 中显示的控件 ID。

您将需要以下内容:

[DllImport("user32.dll")]
static extern IntPtr GetDlgItem(IntPtr hWnd, int nIDDlgItem);

假设"handle"是主window句柄,"TextBoxId"是文本框的id,可以使用下面的方法获取文本框的句柄:

IntPtr TextBoxhWnd = GetDlgItem(handle, TextBoxId);

另请参阅我的Clicking a Button in Another Application