Getting started with Managed C++
Written by Harry Fairhead   
Tuesday, 17 August 2010
Article Index
Getting started with Managed C++
The Designer

Getting started with managed C++ isn't as easy as it should be because the documentation is often not up-todate. Our introduction uses VC++ 2010 and you can follow it using the free Express edition. Find out just how easy, and surprising, it all is.

 

C++ is often thought of as a "difficult" language. Partly because the way that it has been built up from C and partly because it has a history of being used in conjunction with sophisticated and complex technology like the MFC, ATL, Corba or COM. Indeed C and later C++ were the original ways of building Windows applications using the raw API. You can't really blame C++ for seeming complex and difficult when it's so often used in conjunction with complex and difficult APIs.U

What comes as something of a surprise - especially if you have any familiarity with, say, the MFC, is how simple application development with C++ can be. VIsual Studio supports a very easy way to work with Visual C++  - Managed C++. It turns out to be a good way to see just how easy C++ is and how much like other object-oriented languages it is. If you know C#, Java, Visual Basic or any object-oriented language you will be able to follow this article and get started with C++.

You don't even need a full copy of C++, just download and install Visual C++ 2010 Express.

One difficulty is that the syntax of many parts of the language introduced to extend it to "managed" classes changed with VC++ 2005 and while this is some time ago much of the documentation, and most of the examples, still use the old syntax. So let's start with a fresh copy of 2010 and see how it all works.

Managed C++

Managed C++ makes use of the framework, i.e the .NET class library and the common runtime system, to do everything. I’m not going to go into the details of mixed managed and unmanaged C++, nor am I going to go into considerations of migrating code - both are for future articles.

At the moment what is important is to get a clear idea of what using the .NET framework from C++ is all about.

If you start a new Windows Forms project, Managed C++ doesn't support WPF at the moment, then after the project has been created you will see the forms designer much like you would in any .NET language.

 

button1

 

You can drag-and-drop a button from the Toolbox and double click on it to create a click event handler. If you view the generated code you should quickly follow what is happening.

The event handler looks fairly obvious:

private: System::Void button1_Click(
System::Object^  sender,
System::EventArgs^  e) {
}

with both parameters as they would be in any .NET language expect that they are passed as C++ "pointers" to classes of the appropriate type. To be more accurate the new operator ^ works like a pointer but it in fact dereferences a handle to the managed heap. It you think about handles to the managed heap as managed pointers you won't be too far from the truth.

Note: the ^ operator replaces the original __gc* reference pointer type.

To create a Hello World program all you have to do is add the line:

Diagnostics::Debug::WriteLine(
L"Hello World");

The output will appear in the Debug Output window when you run the program.

If you try this out you will notice that there are some differences between using say C# and C++ under Visual Studio. The most obvious is that there is no Intellisense prompting - and you really notice its loss. There is also no interactive error checking. The first you know about an error is when you try to run the program. The errors are reported in the Output window and you need to scroll to the right to read the relevant detail.

If you are used to C# the the C++ environment will seem very primitive and barely adequate. If you are a C++ programmer you won't notice the primitive environment because you will still be in a state of shock that you can create something as sophisticated as a window, with a button and an event handler in a few seconds, with so little code and in such a straight forward manner - compare the experience to when you first learned the MFC say.

If you look at the generated code you will quickly understand the structure of the program and the way it works with the framework. You will discover a constructor Form1 and a destructor ~Form1 have been generated. The constructor calls InitilizeComponent and the destructor uses the delete instruction to remove any components that have been created. Components that you add to the form are declared as pointers to objects of the appropriate type. For example:

private: System::Windows::Forms::
Button^  button1;

Most of the real work is done by the InitilizeComponent method - which is 100% generated by the Designer and you shouldn't ever directly modify it. If you read the method through you should be able to see how it creates and initialises each of the components you have added. For example, the button is created using:

this->button1 = (gcnew 
System::Windows::Forms::Button());

This allocates space on the garbage-collected, i.e. managed, heap and then creates an instance of the type using the space. Notice how similar this is to the use of new in C#..

Once we have created a component initialising it is very easy using the pointer returned by gcnew. For example:

this->button1->Location = 
System::Drawing::Point(58, 68);
this->button1->Name = L"button1";
this->button1->Size =
System::Drawing::Size(75, 23);

Even the setting up of the event handler looks very like the same operation in C#:

this->button1->Click += gcnew 
System::EventHandler(
this, &Form1::button1_Click);

Finally the form is initialised in the same way. The only new action is adding the button object to the form's Controls collection property:

this->Controls->Add(this->button1);

Even though this generated code is simple it does give us some ideas of the differences between raw and managed C++. The first thing to notice is that there aren’t many header files. Traditional C++ has lots of header files that define how libraries are used.  You can still use header files but managed references and using statements do most of the same job in managed C++. Notice that the layout of the form is stored in the header file Form1.h. It is this that the designer reads and writes to determine the form's layout and it is where the code that you have just been examining lives.

This header file is loaded into the main program Forms.cpp in the usual way

#include "Form1.h"

and the main program gets everything going with the single line:

Application::Run(gcnew Form1());

which creates an instance of the form on the managed heap.

 

Using WinForms

To move on from this simple example perhaps the first thing to find out about is how to work with a window.

We have the basics of how manged C++ creates a user interface. The only thing you really have to adapt to is that managed objects are created on the managed heap and instead of pointer to memory you work with handles to allocations on the managed heap. Lets see how this works by creating a dialog box in code.

After all when you first wrote a raw Win32 application you saw how to create a window and there is a sense in which a window is the core of any Windows program. In the case of a managed C++ program, however, the inner workings of message loop, window and window procedure have all but vanished.

The System::WinForms namespace and the System.WinForms.dll library contains classes that enable you to implement a GUI.

In this case the fundamental window class is called Form and it is a fairly high-level abstraction of what a C++ programmer generally thinks of as a window.

For example, it can be a general window, a modal dialog box or a non-modal dialog box.

To create an instance of the Form class we simply write:

Form^ dialog1=gcnew Form();

The instance now exists and we can make use of the many properties and methods that Form offers to customise its look and behaviour. Once again notice that the variable dialog1 isn't a pointer to the new instance but a handle that we tend to treat as if it was a pointer.

For example, to set the caption and display the dialog you would use:

dialog1->Text=L"My Dialog";
dialog1->ShowDialog();

When this program is run a window appears and the program pauses until you close it. You can't switch back to the applications main window until the modal dialog box is closed. 

 

dialog

A dialog box.

 

If you look at the dialog box that we have produced you will see that it isn’t much like a standard dialog box. You can resize it and it has all the wrong window menus. However all of these problems can be fixed with a little custimization.

 

<ASIN:0321334876>

<ASIN:0672326973>

<ASIN:1430225491>

<ASIN:1430229675>

<ASIN:1847195563>

<ASIN:0735626707>

<ASIN:0071668950>

<ASIN:0321543726>

 



Last Updated ( Saturday, 21 May 2016 )