简体   繁体   English

您可以/如何在C#WPF应用程序中托管完整的VB6表单?

[英]Can/how do you host a full VB6 Form in a C# WPF app?

I am currently exploring the option of porting some older VB6 application to WPF with C#. 我目前正在探索使用C#将一些较旧的VB6应用程序移植到WPF的选项。 The plan, in phase one, is to port several key forms and not all the application. 第一阶段的计划是移植几种关键形式,而不是全部应用程序。 The theoretical goal is to open the VB6 form in a container of some sort within WPF via an ActiveX dll. 理论上的目标是通过ActiveX dll在WPF中的某种容器中打开VB6表单。

Is this even possible? 这有可能吗? I've tried looking at the Interop and can't seem to find a solid example of how get it to work with anything but Win32 controls, not a full form. 我尝试查看Interop,但似乎找不到一个可靠的示例说明如何使其与Win32控件(而不是完整格式)一起使用。 I have full access to the old VB6 code and can modify it in anyway needed. 我可以完全访问旧的VB6代码,并可以根据需要进行修改。

The following screenshot of the main WPF app would serve as the wrapper/container: WPF主应用程序的以下屏幕截图将用作包装器/容器:

http://www.evocommand.com/junk_delete_me/main_menu_mockup.png http://www.evocommand.com/junk_delete_me/main_menu_mockup.png

The current VB6 maintenance screen that would be loaded in the “white space” section on the right side of the previous screen. 当前的VB6维护屏幕,该屏幕将加载到前一屏幕右侧的“空白”部分。

I was able to accomplish the task with the following steps: 我可以通过以下步骤完成任务:

  1. Created a new VB6 Active X Control Project. 创建了一个新的VB6 Active X控件项目。 Copied and pasted the entire contents of the VB6 form controls and code behind into the new control. 将VB6表单控件和代码的全部内容复制并粘贴到新控件中。 There are several elements that have to be handled in switching to a control: 切换到控件时必须处理几个元素:

    1. you lose the ability to display the caption of the form in the previous manner. 您将无法以以前的方式显示表单的标题。 You can work around it with alternate controls (label/borderlesstextbox, etc) that accomplish the same functionality if needed. 您可以使用替代控件(标签/无边框文本框等)来解决此问题,这些控件在需要时可以实现相同的功能。 This wasn't a priority since each screen was being hosted in a browser like tab system in our new .Net project. 这不是优先事项,因为每个屏幕都托管在我们新的.Net项目中的选项卡系统之类的浏览器中。

    2. All mousepointer references have to be changed from Me.Mousepointer to Screen.mousepointer 必须将所有鼠标指针引用从Me.Mousepointer更改为Screen.mousepointer

    3. You cannot use Me.Hide and have to alternate events to hide the .Net container. 您不能使用Me.Hide,而必须替换事件以隐藏.Net容器。

    4. Any and all references to Me.[anything] have to be removed or replaced with UserControl.[anything] if they are applicable. 如果适用,对Me。[anything]的任何和所有引用都必须删除或替换为UserControl。[anything]。

    5. If you use any functions that reference a [yourcontrol].Contianer.Property on a form they will need to be altered to loop through the UserControl.Controls collection instead and “Container” is invalid for vb6 ActiveX controls 如果您在表单上使用任何引用[yourcontrol] .Contianer.Property的函数,则需要对其进行更改以遍历UserControl.Controls集合,并且“容器”对vb6 ActiveX控件无效

    6. All non-modal forms/dialog boxes must be removed from the project as there is now no Hwnd to handle in WPF. 由于现在WPF中没有要处理的Hwnd,因此必须从项目中删除所有非模式窗体/对话框。 You get an error of 'Non-modal forms cannot be displayed in this host application from an ActiveX DLL, ActiveX Control, or Property page'. 您收到错误消息“无法从ActiveX DLL,ActiveX控件或属性页面在此主机应用程序中显示非模式形式”。 In our case we had a simple splash screen that would display when certain long processes/reports displayed to let the user know what was running. 在我们的案例中,我们有一个简单的启动屏幕,当显示某些较长的进程/报告时将显示该屏幕,以使用户知道正在运行什么。

  2. I was unable to directly add the VB6 control via the interop to a WPF project . 我无法通过互操作将VB6控件直接添加到WPF项目。 As such a new .Net “Windows Form Control Library” project was created. 因此,创建了一个新的.Net“ Windows窗体控件库”项目。 A reference to the VB6 OCX was added to the project. 对VB6 OCX的引用已添加到项目中。 The VB6 Control s were then added to the .Net toolbox by “right click” –> “Add Item” and pointing a com reference to the VB6 control ocx. 然后通过“右键单击”->“添加项目”并将VB6控件ocx指向com引用,将VB6控件添加到.Net工具箱。 The .Net control was then used to host/serve the VB6 Control. 然后,使用.Net控件托管/服务VB6控件。

  3. To display host a form in the VB6 and get it to fire the necessary initialization functionality the VB6 OCX controls were defaulted in a Visible.False manner so they were initially added to the .Net OCX as invisible controls. 为了在VB6中显示宿主窗体并使其激发必要的初始化功能,VB6 OCX控件默认以Visible.False方式默认,因此它们最初是作为不可见控件添加到.Net OCX的。 When needed the VB6 control is set to visible = True which fires the UserControl_Show() event. 必要时,将VB6控件设置为visible = True,这将触发UserControl_Show()事件。 All code formerly in Form_Load() was moved to this event. 以前在Form_Load()中的所有代码都移到了此事件。 The show event was the easiest method of accessing the Form_Load as needed. show事件是根据需要访问Form_Load的最简单方法。 MSDN: “The control does not receive Show events if the form is hidden and then shown again, or if the form is minimized and then restored. MSDN:“如果窗体被隐藏然后再次显示,或者窗体被最小化然后还原,则控件不会接收Show事件。 The control's window remains on the form during these operations, and its Visible property doesn't change.” 在执行这些操作期间,控件的窗口将保留在窗体上,并且其Visible属性不会更改。”

  4. Wrapping the vb6 controls within a .Net Winform control resolved the issue with Radio/Option buttons being rendered as black as outlined elsewhere in one of my responses to this question without having to convert the frames to Picture boxes as suggested. 将vb6控件包装在.Net Winform控件中解决了此问题,单选按钮/选项按钮被渲染为黑色(如我对此问题的回答之一中其他地方所述),而无需按照建议将帧转换为图片框。

  5. In the WPF app as a menu choice is selected xaml code is dynamically created and displayed via a wrapper with a WindowsFormsHost tag. 在WPF应用程序中,通过菜单选项选择xaml代码是通过带有WindowsFormsHost标记的包装动态创建和显示的。 A dynamically created control object from the .Net winform app is then pushed into the WindowsFormsHost tag on the xaml and the control is made visible on the .net project which fires vb6 UserControl_Show and then load and display of the vb6 form. 然后,将来自.Net winform应用程序的动态创建的控件对象放入xaml的WindowsFormsHost标记中,并使该控件在.net项目中可见,从而触发vb6 UserControl_Show,然后加载并显示vb6表单。

