Project Description
In this proof of concept we try to demonstrate how it’s possible to mix C++ MFC UI with WPF control.
For example, we can replace the standard View with a WPF View or we can add a WPF control to an MFC dialog box. This project is based on the same template architecture available in VC++2008, integrating the Windows Form into an MFC Application



Before to begin you need to prepare VC++2008 in order to build correctly the sample

Setup C++ Directories

1) Add the path to the.NET 3.0 FrameWork assemblies
Choose the Tools/Options menu.
In the Options Dialog Box, choose Project and solution
For the reference files add the following path "C:\Program Files\Reference

Assemblies\Microsoft\Framework\v3.0"


2) In the zip file you will find the \Integration Avalon\BuildSolution directory, including all the

include, lib and dll in order to build the solution.
Add the \Integration Avalon\BuildSolution\include directory to the path (this directory contents two

files, evxavalon.h and evxavalon.inl)

3) Add the \Integration Avalon\BuildSolution\Lib\win32 to the lib path and to the reference files

path.

Note : Only the library AvalonViewud.lib (debug and Unicode) is available in this sample. Don’t

compile with ansi character set.
Important : Install the WPFCommandTarget.dll and WPFHwndSource.dll in the Global Assemblies Cache

(GAC)


Using a WPF in a MFC dialog box:

1) In Visual Studio 2008, choose an MFC dialog box. Called it MFCTest.
2) Add /clr compil option

3) At the end of the stdafx.h file add the following line: #include <evxavalon.h>
4) In the MFCTestdlg.h add:
CAvalonControl<System::Windows::Controls::Button> m_WPFButton ;


5) Add to your MFC Dialog Box a Static Text control, and called it IDCSTATICWPF
6) The add the following code
DDXAvalonControl(pDX,IDCSTATICWPF,this->mWPFButton);
in the CMFCTestDlg::DoDataExchange(…) method
Build the solution, and test it


What I need now, it’s to add some extra code to react to the WPF button click event in the MFC code.

1) In the MFCTestDlg.h file add the following method declaration :
void SurClickBoutonWPF(System::Object^ sender, System::Windows::RoutedEventArgs^ e);

Note : in the .NET World, the best practice for the event it’s to use the pattern, with the

following parameters.
System.Object (which control is raising the event)
System.EventArgs, parameters that you want to pass to the subscriber.

2) In the MFC application, you can use some .NET classes in order to subscribe to the .NET event.

But the C++ team provides us some very helpful macros.
In the MFCTestDlg.h file add the lines:

BEGINDELEGATEMAP (CMFCTestDlg)
EVENTDELEGATEENTRY (SurClickBoutonWPF,System::Object^,System::Windows::RoutedEventArgs^);

ENDDELEGATEMAP ()

Don’t’ forget the « ^ » character which symbolize a ref class.

3) In the MFCTestDlg.cpp file, add the SurClickBoutonWPF method like this
void CMFCTestDlg::SurClickBoutonWPF(System::Object ^sender, System::Windows::RoutedEventArgs ^e)
{
AfxMessageBox(L"Click d'un bouton WPF exécuté dans du code MFC");
}

4) The last thing to do, it’s in the MFC code, subscribe to the WPF control Click Event using

the MAKE_DELEGATE macro.
5) In the OnInitDialog(), add the following code :
mWPFButton->Click+=MAKEDELEGATE (System::Windows::RoutedEventHandler,SurClickBoutonWPF);

The construction looks like the C# construction
6) Build and test the solution


In this sample, I used the System.Windows.Controls.Button, but it’s perfectly allowed to use a WPF

CustomControl, as we will see in a moment.

After this very simple example, what will we cover now, it’s replacing the CView with my own

CavalonView which display a WPF CustomControl.


Replacing the standard CView with the CAvalonView






1) In Visual Studio 2008, create a new MFC SDI application. Called MFCTestVue.
2) Don’t forget to add the /clr command line.
3) Add an include #include <evxavalon.h> in stdafx.h
4) Open the MFCTestVueView.h file, and inherit from CAvalonView
class CMFCTestVueView : public CAvalonView

5) Do the same exercise in the MFCTestVueView.cpp, replace CView by CAvalonView
IMPLEMENT_DYNCREATE(CMFCTestVueView, CAvalonView)
BEGINMESSAGEMAP(CMFCTestVueView, CAvalonView)


Now we need to create our first WPF UserControl.

1) Adding a new project called TestWPFControl In VS 2008 : select the Visual C# language, then "WPF

User Control Library" Template
add a ListBox and a button to the surface designer


2) Come back to the MFC Solution
3) Select the MFC project, and add TestWPFControl as a reference.
4) Open the MFCTestVueView.cpp, and for the constructor add a declaration to the WPF Control

like this :
CMFCTestVueView::CMFCTestVueView():CAvalonView(TestWPFControl::UserControl1::typeid)
5) Build the solution




Now I'm going to show you how to interact from the MFC code with the WPF code.

In these simples’ demos, we will see.
• How to subscribe to the event click
• How to interact with WPF code from MFC command
• How to use standard command like Cut, past, undo etc…


Filling the WPF list box from the MFC code
1) In Visual Studio 2008, open the UserControl1.xaml.cs file
2) Add the two declaration
3) public Button MonButton;
public ListBox MaListeBox;
4) In the constructor
MonButton = this.button
MaListBox = this.ListBox1

5) Open the MFC project and add the following code in the MFCTestVueView.h file :

void SurClickButton(System::Object^ sender,System::Windows::RoutedEventArgs^e);

BEGINDELEGATEMAP (CMFCTestVueView)
EVENTDELEGATEENTRY (SurClickButton,System::Object^, System::Windows::RoutedEventArgs^)
ENDDELEGATEMAP ()
virtual void OnInitialUpdate();

6) Open the MFCTestVueView.cpp file and implement the OnInitialUpdate and SurClickButton

methods like this.

void CMFCTestVueView::OnInitialUpdate()
{
TestWPFControl::UserControl1^ wpfControl;
wpfControl=static_cast<TestWPFControl::UserControl1^>(this->GetControl ());
wpfControl->Button->Click +=MAKE_DELEGATE
(System::Windows::RoutedEventHandler,SurClickButton);
}

void CMFCTestVueView::SurClickButton(System::Object ^sender, System::Windows::RoutedEventArgs ^e)
{
TestWPFControl::UserControl1^ wpfControl;
wpfControl=static_cast<TestWPFControl::UserControl1^>(this->GetControl ());
for (int i= 0;i <20;i++)
{
String^ sEl=String::Format ("Eléments {0}",i.ToString ());
wpfControl->MaListeBox->Items->Add(sEl);
}
}



Trigger a WPF method from an MFC Command
1) Add an new command to the MFC menu
2) Note the number of the command in the resource.h
#define ID_TESTNET 32773
We will use it later in the WPF Project

3) Come back to the WPF project, open UserControl1.xaml.cs,
4) Add a reference to the C:\Program Files\Microsoft Visual Studio 8

\VC\atlmfc\lib\mfcmifc80.dll

5) Inherit the UserControl from Microsoft.VisualC.MFC.ICommandTarget

6) Still in the WPF project, implement the Initialize method. (Note the number of the MFC

command)
public void Initialize(Microsoft.VisualC.MFC.ICommandSource src)
{
src.AddCommandHandler(32773,new Microsoft.VisualC.MFC.CommandHandler

(this.OnTestCommande));
}

7) In last, create the OnTestCommande() method.
private void OnTestCommande(uint cmdID)
{
MessageBox.Show("Code WPF");
}

8) Build the solution

Using the standard MFC command

1) In the WPF Project, add a reference to
.\Integration Avalon\BuildSolution\Lib\win32\WPFCommandTarget.dll

2) In the Initialize method, add the following declaration :
DPE.VisualC.MFC.EV.WPFCommandTarget Wp = new DPE.VisualC.MFC.EV.WPFCommandTarget();
Wp.Initialize(src, this);

3) In order to test the sample add two textbox in the WPF control
4) Build the solution.

Last edited Jul 15, 2008 at 5:21 PM by EricVX12R, version 2