How to: Migrating a CLR console Visual C++ project to Windows Forms

Note: Windows Forms programming in new development is discouraged by Microsoft at this point as Microsoft wants to make full use of hardware accelerated drawing instead of using the CPU-intensive GDI. But maintaining old Windows Forms code in Visual C++ 2012 is still supported, GDI isn’t going anywhere anytime soon.

Visual C++ 2012 removed the Windows Forms project template and I see people scramble to find ways to create a Windows Forms project.  There is a walkaround that’s been around for years, that is, to convert a CLR console application to a Windows one, then add forms related code to the project.

The basic steps are listed at http://support.microsoft.com/kb/317433, conveniently named “How to suppress the console window for a managed extensions to Visual C++ Windows Forms application“. Yes, the need to convert a C++ console application to windows forms is that old, back all the way back in the managed extensions for C++  days.

So what I need to do to add Windows Forms support to a C++/CLI console application? Of course the System.Windows.Forms.dll reference is missing in a new console application, so I need to reference it:

  • In code:

#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System::Windows::Forms;

  • Or In IDE:
    • Select the project in Solution Explorer
    • On the Project menu or the context menu of the project node, select Properties
    • In the Property Pages dialog box, expand the Common Properties node, select Framework and References, and then click Add New Reference.
    • Find and add System.Windows.Forms in the list of available references.

In reality the Windows Forms Designer generates a lot of layout code that uses System.Drawing types like Point and Size, so I need to repeat the steps for System.Drawing.

Next the console window needs to be suppressed. The C++/CLI console project template in fact does not specify an entry point, so compiler guesses because a main function exists, the project is a console application. A Windows Forma application’s entry point has the same signature with the main function, therefore the /subsystem setting of the project needs to be changed to Windows:

  • Go back to the project’s Property Pages dialog box.
  • Click the Linker folder on the type.
  • Click the System property page.
  • Change the SubSystem property to Windows.

Ready? Not yet. The compiler is now trying to find a WinMain function, and throws LNK2028 and  LNK2019 when it can’t find the entry point, which of course isn’t there. I am not interested in writing one as I prefer to keep the nice args command line parameter of an array<String^>^ type , so I need to tell the compiler my entry point function is still main:

  • Go back to the the Linker folder.
  • Click the Advanced property page.
  • Change the Entry Point property to main.

We are almost here. Windows Forms needs an STA thread, so I have to add  [STAThreadAttribute] to the main function:

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{

….. // wait did I add anything here? I guess not yet

Here you go,  a Windows Forms application that does nothing interesting.  Mmm, to make it a little more visual, I create a new Windows Form class named Form1 and run it in the main function:

//before main function
#include “Form1.h”
using namespace ProjectName;

//in the main function
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);

// Create the main window and run it
Application::Run(gcnew Form1());

Yada! I have a Windows Forms application running now.

Advertisement

3 responses to “How to: Migrating a CLR console Visual C++ project to Windows Forms”

  1. Thank-you so very much for this article. I had actually figured out everything except for setting the entry point to “main”. It was driving me insane trying to convert an old CLR app to run in the Windows subsystem instead of console. This was a very clear, detailed, and accurate explanation of the process. Thanks again!

  2. Dear Sheng,
    Many thanks for this article. It’s very useful. However, I have a question. I have my own project written in visual c++ language (2015 enterprise copy). I’m near to finish with but then I realized I need a tidy interface for the user. I created another project using windows form as an interface for my code and its running, but the problem with me I can’t combine my project (including a header file+main.cpp + many .cpp files) with the interface which I created for them. How can I connect two projects (c++ code+Interface)? Any help would be much appreciated. Thanks in advance.

    1. sorry for late reply. normally this is done via writing a C++/CLI wrapper (like Microsoft did to gdiplus, wrap it in System.Drawing).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.