将大型MFC应用程序迁移到WPF / .NET有哪些技巧?

时间:2009-05-07 19:20:03

标签: c# .net c++ wpf mfc

我目前正在开发一个非常大的传统MFC MDI应用程序。它有大量的UI元素 - 可停靠的工具栏,自定义树控件,上下文菜单等。它是一个图像处理应用程序,因此主视图使用DirectX和OpenGL自我渲染。该产品大约有10年的历史,其中一个优先事项是更新它的外观和感觉。

知道Microsoft在提供C ++ / MFC和.NET之间的互操作性方面做得很好我认为以递增方式迁移代码库是有意义的。我现在正在努力的是从哪里开始。

一种方法是使用WPF删除MFC框架并尽可能多地重用C ++代码。这将使我们最大限度地发挥WPF架构的优势,但这将意味着一个漫长的开发阶段,直到我们再次完全正常运行。

另一种方法是使用WPF对应方法逐个替换MFC控件。这将允许我们以增量方式工作。我对这种方法的关注是,这意味着托管和非托管代码之间会有很多连接点,我不知道从哪里开始替换主菜单和工具栏等。

或者我还有其他选择吗?

任何有关此主题信息的建议或链接都​​将不胜感激。

更新:DavidK提出了一些很好的问题,所以我正在添加动机。

1)产品的未来发展

此产品仍在积极开发中,并定期添加新功能。我认为尝试慢慢迁移到C#/ WPF会很有意义。凭借我在C#/ WPF方面的有限经验,我发现在C ++ / MFC中工作效率会提高。

我们用WPF获得的另一件大事就是能够利用多头系统。 MFC应用程序仅限于单个顶级框架,因此很难利用多个监视器。

2)员工保留和招聘

找到愿意使用MFC的开发人员变得越来越难。对于当前开发人员的职业发展而言,接触新技术也很重要。

5 个答案:

答案 0 :(得分:9)

重新审视这个,因为我已成功用WPF替换了我们的顶级MFC UI(主框架,窗口和工具栏)。

事实证明,我们的核心绘图代码只需要交给HWND进行渲染。这使得重用大量现有C ++代码库变得非常容易。

以下是我采用的方法的关键部分的简要说明:

  • 使用.NET HwndHost类来托管要转换为C ++绘图代码的HWND
  • 为需要向WPF / C#UI代码公开的任何本机C ++代码创建C ++ / CLI包装器
  • 将大部分MFC对话框保留为本机C ++代码中的原样。这最大限度地减少了完成UI所需的工作量。 MFC对话框可以随着时间的推移迁移到WPF。

作为旁注,我们正在使用来自Divelements的SandDock和SandRibbon,并且到目前为止对它们非常满意。

答案 1 :(得分:3)

我认为没有更简单的方法可以覆盖,尽管它可能很大程度上取决于底层逻辑与UI层的分离程度。

不希望看起来很消极:你确定这值得努力吗?如果我从头开始编写一个大型应用程序,我现在不会从C ++和MFC开始,但是看看你在哪里,你会从重写它中获得什么?这会增加一个用户将支付的新功能吗?是否有任何用户会被切断谁将无法运行新版本?我不禁怀疑你会从一些相对简单的事情中获得更大的投资回报,以改善应用程序的外观。例如,它是否有XP风格的清单,以便常见的控件获得XP外观?是否花了几天时间来更新位(例如使用新的样式文件对话框)可以让您获得闪亮的新外观?请记住,即使最新,最闪亮的Office 2007也是由Microsoft使用普通的Win32控件实现的。

答案 2 :(得分:2)

我之前必须在使用WinForms的项目中做同样的事情。我们需要将我们的MFC项目迁移到.NET 1.1,我们决定采用MFC应用程序的所有核心功能,并围绕所有这些功能编写托管包装器。然后我们写了一个WinForms前端并逐位插入遗留的c ++代码。我认为从长远来看,我们做出了正确的选择。如果我们试图同时保留MFC前端,我无法想象我们会怎么做。

答案 3 :(得分:2)

FWIW,在此期间,您可以使用MFC功能包(可与VS2008 SP1一起使用)为您的应用程序提供快速的Office 2007外观(如果您的用户愿意,您甚至可以添加功能区)这将更加复杂。)我在一天内使用这些新类改进了一个旧的MFC应用程序的UI,现在,公平地说,它看起来很棒,我的用户非常高兴(你可以支持一大堆外观和色彩方案。)MS选择了BCG工具包,但是如果你想支付少量的钱,还有其他的可用(例如CodeJock)。

我知道这不能回答你的问题,但是如果它只是用户界面的变化,那么你可能值得一看。

答案 4 :(得分:1)

我认为你已经很好地处理了这些策略。请注意,迁移到WPF的一个潜在痛点是并非每个控件都有句柄。遗憾的是,这是最笨拙的互操作性方案。 AFAIK是与MFC和WPF互操作的唯一方法是通过WindowsFormsHost。 WPF范例也与MFC / WinForms截然不同,因此可能存在一些翻译问题。

鉴于您的大型但功能强大的遗留代码库,我可能会支持您的第二种方法。一次从一个控件开始并使其成为WPF-y。在新的托管控件和底层代码库之间创建一个定义良好的接口,然后针对该接口进行操作。如果你一次只做一次,那么你将会处理一个风险较低的风险:WPF的学习曲线(非常陡峭,非常好)。

我觉得重要的是要注意,如果您要使用WinForms,我可能会建议使用前一种方法。更接近的范式和相对平滑的学习曲线将更容易通过一次性工作。