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

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

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

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

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

或者我还有其他选择吗?

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

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

1)产品的未来发展

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

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

2)员工保留和招聘

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

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

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

这是我采取的方法的关键部分的快速概述:

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

作为旁注,我们使用了Divelements的SandDock和SandRibbon, 到目前为止他们对它们非常满意。

我不认为有一种更简单的方法,你没有涉及,虽然它可能很大程度上取决于底层逻辑与UI层的分离程度。

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

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

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

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

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

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

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