Introduction
In the world of MFC programming it is very easy to start writing an MDI
application. But there is no such AppWizard available to write MDI applications
using Managed C++ classes. In this article I have explained how to write a
simple MDI application using managed C++ classes. I have tried to write this
application similar to MFC document-view architecture application.
Screenshot
Start
Create a "Managed C++ Application" project using Visual Studio .NET "New
Project" wizard. This will create a blank project with only main()
function written. Include following common header lines to stdafx.h file.
#using <mscorlib.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>
#using <System.Drawing.dll>
#using namespace System::Windows::Forms;
#using namespace System::ComponentModel;
#using namespace System::Drawing;
#using namespace System::IO;
#using namespace System;
Right click on the project name in workspace window and select Add->Add
class. Add following classes to the project as we see how they work. Please
refer source code for definition of these classes.
The Application class : CTextPadApp
InitInstance
method of this class calls
Application::Run()
function to start the main frame window (of
class CTextPadFrame
). Please refer TextPadApp.h for definition of
this class.
bool CTextPadApp::InitInstance()
{
...
m_MainFrame = new CTextPadFrame();
m_MainFrame->Create();
Application::Run(m_MainFrame);
...
}
The Main frame class : CTextPadFrame
This class represents the MDI main frame window of our application.
CTextPadFrame
is derived from .NET framework's
System::Windows::Forms::Form
class which gives basic windows
functionality to the class. The main frame window class contains the array of
documents System::Collections::ArrayList* m_DocArray,
created and
managed by it's member functions. The Create()
function sets
properties of the main frame window and also creates menu and a document-view
pair.
IsMdiContainer = true;
Text = S"TextPad";
Visible = true;
...
IsMdiContainer = true;
makes this window the MDI parent frame
window.
CTextPadDoc* CTextPadFrame::CreateDocument(void)
{
try
{
m_TextPadDoc = new CTextPadDoc();
if(m_TextPadDoc)
{
m_DocArray->Add(m_TextPadDoc);
CTextPadDoc::iDocs++;
}
else
return 0;
m_TextPadView = new CTextPadView(m_TextPadDoc);
if(m_TextPadView)
{
if(! (m_TextPadView->Create(this)) )
{
MessageBox::Show("Error creating window.");
return 0;
}
}
else
return 0;
m_TextPadDoc->SetView(m_TextPadView);
String *strTitle = new String("Default.txt");
m_TextPadView->SetViewTitle(strTitle);
return m_TextPadDoc;
}
catch(Exception *x)
{
MessageBox::Show(x->ToString());
return 0;
}
}
The CreateDocument()
function actually allocates instances of
the document and view class. Document and view contain pointers to each other as
their member variables.
Menu handlers
As there is only one menu for view and the main frame, all menu handlers are
written in main frame window class CTextPadFrame.
Managed C++ uses
delegates for handling events.
void OnNewDocument(Object *pSender,EventArgs* pArgs);
void OnFileSaveDocument(Object *pSender,EventArgs* pArgs);
void OnFileOpenDocument(Object *pSender,EventArgs* pArgs);
void OnExit(Object *pSender,EventArgs* pArgs);
void OnHelpAbout(Object *pSender,EventArgs* pArgs);
m_FileMenu->MenuItems->Add(m_FileNewMenu);
m_FileNewMenu->Click += new EventHandler(this,&CTextPadFrame::OnNewDocument);
m_FileMenu->MenuItems->Add(m_FileOpenMenu);
m_FileOpenMenu->Click += new EventHandler(this,&CTextPadFrame::OnFileOpenDocument);
m_FileMenu->MenuItems->Add(m_FileSaveMenu);
m_FileSaveMenu->Click += new EventHandler(this,&CTextPadFrame::OnFileSaveDocument);
m_FileMenu->MenuItems->Add(m_FileExitMenu);
m_FileExitMenu->Click += new EventHandler(this,&CTextPadFrame::OnExit);
The View class : CTextPadView
This class represents the view or child window of our MDI application and is
derived from System::Windows::Forms::Form
class.
CTextPadFrame::CreateDocument()
function calls
Create()
function of this class to create and initialize the child
window. CTextPadView::Create()
receives pointer to the main frame
window as a parameter. MdiParent = ParentWnd;
statement makes this
view window a MDI child window.
bool CTextPadView::Create(Form *ParentWnd)
{
...
...
MdiParent = ParentWnd;
Show();
m_TextBox = new TextBox();
if(m_TextBox)
{
m_TextBox->Multiline = true;
m_TextBox->ScrollBars = ScrollBars::Both;
m_TextBox->Font = new System::Drawing::Font(
new FontFamily( S"Times New Roman"), 10.0f );
m_TextBox->Dock = DockStyle::Fill;
Controls->Add(m_TextBox);
}
...
...
return true;
}
The child window contains the TextBox
control and
m_TextBox->Dock = DockStyle::Fill
changes TextBox size to always
fill the client area.
The Document class : CTextPadDoc
The document class does the crucial work of opening and saving files. It has
OpenDocument()
and SaveDocuments()
functions which are
called by menu handlers of main frame window. It uses :
*
FileStream
class to open a file for reading or writing.
*
StreamReader
to read
String
(text) from an opened file and
*
StreamWriter
to write
String
to opened file.
StreamReader *sReader = new StreamReader(fileStream);
if(sReader)
{
m_strTextData = sReader->ReadToEnd();
sReader->Close();
fileStream->Close();
m_AssociatedView->SetTextToTextBox(m_strTextData);
bIsDirtyFileName = false;
}
StreamWriter *sWriter = new StreamWriter(fileStream);
if(sWriter)
{
String *strViewText=m_AssociatedView->GetTextFromTextBox();
if(strViewText != 0)
sWriter->Write(strViewText);
sWriter->Close();
fileStream->Close();
}
m_AssociatedView->SetTextToTextBox(m_strTextData)
and
m_AssociatedView->GetTextFromTextBox()
functions set or get text
from the text-box contained in the view window.
Build
Add few lines to your main()
function as shown below.
#ifdef _UNICODE
int wmain(void)
#else
int WinMain()
#endif
{
CTextPadApp *theApp= new CTextPadApp();
bool bAppInit=theApp->InitInstance();
return 0;
}
That's it! Build and run the application.
Conclusion
It's very easy to write MFC document-view like application using managed c++
classes. If we follow some structured way of writing applications we can write
more complex MDI applications using managed C++ classes.
Please feel free to write me on this article.
Hrishikesh Lele