【问题标题】:How to get Handle of a form that hosts a COM-Control如何获取承载 COM 控件的表单的句柄
【发布时间】:2015-02-10 01:05:52
【问题描述】:

我有一个可视的 DotNet-Control,我在 Delphi 项目中用作 COM-Control。
现在我想获得在 DotNet 中托管这个 DotNet 组件的 delphi 表单的句柄。 当然 - 我可以使用 setParentHandle(pHandle: hwnd); 之类的东西将表单的句柄从 Delphi 传递到 DotNet;我定义的方法,但这不是我想在这里做的方式。

是否有任何 Winapi 调用可以为我提供我在 DotNet 中绘制的组件的句柄?

我想使用此句柄将 DotNetComponent 本身无法处理的消息发送到 Delphi 表单。

【问题讨论】:

  • 您能否准确说明您的 .net 代码中的内容。您的 .net 组件是从哪个类派生的?这是托管在您的 Delphi 应用程序中的组件。
  • dotnet组件基本上是从UserControl派生的。我将其用作图表组件的容器。但是我无法在我的 C# 代码中访问托管的 Delphi 表单(实际上我只需要句柄)。
  • System.Windows.Forms.UserControlSystem.Windows.Controls.UserControl?
  • 当你的这个图表组件被创建时,它可能会创建自己的窗口,对吧?那么你为什么不简单地检查哪个窗口是你的这个窗口的父窗口呢?但是,如果您的组件没有创建自己的窗口怎么办?然后必须先将现有窗口的句柄传递给它,以便它知道应该将其内容呈现到哪里。那就用那个手柄吧。
  • 如果你想要的只是父级的窗口句柄,你不能用控件的窗口句柄调用GetParent吗?

标签: .net delphi winapi com sendmessage


【解决方案1】:

通常,当宿主窗口包含可视 ActiveX 控件时,宿主实现 IOleClientSite 接口并通过其 IOleObject::SetClientSite() 实现将其传递给控件。控件可以在IOleClientSite 中查询IOleWindowIOleInPlaceSite 并调用其GetWindow() 方法来获取主机的HWND。

我不知道IOleObject 在.NET 层是如何实现的,但这就是COM/ActiveX 层的工作方式。因此,.NET 控件可能有一种方法可以覆盖其自己的SetClientSite() 方法,或提供其他方法来访问主机的IOleClientSite 接口。

【讨论】:

    【解决方案2】:

    我在 C# 中使用 WinApi 的 GetParent 方法解决了这个问题。

    [DllImport("user32.dll")]
    private static extern IntPtr GetParent(IntPtr hWnd);
    
    protected override void WndProc(ref Message m){
    
        // 0x20a is the Message constant for WM_MOUSEWHEEL (Scrolling on your control)
        if(m.Msg == 0x20a){
          IntPtr hWnd= GetParent(this.Handle);
          SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
        }
        else
            base.WndProc(ref m);
    }
    

    备注:将所有消息转发到父控件会破坏您的控件,因为它不再接收自己的消息。

    【讨论】:

    • 此代码将破坏您的控制,因为它不会收到它的消息。
    • 哦,谢谢,你是对的。在我的生产代码中,我在将消息发送到父控件之前对消息进行了预过滤,例如使用if(m.Msg = 0x20a)。但是我需要 GetParent 方法来获取我的控件的父窗口的句柄。
    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多