Interoperability between MFC/WIN32 and WPF

C++/CLI extends C++ allowing the usage of .NET managed code and offer a new and more transparent way to interop managed and native worlds.

Let’s create a simple MFC application showing an example how to listen to events raised from a WPF object embedded on it, and then react to them within the MFC application.

Open Visual Studio 2008 and create a new MFC application project. I’m naming it “MFCWPFEventsInterop”.

clip_image001

The MFC wizard will be displayed.

The only change needed is to set the project style to Office as it is shown in the following picture and click Finish button.

clip_image002

Now we have to change project settings in order to use C++/CLI. Enter project properties and change to Common Language Runtime Support (/clr) and then apply your changes.

clip_image003

We also need to reference the WPF assemblies in Common Properties tab.

clip_image005

Then open the “MFCWPFEventsInterop.h” file and add the declaration of OnFileNew method as it is shown in the following code:

   1:  
   2: class CMFCWPFEventsInteropApp : public CWinAppEx
   3: {
   4: public:
   5: CMFCWPFEventsInteropApp();
   6: // Overrides
   7: public:
   8: virtual BOOL InitInstance();
   9: // Implementation
  10: UINT m_nAppLook;
  11: BOOL m_bHiColorIcons;
  12: virtual void PreLoadState();
  13: virtual void LoadCustomState();
  14: virtual void SaveCustomState();
  15: afx_msg void OnAppAbout();
  16: afx_msg void OnFileNew();
  17: DECLARE_MESSAGE_MAP()
  18: };

Then open “MFCWPFEventsInterop.cpp” file, add the two “using” sentences as shown below, and also modify the “ON_COMMAND” so it will use our own implementation of the OnFileNew method.

 

   1:  
   2: // MFCWPFEventsInterop.cpp : Defines the class behaviors for the application.
   3: //
   4: #include "stdafx.h"
   5: #include "afxwinappex.h"
   6: #include "MFCWPFEventsInterop.h"
   7: #include "MainFrm.h"
   8: #include "ChildFrm.h"
   9: #include "MFCWPFEventsInteropDoc.h"
  10: #include "MFCWPFEventsInteropView.h"
  11: using namespace System;
  12: using namespace System::Windows;
  13: #ifdef _DEBUG
  14: #define new DEBUG_NEW
  15: #endif
  16: // CMFCWPFEventsInteropApp
  17: BEGIN_MESSAGE_MAP(CMFCWPFEventsInteropApp, CWinAppEx)
  18: ON_COMMAND(ID_APP_ABOUT, &CMFCWPFEventsInteropApp::OnAppAbout)
  19: // Standard file based document commands
  20: ON_COMMAND(ID_FILE_NEW, OnFileNew)
  21: ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
  22: // Standard print setup command
  23: ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
  24: END_MESSAGE_MAP()
  25: Finally we need to add our implementation code at the end of the file as 
  26: follows:
  27: // CMFCWPFEventsInteropApp message handlers
  28: void OnWPFAppClosed(Object ^sender, EventArgs ^args)
  29: {
  30: AfxGetApp()->m_pMainWnd->SendMessage(WM_CLOSE);
  31: }
  32: void CMFCWPFEventsInteropApp::OnFileNew()
  33: {
  34: CWinAppEx::OnFileNew();
  35: Window^ wpfWindow = gcnew Window();
  36: wpfWindow->Title = "This is a WPF window";
  37: wpfWindow->Closed += gcnew EventHandler(OnWPFAppClosed);
  38: wpfWindow->Show();
  39: }

As you cannotice in the code, we are creating and showing a WPF window at runtime when we add a new file on the MFC application.

 

We are also subscribing to the Closed event of the WPF window and in the event handler we are executing some native C++ code, in this case forcing the application to close.

When you debug the application you will see something similar to the picture below and the if you click the close button within the WPF object, the entire application will shutdown.

clip_image006

 

This is a simple example on how you can handle WPF window events (or any event) within a MFC or WIN32 application.  You can extend it to handle any event thrown from your WPF application and react to it within the native code, so you can have the best of both native and managed worlds.

 

This post was written by Marcelo Martinez – Lead WPF Developer @ UruIT

No Comments