WinForm 在创建之后才收到消息

Posted

技术标签:

【中文标题】WinForm 在创建之后才收到消息【英文标题】:WinForm not receiving messages except right after creation 【发布时间】:2009-07-13 02:09:09 【问题描述】:

我有一些非托管代码位于 DLL 中。它发布了一些方法,我的调用(托管)代码用来挂钩某些 COM 通知。我没有处理调用回托管代码的非托管代码,而是创建了一个隐藏的 Control 派生对象,并将其句柄属性传递给非托管代码,然后将其用作 SendMessage 的参数。

我的控件派生类:

class InteropWindow : Control

  //delegate 
  private Handler m_callback;
  //window message
  private uint m_message;

  public InteropWindow(Handler callback, uint message)
    : base() 
  
    m_callback = callback;
    m_message = message;
  

  protected override void WndProc(ref Message m)
  
    if (m.Msg == m_message)
    
      m_callback(new IntPtr((int)m.WParam));
    

    base.WndProc(ref m);
  

非托管代码中的相关行:

SendMessage(m_notify, m_window_message, (WPARAM)pData, 0);

m_window_message 和 m_message 相同(均来自 RegisterWindowMessage),并且 m_notify == InteropWindow.Handle(pData 有所不同,但在托管代码中用作不透明句柄)。正在调用非托管代码。这些事实已经通过调试得到证实。

创建 InteropWindow 后不久,对 SendMessage 的调用成功。之后(几秒钟后)消息停止到达 WndProc,尽管没有任何错误迹象。

问题是,我在这里做错了什么?


我已经排除了生命周期问题(据我所知),并且使用 HandleRef 无济于事。


编辑第二个。

我已经重写了它以改用函数调用,虽然它充满了自己的危险,但它的工作方式更像我的预期。我开始怀疑这是一个 COM 线程问题,但这只是直觉。

【问题讨论】:

【参考方案1】:

您是否尝试将托管窗口的句柄作为 HandleRef 传递? C# 可以将 HandleRef 编组为 IntPtr,反之亦然,我已经看到微软在反编译他们的一些东西时使用了这个技巧。

您还可以加载 .Net 分析器并观察 GC。很高兴知道您的应用在收集后是否立即崩溃。

【讨论】:

我已通过 GC 确认句柄保持有效;或者,至少,绝对没有迹象表明它会变得无效。没有调用 Control.HandleDestroyed,没有使用时的无效句柄警告,没有任何地方的第一次机会异常,什么都没有。 您可以尝试在您的 COM 对象上创建一个事件吗?我一直是托管方的订户,它可能是一个更简单的解决方案。但是,我不确定如何在 COM/非托管端进行事件。

以上是关于WinForm 在创建之后才收到消息的主要内容,如果未能解决你的问题,请参考以下文章

.net WinForm 有没有定义好的在显示完窗体之后才发生的事件啊?

C#中去掉winform边框如何拖动

WinForm,消息框怎样显示在窗体正中?

VC安装完成之后,新建项目打开Winform窗体无法显示设计窗体。

winform listview控件容器控件

求 在C#中winform窗体中的所有好看提示方式的消息盒子