【问题标题】:SendMessage WM_SETTEXT to TextBox doesn't trigger TextChanged EventSendMessage WM_SETTEXT 到 TextBox 不会触发 TextChanged 事件
【发布时间】:2013-10-27 23:57:09
【问题描述】:

我有获取文本框控件句柄并使用 Windows API 更改文本的代码。 文本更新时不会触发 TextChanged 事件。

有没有办法使用 Windows API 触发 TextBox.TextChanged 事件?

[更新]
我认为事件不触发的原因是因为文本框句柄是通过 DCOM 接口发送的。 该程序是一个用 c# 编写的 National Instruments TestStand shell,并使用 NI TestStand COM 对象来实现核心功能。在 TS 序列文件(一种 TS 脚本语言)中,我为文本框句柄创建了一个对象引用,并在 shell 表单的加载事件中使用 TS api 设置它。之后,我将句柄发送到我的 c# DLL。我使用 SendMessage 来更新文本框,效果很好。问题是 TextChanged 事件没有触发。

我尝试使用 TS 接口发送文本框和 TextChanged 委托,但无法正常工作。我认为通过 TS COM 对象执行此操作存在 AppDomain 问题。

【问题讨论】:

    标签: c# winapi


    【解决方案1】:

    正如这个程序所证明的那样,当控件收到WM_SETTEXT 消息时,TextChanged 事件确实会触发。

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            const uint WM_SETTEXT = 0x000C;
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            static extern IntPtr SendMessage(IntPtr hWnd, unit Msg, 
                IntPtr wParam, string lParam);
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void textBox1_TextChanged(object sender, EventArgs e)
            {
                MessageBox.Show(textBox1.Text);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                SendMessage(textBox1.Handle, WM_SETTEXT, IntPtr.Zero,
                  textBox1.Text + ", " + textBox1.Text);
            }
        }
    }
    

    请注意,答案的原始版本过于复杂,并使用了SendMessage,如下所示:

    static extern IntPtr SendMessage(IntPtr hWnd, unit Msg, 
      IntPtr wParam, IntPtr lParam);
    

    因此必须执行手动编组:

    IntPtr text = Marshal.StringToCoTaskMemUni(textBox1.Text + ", "
      + textBox1.Text);
    SendMessage(textBox1.Handle, WM_SETTEXT, IntPtr.Zero, text);
    Marshal.FreeCoTaskMem(text);
    

    对这个问题的评论 (Automatic casting for string DllImport arguments vs Marshal.StringToCoTaskMemUni) 说服我更新。

    【讨论】:

    • 我有个问题,为什么不用Marshal.StringToHGlobalUni
    • @AppDeveloper 你也可以使用它。无论如何都无所谓。我倾向于使用 pinvoke 来使用 COM 堆,因为如果编组器确实解除分配,那么它会使用 COM 堆。
    • 抱歉,只是为了好奇,COM 堆与普通的非托管内存指针有何不同?
    • @AppDeveloper 这只是一个不同的堆。它还分配一个非托管指针。从概念上讲,它们是相同的。任何进程都可以从 COM 堆进行分配,然后同一进程中的任何其他代码都可以将该内存释放回公共共享堆。对于 HGlobal 堆也是如此。应该是真名了吧!还有其他堆。您可以 p/invoke HeapAlloc。还有VirtualAlloc。堆积如山!
    • 如果目标应用程序(带有 textBox1)是另一个应用程序,此示例将如何变化?
    【解决方案2】:

    我不确定您要更改什么文本,但我在文本框中使用了 PostMessages 和按键(用于数字)的组合,它触发了 TextChangedEvent。

    this的方法二。它基本上将鼠标设置为单击文本框,然后将您想要的文本的按键发送到文本框(逐个字母)。

    【讨论】:

      猜你喜欢
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 1970-01-01
      相关资源
      最近更新 更多