30
votes

I am currently working on a very large legacy MFC MDI application. It has a large number of UI elements - dockable toolbars, custom tree controls, context menus, etc. It is an image processing application so the main views render themselves using DirectX and OpenGL. The product is about 10 years old and one of the priorities here is to update the look and feel of it.

Knowing that Microsoft has done a good job of providing interoperability between C++/MFC and .NET I thought it would make sense to migrate the code base incrementally. What I'm struggling with now is where to start.

One approach is to rip out the MFC framework with WPF and reuse as much of the C++ code as we can. This will let us maximize the benefits of the WPF architecture but will mean a long development period until we're fully functional again.

Another approach is to replace MFC controls one at a time with their WPF counterparts. This will allow us to work incrementally. My concern with this approach is that it means there will be an awful lot of connection points between managed and unmanaged code and I'm not sure where to start with replacing things like the main menu and toolbars.

Or is there another option here I'm not seeing?

Any suggestions or links to information on this topic would be appreciated.

Update: DavidK raised some excellent questions so I'm adding the motivations behind this.

1) Future development of the product

This product is still being actively developed with new features getting added on a regular basis. I thought that it would make a lot of sense to try and slowly migrate towards C#/WPF. In my limited experience with C#/WPF I found the productivity gains to be amazing over working in C++/MFC.

The other big thing we're getting with WPF is the ability to take advantage of multi-head systems. MFC applications are limited to a single top level frame, making it very difficult to leverage multiple monitors.

2) Employee retention and recruitment

It's getting harder and harder to find developers who are willing to work on MFC. It's also important for the career development of the current developers to get exposure to newer technologies.

5
I'd give more than one upvote, if I could.Paul Sonier
the ideal migration from MFC is to go with QT; at least then your current developers won't be clamouring to develop using the next cool GUI technology that'll be out in a few years time :)gbjbaanb
The problem with QT is that it's really a lateral move from MFC rather than a leap forward in terms of technology and productivity gains. I see no good reason to go from MFC to QT unless you're looking for a cross-platform solution. For a Windows shop, that move wouldn't make any sense.17 of 26

5 Answers

11
votes

Revisiting this because I have successfully replaced our top level MFC UI (the main frame, windows, and toolbars) with WPF.

As it turns out, our core drawing code merely needs to be handed an HWND to render into. This made it really easy to reuse the bulk of our existing C++ codebase.

Here's a quick rundown on the key pieces of the approach I took:

  • Used the .NET HwndHost class to host an HWND for the C++ drawing code to render into
  • Created C++/CLI wrappers for any native C++ code that needed to be exposed to the WPF/C# UI code
  • Left most of the MFC dialogs as-is in the native C++ code. This minimizes the amount of work needed to finish the UI. The MFC dialogs can be migrated to WPF over time.

As a side note, we're using SandDock and SandRibbon from Divelements and have been very happy with them so far.

3
votes

I don't think there's an easier way that you've not covered, although it will probably depend quite a bit on how well separated the underlying logic is from the UI layer.

Without wishing to seem negative: are you sure that this will be worth the effort? If I were writing a large application from scratch I wouldn't start with C++ and MFC now, but seeing where you are, what will you really gain from rewriting it? Will that add a single new feature that users will pay for? Are there any users you'll cut off who won't be able to run the new version? I can't help suspecting you'll get a much bigger return on investment from looking at some relatively simple things you could do to improve the appearance of the application as it is. For example, does it have an XP-style manifest so that common controls get the XP look? Would a few days spent updating bits (e.g. using the new style file dialogs) get you most of the way to a shiny new look? Bear in mind that even the newest, shiniest Office 2007 was implemented by Microsoft with ordinary Win32 controls.

2
votes

I had to do the same thing in a project using WinForms before. We needed to migrate our MFC project to .NET 1.1 and we decided to take all the core functionality of the MFC application and write managed wrappers around all of them. Then we wrote a WinForms front end and plugged in the legacy c++ code bit by bit. I think we made the right choice in the long run. I can't imagine how we would have done it if we had tried to preserve the MFC front end at the same time.

2
votes

FWIW, in the interim, you could use the MFC Feature Pack (available with VS2008 SP1) to give your app an Office 2007 look and feel pretty quickly (you can even add a ribbon if it's something your users would like, though this would be more involved.) I revamped the UI for an old MFC app using these new classes in a single day and now, to be fair, it looks fantastic, and my users are very pleased (you can support a whole host of looks and colour schemes.) MS opted for the BCG toolkit, but there are others available if you want to pay a small amount of money (CodeJock for example.)

I know this doesn't answer your question but if it's just UI changes you're after then it might be worth a look.

1
votes

I think you've got a good handle on the strategies. Note that one potential pain point in migrating to WPF is that not every control has a handle. This is unfortunately the clumsiest interoperability scenario. AFAIK, the only way to interop with MFC and WPF is to go through WindowsFormsHost. The WPF paradigm is also radically different from MFC/WinForms, so there may be some translation problems there.

Given your large, but functional, legacy codebase, I would probably argue in favor of your second approach. Start with one control at a time and make it WPF-y. Create a well-defined interface between your new managed control and the underlying codebase, then work against that interface. If you do it one at a time, you'll be working with a lower risk-profile re: WPF's learning curve (which is pretty steep, imho).

I feel like it's important to note that I would probably suggest the former approach if you were going to WinForms. The closer paradigm and relatively smooth learning curve would be much easier to work through all-at-once.