Windows窗体作为非托管应用程序的子窗口 [英] Windows Form as child window of an unmanaged app

查看:167
本文介绍了Windows窗体作为非托管应用程序的子窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这可以做吗?如果是,如何?



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



关于第一种方法,我已经设法让CLR启动并加载一个C#程序集(主要是因为 MattiasHögström)。在我碰到一个路障是,我看不到如何告诉我在CLR中运行的组件,它需要是一个窗口从C ++传递的窗口的孩子。



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



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



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



同样,我对任何澄清子窗口的输入感兴趣问题,独立于我在这里提到的方法。但鉴于上下文,我可以将一般问题减少到两个具体问题(我只需要一个答案):




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






  • 如果在由原生应用程序托管的CLR中运行Windows窗体,如何使窗体成为子窗口

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



有一种方法:使用WPF interop 。 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


I am looking for a way to embed Windows Forms applications written in C# in a C++ windows application. The native application main window is subdivided into several panes. The C# app is supposed to appear within one of those panes, i.e. the root window of the C# component (the outermost form) must be a child window of the main application.

Can this be done? If so, how?

Some additional context: To my knowledge, there are two ways to go about this. First, host the CLR in the native app by using the .net hosting APIs (ICLRRuntimeHost, etc.). Second, host the CLR by putting the windows form in an ActiveX control.

Regarding the first approach, I have managed to get the CLR started up and to load a C# assembly (thanks largely to Mattias Högström). Where I am hitting a road block is that I see no way how to tell the component I am running in the CLR that it needs to be a child of a window passed in from the C++ side.

I have also experimented with the second method (using ActiveX and thanks to Daniel Yanovsky). It almost, but only almost, works for my purposes. I can let arbitrary Windows Forms components run in a child pane of the native app. BUT they always run on the main thread of the main app. This means they use the windows message loop of the main app. MSDN says this will not work reliably since the standard Windows message loops don't meet the requirements of Windows Forms (I wanted to post the link to MSDN here but have already used up my new-user-two-link-allotment).

The exceptions to the message loop issue are, according to MSDN, Internet Explorer and MFC apps. The native app I am using as a host is definitely not Internet Explorer. Also, it uses the windows API as wrapped by wxWidgets so MFC is not (or at least not a welcome) option.

The solutions Microsoft proposes involve letting the C# components run in their own message loops on their own threads. This, at least as far as I can tell, necessarily leads back to the first approach mentioned above. So I am back to the question of getting a Windows Form to work under a passed-in parent window.

Again, I am interested in any input that clarifies the child window issue, independent of the approaches I have mentioned here. But in light of the context I could reduce the general question to two specific questions (and I would need an answer to only one of them):

  • Given a Windows Form hosted in an ActiveX control, how can I allow the form to run in its own message loop on its own thread?

or

  • Given a Windows Form running in a CLR hosted by a native app, how can I make the form be a child window of a window in the native app?

解决方案

yes, it can be done. We did the same thing years ago. This is our approach: .NET control also has native window handle, we get these handles through C++/CLI and pass them to Win32, and add these handles as the children of native windows. So the .NET controls run on the main thread of the main app, the problematic part is the message loop, as you have mentioned in your question. We need route the message between the nation and .NET windows if needed. As I remembered, we fixed a lot of bugs related to this, and still there were some mysterious problem we didn't figure out.

There's anothe way: using WPF interop. http://msdn.microsoft.com/en-us/library/ms742522.aspx . According to MS, this should fix the message problems, but we didn't try this approach. You can just use Win32 to host WPF, then use WPF to host Winform.

So for your last 2 questions:

  1. You can't. Only one message loop.
  2. Use handle. This article talks about the handle of Windows Forms: http://blogs.msdn.com/b/jfoscoding/archive/2004/11/24/269416.aspx

这篇关于Windows窗体作为非托管应用程序的子窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