Introduction and Pre-requirements
Hello, and welcome to this article series. In this first part of the series, I will introduce you to the world of C++/CLI briefly. For starters, let's have a look on a set of abbreviations that may pop up on our way.
- CLR = Common Language Runtime, the heart of .NET Framework.
- CRT = C/C++ Run-time (Usually, means the libraries).
- MSIL = Microsoft Intermediate Language, or 'What C++/CLI is compiled to'.
Before starting on this article, I recommend reading the following set of articles on the C++/CLI syntax, written by our very own Nishant S. You can find the articles, in the preferred reading order, right here:
Another thing that must be fulfilled before starting is the installation and setup of Visual C++ 2005 Express Beta. If you are an MSDN Subscriber, you can gain access to the Visual Studio 2005 version also, but for the sake of simplicity, we will use the Express version in the context of this article. In this light, the following software/additions need to be installed and present:
The basics of C++/CLI - A simple Hello World application
After the pre-requirements have been filled, we can start on our journey to conquer the world of C++/CLI. Our first task on this path is to create a small sample application that pops up a simple message box from the .NET Framework.
First, boot up your VC++ 2005 and from File -> New -> Project, create a new, empty .NET project. Name this project as 'Hello_CLI'. The wizard will create a project skeleton that uses the CLR and supports C++/CLI extensions on the standard C++ language.
Supporting the Platform SDK
In order to create Windows applications, we need to add support to the Platform SDK. When you install the SDK, the installer automatically configures the Visual Studio to point to the correct directories for the headers and libraries.
If you have multiple installations of Visual Studio on your machine, these directories might or might not be correct. At this point, it is good practice to check whether this is the case. Go to the Tools -> Options menu, and on the left-hand list, expand Projects and Solutions, then click on VC++ Directories. The key directories are for Executable files, Include files and Library files. If the directory entries are not listed, you must add them manually. This is a daunting process, but when done, it comes a long way in simplifying things.
After the directories are set, the next step is to actually include the necessary files. So, go back to the Solution Explorer view, right-click on the project name, and add a new header file. Name this file StdAfx.h, and paste the following as its contents:
<PRE lang=c++>// Common include file for Windows Platform SDK
// Top-level Windows version
#define WINVER 0x0400
// Windows NT 4.0
#define _WIN32_WINNT 0x0400
// Windows 98
#define _WIN32_WINDOWS 0x0410
// Internet Explorer 4.0
#define _WIN32_IE 0x0400
// Exclude rarely-used stuff from Windows headers
// Windows Header Files:
Supporting the .NET Framework
Although the wizard that generated our project automatically adds support for the CLR, it is still our task to reference the necessary assemblies that we wish to use. In standard C++ terms, this would mean importing the needed libraries. However, in the world of C++/CLI, all this is made much simpler.
Back in the Solution Explorer, right-click on the solution name and choose Add .NET Reference. This will pop up the project settings and take you to the page of the references. As of now, no references have been added, so we need to add them manually. Click on Add New Reference button. From the list that pops up, choose System.dll and System.Windows.Forms.dll. Add them, and click OK. Now, exit the project properties.
Now, it is our task to add some actual code. For starters, add a new C++ source file named main.cpp. Paste the following code snippet into this file:
<PRE lang=mc++>#include "stdafx.h"
// Define our entry-point
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpStrCmdString, int nCmdShow)
// Display a managed message-box
System::Windows::Forms::MessageBox::Show( L"Hello C++/CLI", L"TestApp",
You might wonder some of the code lines, so let's get through them in an orderly fashion. Our first command is to include the Platform SDK headers. As we are using both the Platform SDK and the .NET Framework, there are a few instances on where duplicate names are found.
One of these is the
MessageBox function. So, we will promptly undefine
MessageBox. This automatically results in the fact that if you wish to create an unmanaged messagebox, you must explicitly call either the ANSI version (
MessageBoxA) or the UNICODE version (
The next step, as visible, is to define the entry-point of our Win32 application. The calling convention (<CODE lang=mc++>__stdcall) is necessary, otherwise the Whidbey compiler will issue a warning. However, our main task is to pop up a managed message-box, so that is what we will do. From the
System::Windows::Forms namespace, a class called
MessageBox is found. This class cannot be instantiated, but it has one static method (
Show()) that can be used to display a messagebox. As for the parameters of the call, you should see the class definition in the MSDN or the off-line documentation, if you have it installed.
This program, when built and executed, does nothing much more than pop up a messagebox. Interesting things during the debug execution are that in addition to the normal thread of execution, a secondary .NET thread is executed alongside, on which the managed code runs. These threads are named as Native and .NET in the output window.
Taking a step further - Using Windows Forms
After we have taken our first elusive steps into the depths, it's time to make a bit larger leap. This time, we will take on the Windows Forms usage. At this point, you can either use the old project or create a new one. I will present the steps necessary when you start from ground zero, so if you decide to use the old project as a base, do only the changes that are necessary.
Again, create a blank .NET project by using the wizard, just like in the previous chapter. Following the same steps, add support to the Platform SDK by creating the StdAfx.h file and pasting the code contents there.
Now, it's time to add the references needed to use Windows Forms. Unlike you might think, just using the System.Windows.Forms.dll is not enough. As we will be using the Forms Designer to accomplish the creation, the wizards will include the necessary references for us. So, just right-click on the project, add a new item, and under UI choose Windows Form (.NET). Name the form <iii>
MyForm1. The adding of the form into the project may take up to five minutes, so be patient.
We are automatically presented with a form. First, right-click on the form and select Properties. Under Appearance, change the
Text property to Win32 Test Form. This property determines the caption shown on the form. Next, let's add some text and a button on the form. From the Toolbox, select a
Label control and move it on the form. Open up its properties and change the
Text property to Press this button to quit. Then, add a button from the Toolbox, giving it similarly a caption of Exit. For the button, we also need to change the ID to
ID_EXIT. The ID, in .NET Framework, is called
Name, and can be found under Design in the properties box.
Place and size the controls and the form so that your form looks just about like this.
When done, click on Save All and close the Form Designer by closing the form window. Then return to the Solution Explorer, now it's time to take our form into use.
Add a new source file, called main.cpp. Again, include the common header file. Then include the form's header file MyForm1.h and write the
WinMain() function. Naturally, you can copy these from the previous chapter's files.
As for the contents of the
WinMain function, write the following:
<PRE lang=mc++>int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpStrCmdString, int nCmdShow)
// Create, show and run the form, enabling visual styles on the fly
System::Windows::Forms::Application::Run( gcnew Hello_CLI_2::MyForm1() );
This code fragment would display the form, but as we have not coded any functionality to the button, it won't do much. Now, it's time to add that functionality. So, back in Solution Explorer, right-click on MyForm1.h and select View Designer. This takes us back to the Form Designer.
Now, locate our button, right-click on it, and choose Properties. In the Properties window, look for an image of a small lightning button in the upper part of the window. This button has a tooltip called Events. When you find it, click on it, and a list of possible events to which you can respond is displayed.
To remain simple, we will only respond to the Click event, which occurs whenever a button is clicked over the button. Into the box next to Click, write OnClicked_Exit and press Enter. After a minute or two, a piece of code is auto-generated and you're taken into the code view of the form, into this new function.
Inside this function, we wish to terminate the form, and for this purpose, the
System::Windows::Forms::Application offers a method called
Exit. To call this method, write the following inside the function:
<PRE lang=mc++>private: System::Void OnClicked_Exit(System::Object^ sender,
// Terminate the form
So, now when the project is built and executed, a small, nifty form is displayed. Clicking on the button will close the application.
There it was. Now we know how to write applications that run on the Win32 platform and make use of the .NET Framework. Although it is also possible to create a pure-.NET application that doesn't use the unmanaged platform, I decided to use this approach because it's more intuitive to people who have programmed for Windows earlier on.
As for the writing of this article, I would like to thank Nishant S. for his patience in answering some of my daunting questions, and for the pre-work made in writing the articles mentioned at the start of this one.
That is all for now. Look forward for the next part in the series: creating Windows MDI Forms applications and how to take MFC into the play as well.