Windows窗体作为非托管应用程序的子窗口

时间:2012-11-14 14:59:50

标签: c# c++ winapi clr

我正在寻找一种在C ++ Windows应用程序中嵌入用C#编写的Windows窗体应用程序的方法。本机应用程序主窗口细分为多个窗格。 C#app应该出现在其中一个窗格中,即C#组件的根窗口(最外面的窗体)必须是主应用程序的子窗口。

可以这样做吗?如果是这样,怎么样?

一些额外的背景:据我所知,有两种方法可以解决这个问题。首先,使用.net托管API(ICLRRuntimeHost等)在本机应用程序中托管CLR。其次,通过将Windows窗体放在ActiveX控件中来托管CLR。

关于第一种方法,我设法启动了CLR并加载了一个C#程序集(主要归功于Mattias Högström)。在我遇到障碍的地方是,我认为如何判断我在CLR中运行的组件是否需要成为从C ++端传入的窗口的子项。

我还尝试了第二种方法(使用ActiveX并感谢Daniel Yanovsky)。它几乎,但只是差不多,适合我的目的。我可以让任意Windows窗体组件在本机应用程序的子窗格中运行。但它们总是在主应用程序的主线程上运行。这意味着他们使用主应用程序的Windows消息循环。 MSDN说这不会可靠地工作,因为标准的Windows消息循环不符合Windows窗体的要求(我想在这里发布到MSDN的链接,但已经用完了我的新用户双链接分配)。 / p>

根据MSDN,Internet Explorer和MFC应用程序的消息循环问题的例外情况。我作为主机使用的本机应用程序绝对不是Internet Explorer。此外,它使用由wxWidgets包装的Windows API,因此MFC不是(或至少不是受欢迎的)选项。

Microsoft提出的解决方案涉及让C#组件在自己的线程上运行自己的消息循环。至少据我所知,这必然会导致回到上面提到的第一种方法。所以我回到了让Windows窗体在传入的父窗口下工作的问题。

同样,我对任何澄清子窗口问题的输入感兴趣,与我在此处提到的方法无关。但根据上下文,我可以将一般性问题简化为两个具体问题(我只需要回答其中一个问题):

  • 鉴于ActiveX控件中托管的Windows窗体,如何允许窗体在其自己的线程上的自己的消息循环中运行?

  • 鉴于在本机应用程序托管的CLR中运行的Windows窗体,如何使该窗体成为本机应用程序中窗口的子窗口?

1 个答案:

答案 0 :(得分:1)

是的,可以做到。几年前我们做了同样的事情。这是我们的方法:.NET控件也有本机窗口句柄,我们通过C ++ / CLI获取这些句柄并将它们传递给Win32,并将这些句柄添加为本机窗口的子句。因此,.NET控件在主应用程序的主线程上运行,有问题的部分是消息循环,正如您在问题中提到的那样。如果需要,我们需要在国家和.NET窗口之间路由消息。正如我记得的那样,我们修复了很多与此相关的错误,但仍有一些我们没想到的神秘问题。

还有另外一种方法:使用WPF互操作。 http://msdn.microsoft.com/en-us/library/ms742522.aspx。根据MS,这应该解决消息问题,但我们没有尝试这种方法。您可以使用Win32来托管WPF,然后使用WPF来托管Winform。

所以最后两个问题:

  1. 你不能。只有一个消息循环。
  2. 使用手柄。本文讨论Windows窗体的句柄:http://blogs.msdn.com/b/jfoscoding/archive/2004/11/24/269416.aspx