I think what you will have to do is extract the VB6 form contents into an ActiveX control. 我认为您要做的是将VB6表单内容提取到ActiveX控件中。 You can then expose this in your ActiveX dll and place that in your WPF form. 然后,您可以在ActiveX dll中公开它,并将其放在WPF表单中。 I doubt it's possible to host a VB6 form within any other type of form. 我怀疑是否可以在任何其他类型的表单中托管VB6表单。

Can you even load that VB6 form in another VB6 form? 您甚至可以将该VB6表单加载到另一个VB6表单中吗? I suggest you get that working first. 我建议您首先开始工作。

There is no reliable way to set parent of a VB6 form. 没有可靠的方法来设置VB6表单的父级。 You can always hack it or use plain ActiveX control (UserControl in VB6) as UI container instead of VB6 forms. 您始终可以修改它,也可以将普通的ActiveX控件(VB6中为UserControl)用作UI容器而不是VB6表单。

I found a method to do what was needed within WinForms rather than WPF at this point. 在这一点上,我找到了一种在WinForms中而不是WPF中执行所需工作的方法。 http://www.codeproject.com/KB/vb-interop/VB6formsinNET.aspx I figure if I can get it working 100% there I can port it over to WPF or worse case host the WinForm element in the WPF form if I absolutely have too ( UGLY ). http://www.codeproject.com/KB/vb-interop/VB6formsinNET.aspx我想知道如果我能使它100%工作,我可以将其移植到WPF或更糟的情况下,如果我以WPF形式托管WinForm元素绝对也有( 丑陋 )。

Anyway, I've gotten a bit closer, but am having a very odd issue with certain controls painting too the screen. 无论如何,我已经走得更近了,但是某些控件也在绘制屏幕时遇到了一个非常奇怪的问题。 Radio/Option buttons are rendering as solid black: 单选/选项按钮呈现为纯黑色:

http://www.evocommand.com/junk_delete_me/optionbuttons.png http://www.evocommand.com/junk_delete_me/optionbuttons.png

I've tried explicitly changing the controls' background color from buttonface to a fixed color and it still does it. 我尝试过将控件的背景颜色从按钮表面显式更改为固定颜色,并且仍然可以。 I'm assuming it's a layering issue with the option buttons being within the frame control. 我假设这是一个分层问题,其中选项按钮位于帧控件内。 I'm at a bit of a loss on how to proceed without massive rework of the VB6 content to change the options buttons to checkboxes. 如果不进行大量的VB6内容更改以将选项按钮更改为复选框,我将不知所措。 It's a hefty app and there are 600+ option button controls across the application that I don't exactly want to deal with. 这是一个庞大的应用程序,整个应用程序中有600多个我不想处理的选项按钮控件。

EDIT: I was able to confirm it has something to do with the layering of the option within a Frame control. 编辑:我能够确认它与框架控件中选项的分层有关。 If pulled out to the base form the issue does not occur: http://www.evocommand.com/junk_delete_me/optionbuttons2.png 如果将其拉出至基本表单,则不会发生此问题: http : //www.evocommand.com/junk_delete_me/optionbuttons2.png

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM