Soit un fichier XAML UserControl1.xaml accompagnés de sa source en C# UserControl1.xaml.cs. Et vous désirez intégrer le design de votre XAML dans votre fenêtre MFC.
Et bien commençons par créer une solution MFC_WPF et insérons les projets suivants :
1. Un projet C# WPF User Control Library WpfControlLibrary1
2. Un projet C++/CLI Windows Forms Control Library ClrControlLibrary1
3. Un projet MFC SDI ou MDI MfcWpfApp
Voici le code XAML
Voici le code behind du XAML
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 <UserControl x:Class="WpfControlLibrary1.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="432"> <Grid Width="690"> <Label Content="Demonstration Of WPF Controls Hosting In MFC Application" Margin="112,12,110,384"></Label> <Button Margin="90,66,79,308" Click="OnClick">I am a WPF Button, click me please</Button> <!-- Place a Label control at the top of the view. --> <Label HorizontalAlignment="Center" TextBlock.TextAlignment="Center" FontSize="20" Foreground="Red" Content="Model: Cone" Margin="57,149,42,0" Width="230" /> <!-- Viewport3D is the rendering surface. --> <Viewport3D Name="myViewport" Margin="200,149,222,25" Width="268"> <!-- Add a camera. --> <Viewport3D.Camera> <PerspectiveCamera FarPlaneDistance="20" LookDirection="0,0,1" UpDirection="0,1,0" NearPlaneDistance="1" Position="0,0,-3" FieldOfView="45" /> </Viewport3D.Camera> <!-- Add models. --> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup > <Model3DGroup.Children> <!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. --> <DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" /> <!-- Define a red cone. --> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="0.293893 -0.5 0.404509 0.475528 -0.5 0.154509 0 0.5 0 0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 0.154509 0.475528 -0.5 -0.154509 0 0.5 0 0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 -0.154509 0.293893 -0.5 -0.404509 0 0.5 0 0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 0.293893 -0.5 -0.404509 0 -0.5 -0.5 0 0.5 0 0 -0.5 -0.5 0 0.5 0 0 0.5 0 0 -0.5 -0.5 -0.293893 -0.5 -0.404509 0 0.5 0 -0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 -0.293893 -0.5 -0.404509 -0.475528 -0.5 -0.154509 0 0.5 0 -0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 -0.154509 -0.475528 -0.5 0.154509 0 0.5 0 -0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 0.154509 -0.293892 -0.5 0.404509 0 0.5 0 -0.293892 -0.5 0.404509 0 0.5 0 0 0.5 0 -0.293892 -0.5 0.404509 0 -0.5 0.5 0 0.5 0 0 -0.5 0.5 0 0.5 0 0 0.5 0 0 -0.5 0.5 0.293893 -0.5 0.404509 0 0.5 0 0.293893 -0.5 0.404509 0 0.5 0 0 0.5 0 " Normals="0.7236065,0.4472139,0.5257313 0.2763934,0.4472138,0.8506507 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 -0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.5308242,0.4294462,0.7306172 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.7236065,0.4472139,0.5257313 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.858892,0.429446,0.279071 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.8944269,0.4472139,0 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.858892,0.429446,-0.279071 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.7236065,0.4472139,-0.5257313 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.5308242,0.4294462,-0.7306172 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.2763934,0.4472138,-0.8506507 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.5308249,0.4294459,-0.7306169 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.7236068,0.4472141,-0.5257306 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8588922,0.4294461,-0.27907 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8944269,0.4472139,0 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.858892,0.429446,0.279071 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.7236065,0.4472139,0.5257313 0.858892,0.429446,0.279071 0.7236065,0.4472139,0.5257313 0.5308242,0.4294462,0.7306172 0.858892,0.429446,0.279071 " TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial> <DiffuseMaterial.Brush> <SolidColorBrush Color="Red" Opacity="1.0"/> </DiffuseMaterial.Brush> </DiffuseMaterial> </GeometryModel3D.Material> </GeometryModel3D> </Model3DGroup.Children> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </Grid> </UserControl>
Suivons les étapes suivantes:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfControlLibrary1 { /// <summary> /// Interaction logic for UserControl1.xaml /// </summary> public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } private void OnClick(object sender, RoutedEventArgs e) { System.Windows.MessageBox.Show("Elargissez votre spectre. Ce message s'affiche depuis votre CWinFormsView MFC", "Hello World"); } } }
1. Ajoutons des fichiers existants au projet WpfControlLibrary1
2. Modifier le chemin de sortie de l'output du projet WpfControlLibrary1
à partir de Propriétés du projet > Build > Output Path : Votre répertoire parent\MFC_WPF\Debug\
3. Compilez votre projet WpfControlLibrary1 pour s'assurer que l'insertion de votre fichier XAML ainsi que le path de l'assemblie est bien configuré.
4. Aller dans votre user control du projet ClrControlLibrary1 et ajouter un control ElementHost de la toolbox sous la catégorie WPF Interoperability sur la surface de votre control et fait le encrer sur toute la surface
votre CLR User Control doit avoir un code comme celui-ci
5. Modifier le code de votre CLR User Control comme ceci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 #pragma once using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; namespace ClrControlLibrary1 { /// <summary> /// Summary for ClrControlLibrary1Control /// </summary> public ref class ClrControlLibrary1Control : public System::Windows::Forms::UserControl { public: ClrControlLibrary1Control(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// </summary> ~ClrControlLibrary1Control() { if (components) { delete components; } } private: System::Windows::Forms::Integration::ElementHost^ elementHost1; protected: private: /// <summary> /// Required designer variable. /// </summary> System::ComponentModel::Container^ components; #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> void InitializeComponent(void) { this->elementHost1 = (gcnew System::Windows::Forms::Integration::ElementHost()); this->SuspendLayout(); // // elementHost1 // this->elementHost1->Dock = System::Windows::Forms::DockStyle::Fill; this->elementHost1->Location = System::Drawing::Point(0, 0); this->elementHost1->Name = L"elementHost1"; this->elementHost1->Size = System::Drawing::Size(150, 150); this->elementHost1->TabIndex = 0; this->elementHost1->Text = L"elementHost1"; this->elementHost1->Child = nullptr; // // ClrControlLibrary1Control // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->Controls->Add(this->elementHost1); this->Name = L"ClrControlLibrary1Control"; this->ResumeLayout(false); } #pragma endregion }; }
Au niveau de la classe de base
Au niveau des membres virtuels
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 public ref class ClrControlLibrary1Control : public System::Windows::Forms::UserControl , public Microsoft::VisualC::MFC::ICommandTarget , public Microsoft::VisualC::MFC::IView
6. Il faut ensuite référencer l'assemblie MFCMIFC80.dll dans le projet ClrControlLibrary1 qui se trouve typiquement dans le répertoire d''installation de votre Visual Studio (VS 2010 chez moi ) soit $(VsInstallDir)VC\atlmfc\lib\MFCMIFC80.dll
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 private: System::Windows::Forms::Integration::ElementHost^ elementHost1; Microsoft::VisualC::MFC::ICommandSource^ m_CmdSrc; // need ID of control in MFC dialog and callback function public: virtual void Initialize(Microsoft::VisualC::MFC::ICommandSource^ cmdSrc) { m_CmdSrc = cmdSrc; } virtual void OnInitialUpdate() { // Create the WPF UserControl. WpfControlLibrary1::UserControl1^ MyWpfControl = gcnew WpfControlLibrary1::UserControl1(); // Assign the WPF UserControl to the ElementHost control's // Child property. elementHost1->Child = MyWpfControl; } virtual void OnUpdate() { } virtual void OnActivateView(bool activate) { }
7. Il faut aussi référencer l'assemblie WpfControlLibrary1.dll dans le projet ClrControlLibrary1
8. Compiler le projet ClrControlLibrary1 en vous rassurant que le compilateur jette son output dans Votre répertoire parent\MFC_WPF\Debug\
9. Aller dans le projet MfcWpfApp et modifier les settings afin qu'il supporte le runtime .NET
[FAQ VC++]Comment ajuster les settings de ses projets MFC pour supporter des composants .NET.
10. Puis Propriétés du projet MfcWpfApp > Configuration Properties > C/C++ > General > Resolve #using References : Votre répertoire parent\MFC_WPF\Debug\
11. Dans le stdAfx.h du projet MfcWpfApp insérer le code qui permet de référencer le projet ClrControlLibrary1
12. Changer la classe de base CView en CWinFormsView pour la classe CMfcWpfAppView
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 #if defined(__cplusplus_cli) struct _TREEITEM { }; // definition required while mapping to MSIL type struct _IMAGELIST { }; // definition required while mapping to MSIL type #include <vcclr.h> #include <afxwinforms.h> // MFC Windows Forms support #using <ClrControlLibrary1.dll> #endif
13. Dans le fichier source de MfcWpfAppView.cpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 class CMfcWpfAppView : public CWinFormsView { protected: // create from serialization only CMfcWpfAppView(); DECLARE_DYNCREATE(CMfcWpfAppView) // Attributes public: CMfcWpfAppDoc* GetDocument() const; gcroot<ClrControlLibrary1::ClrControlLibrary1Control^> GetWpfControl() const { return static_cast<ClrControlLibrary1::ClrControlLibrary1Control^>(CWinFormsView::GetControl()); }
C'est dans le constructeur que l'on définit le type de vue
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 CMfcWpfAppView::CMfcWpfAppView() :CWinFormsView(ClrControlLibrary1::ClrControlLibrary1Control::typeid) { // TODO: add construction code here }
14. Enfin Compiler toute votre solution et lancer l'exécutable de MFC basé sur WPF
Le principe d'intégration MFC <--> WPF
[FAQ VC++]Quelle est la clé d'intégration de la technologie WPF dans les MFC?
Partager