Introduction

This article presents a very clean and simple method to render an OpenGL window on a Windows Forms using Managed C++. This method requires no add-ins, third party DLLs, or ActiveX components, often demonstrated with C# Windows Forms. This implementation is in pure .NET using Managed C++. This article assumes the reader has a working knowledge of OpenGL and is using Microsoft Visual Studio .NET 8.0.

Background

Presenting an OpenGL window on an MFC view was very straight forward and easy to implement. The advent of Windows Forms however presents some problems. The concept of the window Device Context does not really exist in Windows Forms. There are some implementations of OpenGL on Windows Forms already out there but these rely on DLLs or ActiveX components containing MFC or Win32 SDK calls. These implementations also assume that the programmer is using C#. Whilst there are some advantages of using C#, I suspect that, like myself, I don't want to rewrite my existing applications in C# just to take advantage of Windows Forms. I also suspect that many C++ programmers don't want or can't move to C#, for corporate reasons or whatever. The implementation here is using pure Managed C++ and .NET.

The implementation

Firstly, we need a new Windows Forms application to work with. Create a new a new Windows Forms application (File -> New -> Project -> Visual C++ -> CLR -> Windows Forms Application).

We will now build an OpenGL class that can be used on several Windows Forms. This can be easily converted into a control that can be added to the Design Time Designer, but I'm not covering that.

Create a new header file for the class, I called my OpenGL.h and copy the following code snippets into it. I will comment below the snippet what the code actually does: -

Standard function to set a pixel format for a Win32 SDK / MFC Device Context. See OpenGL websites for more on this.

If you copy all of the snippets it should build fine, don't forget to add openGL32.lib, gdi32.lib, and User32.lib to your project (Project -> Properties -> Configuration -> All Configurations -> Linker -> Input).

The test container

Open the code view to your form and add the header to your OpenGL class and add a member variable that is a pointer to the class in your Form. Next, change your Form's constructor: -

Points of interest

This method works because the System::Windows::Forms::NativeWindow provides a low-level encapsulation of a window handle and a window procedure. This allows us to treat the class as a HWND (see my user control).

I've changed the demo slightly to show it is more likely to be used. I did this because I've purposefully kept the OpenGL simple (I've not even setup the viewport or viewing frustrum but that is entirely application specific, my article is to show the method of creating an OpenGL view on a Windows Forms).

History

2006/10/18 - Submitted article to CodeProject.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

As you already mentioned, I did it on the wasteful way, onResizeStart destroy the openGl instance and onResizeEnd I initialized the openGl-class again. I think the proper way would be to use the GLResize function, but I didn't know how to handle with it. It didn't work for me.

You can use the CWnd::SetWindowPos(window,0,posx,posy,width,height,0); function to resize the window afterwards, you can even move it and do other stuff with the window.

Have a look at the MFC documentation. I followed this tutorial and got my gl window attached to a panel on my CLR form. Everytime the resize event of the panel is called I call the resize of my gl window, where I update the viewport and the window size.

I'm trying to render some opengl scene into a windows form, exactly what this code suggest, but I get a runtime error, I debugued into this code and I realize that the mistake is because the variable m_hDC gets this part of the code, totally empty, can someone help me here??
thanks in advance
Raissel

FWIW, I have been having this same problem on two different machines. I finally just got past it by wrapping the SetPixelFormat through wglMakeCurrent into a loop like such:
PIXELFORMATDESCRIPTOR pfdDescribed;
int maxPixelFormatIndex = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfdDescribed);
for (int i = iPixelFormat; i < maxPixelFormatIndex; ++i)
{
if(SetPixelFormat(m_hDC, iPixelFormat, &pfd) == FALSE)
{
//MessageBox::Show("SetPixelFormat Failed");
continue;
//return 0;
}

Did you try calling the Resize function before MyPxelFormat function? The opengl-view appears to me, when i call glViewPort before the pixel-format stuff. I'm talking about the functions from the downloadable content, not of the code pasted in this tut.

I ventured away from this code block as a starting point, and have ported over what I needed from the Tao Framework's SimpleOpenGLControl, to managed C++. I am no longer running into this issue. Some things I notice that they do differently before calling SetPixelFormat:
they call the following on the control before doing any openGL calls:

but after this I couldn't use gluPerspective, it didn't have had any effect on the perspective.

I searched for the problem and it seems to be a problem with the latest .NET Framework or something like this. I'm using Visual C++ 2008. Other guys using 2005 doesn't seem to have this problem. In anoter board i've found this thread:

Did you ever get this to work? The example compiles but I get an error once it starts to run. Any help is greatly appreciated. I haven't found any other useful references to opengl in a windows form in 2 days of searching the web.

Well my version of code compiled and ran without error but it didnt show any thing except a black screen.
I have called resize function before setPixel, as described in earlier post. But i cant see any thing. Any help??? Please.

If anyone chose to download only the OpenGL.h file from the link at the top, it is not the same as OpenGL.h included in the entire "project" download. This might help if you can't figure out where this "resizeGLscene" method is everyone is talking about.