translate

Monday, February 22, 2010

How to host/display a MFC dialog from WFP application.


How to host/display a MFC dialog from WFP Window.
Now a day most of the new application or solution are developed using .Net WPF technology. But at the same time we need to support the legacy applications developed using Win32 or MFC.  Again always it is not possible to rewrite/port the exiting application using new technology because of many factors like time, budget etc.  So what is the solution? Answer is provide a way or hosting environment in new application to reuse the exiting application code/module.
I had same issue where I need to provide a way to use exiting GUI developed in MFC in newly develop WPF application.
Initially I searched a lot on internet but got nothing. Every article demonstrate you how to host a Win-Form or WPF control in MFC, but not the MFC in WPF. 
So I tried to develop the solution on my own. After lot of R&D and MSDN study I found the solution for this problem. Here I will show you how you can show an MFC dialog from WPF window.
There is no direct way to show MFC dialog from WPF, so we will create a managed CLI/C++ wrapper dll that will act as a mediator between WPF & native MFC resource dll.

1.       Create a MFC Resource DLL:

a.       From Visual Studio create a new MFC Dll project, name it as MFCDialog

b.      Select default options, visual studio will create necessary files for you.
c.       Now add a new resource as Dialog


d.      Now double click on that dialog to add a class for MFC dialog, derive it from CDialog & name is as “DummyDialog”. This will create and add two new file “DummyDialog.h” & “DummyDialog.c” to the MFC project.

e.      Now add two new public function declaration to “DummyDialog.h”

BOOL OpenModalDialog(HWND hwnd);
      static DummyDialog* CreateDummyDialog(void);

f.        Add following code as function definition to “DummyDialog.c”
// DummyDialog message handlers
BOOL DummyDialog::OpenModalDialog(HWND hwnd)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
      return DoModal();
}

DummyDialog* DummyDialog::CreateDummyDialog()
{
      AFX_MANAGE_STATE(AfxGetStaticModuleState())
      return new DummyDialog();
}

g.       Now you are almost done with MFC Dialog, only remaining part is to export this class so that other application/dll can use it. Add following code to “DummyDialog.h”
#if defined(DLLEXPORT)
#define DllExport   __declspec( dllexport )
#else
#define DllExport   __declspec( dllimport )
#endif

And decorate class definition with DllExport macro as:
class DllExport DummyDialog : public CDialog

h.      Modify project setting to add new  DLLEXPORT preprocessor to avoid linkage error

i.         Now you are done with MFC resource dll

2.       Next is How to build Host Wrapper DLL:

a.       From Visual Studio create a new MFC Dll project, name it as MFCHost


b.      Select default options, visual studio will create necessary files for you.
c.       Now add a new header file, name it “MFCWrapper.h”. Add following code to this file
#pragma once

namespace CSRWindow
{
      public ref class MFCWrapper
      {

      public:
// Default constructor
            MFCWrapper();

// Function to show MFC modal dialog from WPF //application
            static void ShowmodalDialog(void);
      };
}

 “CSRWindow” is the namespce for MFC host wrapper. MFCWrapper is a wrapper class to be used by WPF application.
We have declared ShowmodalDialog as static member function to display the dialog.

d.      Now add a new cpp source code file, name it “MFCWrapper.cpp”.  Add following code to this file
#include "stdafx.h"
#include "MFCWrapper.h"
#include "..\MFCDialog\DummyDialog.h"

namespace CSRWindow
{
      // Default constructor
      MFCWrapper::MFCWrapper()
      {
            // You can add any other intialization code here
      }

      void MFCWrapper:: ShowmodalDialog()
      {
            // Create an instance of MFC Dummy dialog
            DummyDialog* pDlg = DummyDialog::CreateDummyDialog();

            // Check for null object
            if(pDlg)
            {
                  // Display the dialog
                  pDlg->OpenModalDialog(NULL);

                  // Free the object
                  delete pDlg;
                  pDlg = NULL;
            }
      }
}
e.      Now save both the files and compile the code. I am sure you will get some compilation errors.

f.        Change the “Common Language Runtime support” setting from Project properties. By default it is always “No Common Language Runtime support” for MFC project. Update it to “Common Language Runtime Support (/clr)”

g.       Now add a new reference of MFCDialog.dll, from “Project” tab under Add Reference Dialog.


h.      Also add .NET assembly reference for “PresentationCore”, “PresentationFramework”, “System” & “WindowsBase”

i.         Compile the code, now you are done with the host wrapper implementation.

3.       Now Create a WPF test application to display the MFC dialog:

a.       Add new WPF Window Application project to the existing solution, name it “DemoApp”


b.      Now add reference of “MFCHost.dll” to this project

c.       Add a new button to the Window1.xaml, name it “ShowDialog” and add Click event


d.      Add following code to ShowDialog Click event handler
private void ShowDialog_Click(object sender, RoutedEventArgs e)
            {
            MFCWrapper.ShowmodalDialog();
         }

Don’t forgot to add “using CSRWindow” namespace to “Window.xaml.cs”

e.      Now set output directory of “DemoApp” project to “..\Debug\”
f.        Now Run the DemoApp and click on ShowDialog button

g.       MFC Demo Dialog is displayed from WPF application.

You can also download the source code & demo application : MFCDialog.zip



5 comments:

  1. This sample is not working for me
    Getting the below error when i run the sample.

    An unhandled exception of type 'System.BadImageFormatException' occurred in PresentationCore.dll

    Additional information: Could not load file or assembly 'MFCHost, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.

    ReplyDelete
    Replies
    1. Set the platform target of the DemoApp to x86

      Delete
  2. Great and that i have a swell provide: How Much House Renovation Cost Philippines outdoor home renovations

    ReplyDelete