C# 外部应用程序中文本框的SetText。Win32 API

C# 外部应用程序中文本框的SetText。Win32 API,c#,winapi,interop,C#,Winapi,Interop,使用Winspector,我发现要更改的子文本框的ID为114。为什么这个代码不改变文本框的文本 [DllImport("user32.dll")] static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem); [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int msg, int Param, s

使用Winspector,我发现要更改的子文本框的ID为114。为什么这个代码不改变文本框的文本

    [DllImport("user32.dll")]
    static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int msg, int Param, string s);

    const int WM_SETTEXT = 0x000c;

    private void SetTextt(IntPtr hWnd, string text)
    {
        IntPtr boxHwnd = GetDlgItem(hWnd, 114);
        SendMessage(boxHwnd, WM_SETTEXT, 0, text);
    }

以下是我在删除/禁用my GetLastError错误检查的情况下成功用于此目的的内容:

[DllImport("user32.dll", SetLastError = false)]
public static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, string lParam);
public const uint WM_SETTEXT = 0x000C;

private void InteropSetText(IntPtr iptrHWndDialog, int iControlID, string strTextToSet)
{
    IntPtr iptrHWndControl = GetDlgItem(iptrHWndDialog, iControlID);
    HandleRef hrefHWndTarget = new HandleRef(null, iptrHWndControl);
    SendMessage(hrefHWndTarget, WM_SETTEXT, IntPtr.Zero, strTextToSet);
}
我已经测试了这段代码,它可以正常工作,因此,如果您失败,您需要确保使用了正确的窗口句柄(对话框本身的句柄)和正确的控件ID。还可以尝试一些简单的操作,例如在记事本中编辑“查找”对话框

我还不能在帖子中对使用(char*)发表评论,但这不是必须的。请参见中的第二个C#重载。您可以将字符串或StringBuilder直接传递到SendMessage中

我还注意到你说你的控制ID是114。你确定WinSpector给了你10进制的值吗?因为您正在将它作为一个以10为基数的数字馈送给GetDlgItem。我使用Spy++来实现这一点,它在base 16中返回控件ID。在这种情况下,您将使用:

IntPtr boxHwnd = GetDlgItem(hWnd, 0x0114);

你确定你传递的文本正确吗?SendMessage last param应该是指向包含要设置的文本的char*的指针。
看看我的“粗糙的黑客”设置文本

这是在Delphi 5中完成的,其中PChar是char*alias,我只是将其转换为int(Delphi中的整数)。

您必须确保在外部应用程序的内存空间中分配了“text”。您将无法在调用者应用程序中分配文本并将其传递给另一个应用程序,因为每个应用程序都有自己的专用内存空间。

请将您的控件id(从spy++)从十六进制数转换为十进制数,并将该值传递给GetDlgItem函数。使用此
你将得到文本框的句柄。这对我很有用

[DllImport("user32.dll")]
static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int Param, string s);

const int WM_SETTEXT = 0x000c;

private void SetTextt(IntPtr hWnd, string text)
{
    IntPtr boxHwnd = GetDlgItem(hWnd, 114);
    SendMessage(boxHwnd, WM_SETTEXT, 0, text);
}

WinSpector返回以10为基数的数字。我用Visual Studio制作了一个小的测试应用程序,这种技术工作得很好,但它不适用于我正在使用的实际应用程序。当您使用实际应用程序单步执行代码时,GetDlgItem()是否返回非零值?是的,它返回,我可以使用WM_GETTEXT从中获取现有文本。只是WM_SETTEXT不起作用。如果我建议的是明显的事情,很抱歉,但有时候把这些事情说出来是好的。我想下一步我会尝试改变一些东西,比如主窗口的标题栏文本(如果有),看看我是否可以改变它——换句话说,改变一个很可能没有被程序修改的窗口的窗口文本。如果可行,那么在窗口中尝试一些静态控件的文本,如标签。如果这两种方法都有效,它将向我表明程序正在以一种不寻常的方式处理该文本框。继续…我还将尝试使用Spy++(或任何您喜欢的工具)查看textbox控件,以查看它接收到的消息。您应该能够验证文本框是否正在接收WM_SETTEXT,以及程序是否正在发送可能覆盖您操作的内容。