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

jas*_*onk 6 c# vb6 wpf interop vb6-migration

我目前正在探索使用C#将一些旧的VB6应用程序移植到WPF的选项.第一阶段的计划是移植几个关键形式而不是所有应用程序.理论上的目标是通过ActiveX dll在WPF中的某种容器中打开VB6表单.

这甚至可能吗?我试过看Interop并且似乎找不到一个可靠的例子,说明如何使用Win32控件,而不是完整的表单.我可以完全访问旧的VB6代码,并且无论如何都可以修改它.

主WPF应用程序的以下屏幕截图将用作包装器/容器:

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

当前VB6维护屏幕将加载到上一屏幕右侧的"空白区域"部分.

jas*_*onk 11

我能够通过以下步骤完成任务:

  1. 创建了一个新的VB6 Active X控件项目.将VB6表单控件和代码的全部内容复制并粘贴到新控件中.切换到控件时必须处理几个元素:

    1. 你失去了以前一种方式显示表单标题的能力.您可以使用备用控件(label/borderlesstextbox等)来解决它,如果需要,可以实现相同的功能.这不是优先事项,因为每个屏幕都在我们新的.Net项目中的标签系统等浏览器中托管.

    2. 必须将所有鼠标指针引用从Me.Mousepointer更改为Screen.mousepointer

    3. 您不能使用Me.Hide并且必须交替事件来隐藏.Net容器.

    4. 任何和所有对我的引用.[任何]必须被删除或用UserControl替换.[任何]如果适用的话.

    5. 如果您在表单上使用任何引用[yourcontrol] .Contianer.Property的函数,则需要将其更改为循环访问UserControl.Controls集合,而"Container"对于vb6 ActiveX控件无效

    6. 必须从项目中删除所有非模态窗体/对话框,因为在WPF中现在没有要处理的Hwnd.您收到错误"无法从ActiveX DLL,ActiveX控件或属性页中显示此主机应用程序中的非模态窗体".在我们的例子中,我们有一个简单的启动屏幕,当显示某些长流程/报告时,它会显示,以便让用户知道正在运行的内容.

  2. 我无法通过互操作直接将VB6控件添加到WPF项目中.因此,创建了一个新的.Net"Windows窗体控制库"项目.项目中添加了对VB6 OCX的引用.然后通过"右键单击" - >"添加项目"将VB6控件添加到.Net工具箱,并将com引用指向VB6控件ocx.然后使用.Net控件来托管/提供VB6控件.

  3. 为了在VB6中显示主机表格并使其启动必要的初始化功能,VB6 OCX控件以Visible.False方式默认,因此它们最初作为隐形控件添加到.Net OCX中.需要时,VB6控件设置为visible = True,触发UserControl_Show()事件.之前在Form_Load()中的所有代码都已移至此事件.show事件是根据需要访问Form_Load的最简单方法.MSDN:"如果窗体被隐藏然后再次显示,或者窗体最小化然后恢复,则控件不会收到Show事件.在这些操作期间,控件的窗口仍保留在窗体上,其Visible属性不会改变."

  4. 在.Net Winform控件中包装vb6控件解决了Radio/Option按钮呈现为黑色的问题,如我对此问题的一个回答中所述,而不必按照建议将帧转换为图片框.

  5. 在WPF应用程序中,选择菜单选项时,xaml代码将通过带有WindowsFormsHost标记的包装器动态创建和显示.然后,来自.Net winform应用程序的动态创建的控制对象被推送到xaml上的WindowsFormsHost标记中,并且该控件在.net项目上可见,该项目将触发vb6 UserControl_Show,然后加载并显示vb6表单.