We have had some internal discussion about CWinFormsDialog<> template that clearly discovered some confusion about what is a proper way for user to use this template. In short, this template should be seen as CDialog MFC class. The primary scenario we have in mind for this template is when a developer creates a MFC wrapper around System::Windows::Form::Control for its future use in MFC applications. In other words, let's say you have a Winform control created in either in C++ or C# called HostedWinFormsControl and you want to integrate it with your existing MFC applications. Do this:
- Add #include <afxwinforms.h> to stdafx.h.
- Generate using Class wizard an MFC class that subclasses CDialog. You won't need resource template, so go ahead and delete it. Let's call this new class as CHostForWinForm.
- Go ahead and replace every appearance of CDialog in hostforwinform.h and hostforwinform.cpp with CWinFormsDialog<HostedWinFormsControl>.
- Now you want your MFC dialog listen to events on your winform, for example, you want to know when user clicks on a specific button. You need to add a delegate map, MAP_DELEGATE_MAP, see below. This creates a proxy around your native class that is used to call methods of a native class when a managed event is fired.
- Of course, you need to add OnButtonX() methods to your MFC class that are used as a handlers for Click events on winform side.
- Last step is to organize data exchange, which is basically means to change DoDataExchange() method of the host MFC class as it is shown below.
And that's it. Now you can use this MFC class that hosts Winform as a regular MFC dialog. Here are the code snippets:
--------------------------------------------------------------------------------------------------------
HostForWinForm.h
--------------------------------------------------------------------------------------------------------
#pragma once
// CHostForWinForm dialog
class CHostForWinForm : public CWinFormsDialog<HostedWinForms::HostedWinFormsControl>
// public CDialog
{
DECLARE_DYNAMIC(CHostForWinForm)
public:
CHostForWinForm(CWnd* pParent = NULL); // standard constructor
virtual ~CHostForWinForm();
virtual BOOL OnInitDialog();
// Dialog Data
// enum { IDD = IDD_HOSTFORWINFORM };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
/////////////////////////////////////////////
// CODE YOU ADD TO INTEGRATE WINFORM CONTROL
public:
virtual void OnButton1( System::Object^ sender, System::EventArgs^ e );
virtual void OnButton2( System::Object^ sender, System::EventArgs^ e );
BEGIN_DELEGATE_MAP( CHostForWinForm )
EVENT_DELEGATE_ENTRY( OnButton1, System::Object^, System::EventArgs^ );
EVENT_DELEGATE_ENTRY( OnButton2, System::Object^, System::EventArgs^ );
END_DELEGATE_MAP()
CString m_sEditBoxOnWinForm;
};
--------------------------------------------------------------------------------------------------------
HostForWinForm.cpp
--------------------------------------------------------------------------------------------------------
#include "stdafx.h"
#include "HostForWinForm.h"
// CHostForWinForm dialog
IMPLEMENT_DYNAMIC(CHostForWinForm, CWinFormsDialog<HostedWinFormsControl>)
CHostForWinForm::CHostForWinForm(CWnd* pParent /*=NULL*/)
: CWinFormsDialog<HostedWinFormsControl>(CHostForWinForm::IDD, pParent)
{
}
CHostForWinForm::~CHostForWinForm()
{
}
void CHostForWinForm::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
/////////////////////////////////////////////
// CODE YOU ADD TO INTEGRATE WINFORM CONTROL
if (pDX->m_bSaveAndValidate)
m_sEditBoxOnWinForm = CString( m_control->textBox1->Text);
else {
m_pControl->textBox1->Text = gcnew System::String(m_sEditBoxOnWinForm);
}
}
BEGIN_MESSAGE_MAP(CHostForWinForm, CWinFormsDialog<HostedWinFormsControl>)
END_MESSAGE_MAP()
BOOL CHostForWinForm::OnInitDialog()
{
CWinFormsDialog<HostedWinFormsControl>::OnInitDialog();
/////////////////////////////////////////////
// CODE YOU ADD TO INTEGRATE WINFORM CONTROL
GetControl()->OkButton->Click += MAKE_DELEGATE( System::EventHandler, OnButton1);
GetControl()->CancelButton->Click += MAKE_DELEGATE( System::EventHandler, OnButton2);
return TRUE;
}
/////////////////////////////////////////////
// CODE YOU ADD TO INTEGRATE WINFORM CONTROL
void CHostForWinForm::OnButton1( System::Object^ , System::EventArgs^ )
{
CDialog::OnOK(); // This will close the dialog and DoModal will return.
}
/////////////////////////////////////////////
// CODE YOU ADD TO INTEGRATE WINFORM CONTROL
void CHostForWinForm::OnButton2( System::Object^ , System::EventArgs^ )
{
CDialog::OnCancel(); // This will close the dialog and DoModal will return.
}
Questions, comments, suggestions? Feel free to comment.
P.S.: This code snippet may not work with Beta 2, because we have fixed some bugs in CWinformDialog<> after Beta 2. But this is how it should work in the final release of VS2005.