Soient des composants .NET faisant partis du namespace System.Windows.Forms comme une listview .NET ou un webbrowser .NET ou un DataGridView .NET ou un ReportViewer .NET et montrons comment nous pouvons les héberger dans une vue MFC dans un modèle SDI ou MDI.
Créeons une solution MFC Hosting contenant trois projets :
1. Un Projet C++/CLI HostingWinFormsControls Windows Forms Control Library
2. Un Projet DLL MfcWinFormsHostDll Dll d'extension MFC
3. Un Projet Exe MfcWinFormsHost Application MFC MDI
Dans le projet HostingWinFormsControls nous allons ajouter plusieurs user control pour chacun des composants .NET en oubliant pas de faire Dock in Parent Container de façon à remplir la surface de chacun de nos User Control
Dans le projet MfcWinFormsHostDll nous allons montrer comment une dll d'extension MFC peut hoster des contrôles .NET et illustrer ainsi l'exportation des classes C++ dans une application MFC
Le projet MfcWinFormsHost peut hoster les contrôles .NET de 2 façons. Soient par sa dll d'extension MfcWinFormsHostDll ou directement à partir du User Control HostingWinFormsControls.
Pour le cas d'un DataGridView le code généré est le suivant :
Maintenant il est question que ce usercontrol soit connecté à l'infrastructure des MFC. Nous allons entamer 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 public ref class HostingWinFormsControlsControl : public System::Windows::Forms::UserControl { public: HostingWinFormsControlsControl(void) { InitializeComponent(); // //TODO: Add the constructor code here // } // ... private: System::Windows::Forms::DataGridView^ dataGridView1; // ...
Pour le projet HostingWinFormsControls
1. Modifier la classe de base de chacun de nos user control comme ceci
2. Implémenter les méthodes virtualles commec cela
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 public ref class HostingWinFormsControlsControl : public System::Windows::Forms::UserControl , public Microsoft::VisualC::MFC::ICommandTarget , public Microsoft::VisualC::MFC::IView {
3. Il faut ensuite référencer l'assemblie MFCMIFC80.dll dans le projet HostingWinFormsControlsControl 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 private: 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) { // Pour connecter les messages command avec votre CWinFormsViews m_CmdSrc = cmdSrc; //m_CmdSrc->AddCommandHandler(ID_COMMAND1, gcnew CommandHandler(this, &WpfUserControlHostControl::OnMethod1)); //m_CmdSrc->AddCommandHandler(ID_COMMAND2, gcnew CommandHandler(this, &WpfUserControlHostControl::OnMethod2)); //m_CmdSrc->AddCommandHandler(ID_COMMAND3, gcnew CommandHandler(this, &WpfUserControlHostControl::OnMethod3)); } virtual void OnInitialUpdate() { // Le OnInitialUpdate de CWinFormsView() appelle cette méthode ci } virtual void OnUpdate() { // Le OnUpdate de CWinFormsView() appelle cette méthode ci } virtual void OnActivateView(bool activate) { // Lors que votre CWinFormsView() est activée }
Pour le projet MfcWinFormsHostDll
4. Ajouter une classe MFC qui dérive de CView en l'appelant CMfcDataGridView. Ensuite remplacer toutes les occurences de CView en CWinFormsView
N'oubliez de mettre la macro AFX_EXT_CLASS devant CMfcDataGridView car elle sera exportée depuis notre Dll d'extension MFC MfcWinFormsHostDll. La classe de base doit être la CWinFormsView.
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 class AFX_EXT_CLASS CMfcDataGridView : public CWinFormsView { DECLARE_DYNCREATE(CMfcDataGridView) protected: CMfcDataGridView(); // protected constructor used by dynamic creation virtual ~CMfcDataGridView(); public: virtual void OnDraw(CDC* pDC); // overridden to draw this view #ifdef _DEBUG virtual void AssertValid() const; #ifndef _WIN32_WCE virtual void Dump(CDumpContext& dc) const; #endif #endif protected: DECLARE_MESSAGE_MAP() };
5. Ajouter une petite méthode très utilitaire dans notre classe
-> L'idée ici est que la CListView a son GetListCtrl(), la CTreeView a son GetTreeCtrl(), et donc notre CMfcXXXView a son GetXXXCtrl()
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 class AFX_EXT_CLASS CMfcDataGridView : public CWinFormsView { //... // Attributes public: gcroot<HostingWinFormsControls::HostingWinFormsControlsControl^> GetDataGridControl() const;
-> Lorsque des données membres d'une classe sont définies, ou bien certains argument ou type de retour de méthodes, les classes natives imposent à ce que les membres managés soit vêtu en toute transparence par des gcroot<>.
6. Dans le fichier source de MfcDataGridView.cpp on a :
C'est dans le constructeur que l'on définit notre type de vue
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 CMfcDataGridView::CMfcDataGridView() :CWinFormsView(HostingWinFormsControls::HostingWinFormsControlsControl::typeid) { }
Et voici l'implémentation de notre GetXXXControl()
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 gcroot<HostingWinFormsControls::HostingWinFormsControlsControl^> CMfcDataGridView::GetDataGridControl() const { return static_cast<HostingWinFormsControls::HostingWinFormsControlsControl^>(CWinFormsView::GetControl()); }
7. Il faut référencer le projet HostingWinFormsControls dans MfcWinFormsHostDll
8. Configurer votre dll d'extension pour qu'elle support le runtime .NET
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 // dans le StdAfx.h de MfcWinFormsHostDll // ... #if defined(__cplusplus_cli) #include <vcclr.h> #include <afxwinforms.h> // MFC Windows Forms support #using <HostingWinFormsControls.dll> #endif
[FAQ VC++]Comment ajuster les settings de ses projets MFC pour supporter des composants .NET.
9. Préparer votre dll afin que ses objets (fichier *.h, *.lib) soit correctement exportable et vue des autres modules.
[FAQ VC++]Comment exploiter efficacement l'exportation des classes C++
En final on doit avoir le fichier MfcWinFormsHostDll.h et la librairie MfcWinFormsHostDll.lib
Le fichier MfcWinFormsHostDll.h
La sortie de la librairie MfcWinFormsHostDll.lib
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 #pragma once #include "MfcDataGridView.h"
Propriétés du projet MfcWinFormsHostDll > Configuration Properties > Linker > Advanced > Import Library : $(SolutionDir)$(Configuration)\$(TargetName).lib
Pour le projet MfcWinFormsHost
10. Pour la classe CMfcWinFormsHostView remplacer toutes les occurences de sa classe de base CView par CMfcDataGridView
11. Dans le fichier stdAfx de MfcWinFormsHost on référence le projet MfcWinFormsHostDll
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 class CMfcWinFormsHostView : public CMfcDataGridView
Puis Propriétés du projet MfcWinFormsHost > Configuration Properties > C/C++ > General > Resolve #using References : $(SolutionDir)$(Configuration)\
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 // le fichier stdAfx de MfcWinFormsHost #if defined(__cplusplus_cli) #include <vcclr.h> #include <afxwinforms.h> // MFC Windows Forms support #using <HostingWinFormsControls.dll> #endif #include "..\MfcWinFormsHostDll\MfcWinFormsHostDll.h"
12. Il faut référencer la librairie MfcWinFormsHostDll.lib dans le projet MfcWinFormsHost
Propriétés du projet MfcWinFormsHost > Configuration Properties > Linker > Input > Additional Dependencies : MfcWinFormsHostDll.lib
Propriétiés du projet MfcWinFormsHost > Configuration Properties > VC++ Directories > Librairies Directories : on ajoute $(SolutionDir)$(Configuration)\;
Bon on compile toute la solution et on obtient une application comme celle-ci
Les DataGridView de DotNet sont pour l'instant vide. Il suffit de les remplir en fournissant par exemple le DataSource qui est attaché au control interne DataGridView.
Pour travailler avec votre control vous avez la méthode CMfcWinFormsHostView::GetDataGridControl() de la vue de votre exe car
CMfcWinFormsHostView dérive de CMfcDataGridView de votre dll MFC et CMfcDataGridView embarque son contrôle interne gcroot<HostingWinFormsControls::HostingWinFormsControlsControl^>
Remarquez que pour obtenir ce résultat il suffit d'avoir bien maîtriser les 2 points ci dessous:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 void CUneClassDuProjetMfcWinFormsHost::SomeMethod(CDocument* pDoc) { POSITION pos = pDoc->GetFirstViewPosition(); CMfcWinFormsHostView* pView = static_cast<CMfcWinFormsHostView*>(pDoc->GetNextView(pos)); HostingWinFormsControls::HostingWinFormsControlsControl^ pUserControl = pView->GetDataGridControl(); System::Windows::Forms::DataGridView^ pDataGridView = pUserControl->dataGridView1; // bon je travaille avec mon DataGridView // .... }
1. [FAQ VC++]Comment exploiter efficacement l'exportation des classes C++
2. [FAQ VC++]Comment ajuster les settings de ses projets MFC pour supporter des composants .NET.
Voilà
Partager