在外部应用程序中设置文本框的文本。Win32 API。

4
使用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);
    }
4个回答

8
以下是我成功使用的代码,已经删除/禁用了我的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 *)的帖子中发表评论,但这并不是必要的。请参见p/Invoke SendMessage中的第二个C#重载。你可以直接将String或StringBuilder传递到SendMessage中。
我还注意到你说你的控件ID是114。你确定WinSpector以十进制给出了该值吗?因为你正在将其作为十进制数输入到GetDlgItem中。我使用Spy++进行此操作,它以十六进制返回控件ID。在这种情况下,你应该使用:
IntPtr boxHwnd = GetDlgItem(hWnd, 0x0114);

1
是的,可以使用WM_GETTEXT从中获取现有文本。只是WM_SETTEXT无法正常工作。 - Kirschstein
1
抱歉如果我说了一些显而易见的事情,但有时候把这些事情说出来是好的。我认为接下来我会尝试改变主窗口的标题栏文本(如果有的话),看看是否可以更改它 - 换句话说,更改程序最可能没有被修改的窗口的窗口文本。 如果这样行得通,那么尝试在窗口中使用静态控件(如标签)的一些文本。 如果这两者都有效,那么对我来说就意味着该程序正在以不寻常的方式处理该文本框。继续... - Gregyski
@Greg:谢谢你分享这个宝贵的信息!SetLastError = false,真是让人惊讶啊...哈哈! :D - Jörgen Sigvardsson
在Spy++中,您从哪里获取控件ID?我遇到了同样的问题,需要更多地进行调试。 - Dean Hiller
有两种方法:1)在提供的列表中手动查找窗口(或在较新的Spy++中使用“Window Search”),然后右键单击并选择“属性”。2)使用“查找窗口”工具(不要将其与“日志”或“日志消息”命令混淆,它也具有窗口选择器控件)。单击控件,然后单击“确定”。无论哪种情况,您都将获得窗口的属性对话框,并且“Control ID”将显示在“Instance Handle”和“User Data”之间。 - Gregyski
显示剩余4条评论

2
请将从Spy++获取的控件ID从十六进制转换为十进制,并将该值传递给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);
}

0

你确定你传递的文本是正确的吗?SendMessage 的最后一个参数应该是指向 char* 类型的指针,其中包含你想要设置的文本。
看看我在 Delphi 5 中如何从 TDBGrid 获取选定单元格 中设置文本的“粗略 hack”。
这是在 Delphi 5 中完成的,其中 PChar 是 char* 的别名,我只是将其强制转换为 int(在 Delphi 中为 Integer)。


0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接