MDI form under C# (.NET) causes an error on SwapBuffers()

Hi @ all.

I am trying to set up a MDI form, containing several child forms with one child performing OpenGL rendering. In my OpenGL form, I do all setups and drawing belonging to OpenGL.

It’s done in that way:

// get the device context
_hwnd = ((this.Handle).ToInt32());
_hDC = GetDC(_hwnd);

// setup the pixel format with DOUBLEBUFFER enabled

ChoosePixelFormat(…)
SetPixelFormat(…)
wglCreateContext(…)
wglMakeCurrent()

initOpenGL()

// override OnPaintBackground(…) to stop flickering.
// draw in OnPaint

drawGLScene(…);
SwapBuffers(…);

Everything works fine when I instantiate these form in a single SDI Application like this way:

// Main
Application.Run(new OpenGLFrame());

Now I try to set up this form to be a children of a MDI form like this:

//Main
Application.Run(new Mainframe()); // suppose that Mainframe is a form with IsMdiContainer = true

And inside my Mainframe:

// show the OpenGL form
private void menuItemFile_AddNew_Click(object sender, System.EventArgs e)
{
OpenGLFrame midiChild = new OpenGLFrame();
midiChild.MdiParent = this;
midiChild.Show();
midiChild.Activate();
}

After setting the MdiParent for my OpenGL form, no painting is done anymore…
…every call to SwapBuffers() fails due to a ERROR_INVALID_HANDLE. (got it by GetLastError()…)

When I omit the “midiChild.MdiParent = this” statement, the OpenGL form will show up, everything is working fine but the form will not be connected to my MDI container anymore.

Does anyone know what’s the problem or how to come around this?
Thanks for your efforts.

hmmm… i’ve been playing with vs 2005 and this just works for me. i create a mdiparent window, on ShowNewForm() i replace the name of the child class with my opengl view, then i render on my tick.

maybe you hosed some of your properties messing about in the designer? or maybe there’s something in your opengl context setup that’s not quite right.

how are you importing GetDC (IntPtr GetDC(IntPtr))?
IntPtr hWnd = control.Handle;
IntPtr hDC = GetDC(hWnd);

are you using a known framework or your own to import all the wgl/opengl procs? be very careful when importing/marshaling (a lesson i’ve recently learned the hard way ;-)).

what’s glGetError returning (actually, this won’t catch all mistakes)?

i’m out of ideas :wink:

Hi.

On weekend, I tried to figure out if I am doing some failures importing or marshalling the OpenGL procs…
Well, I could not find an error…
I am programming with Visual Studio 2003 and .NET Framework version 1.1.4322.

glGetError returns me an GL_INVALID_OPERATION on calls to SwapBuffers() when the form is set to be a child form…

I tried several approaches.

  1. doing the importing / marshalling of all OpenGL stuff by myself:

    [DllImport("user32")]
    

    public static extern int GetDC(int hwnd);

    _hwnd = (int)((this.Handle).ToInt32());
    

    _hDC = GetDC(_hwnd);



    [StructLayout(LayoutKind.Sequential)]
    public struct PIXELFORMATDESCRIPTOR
    {
    public short nSize;
    public short nVersion;
    public int dwFlags;
    public byte iPixelType;
    public byte cColorBits;
    public byte cRedBits;
    public byte cRedShift;
    public byte cGreenBits;
    public byte cGreenShift;
    public byte cBlueBits;
    public byte cBlueShift;
    public byte cAlphaBits;
    public byte cAlphaShift;
    public byte cAccumBits;
    public byte cAccumRedBits;
    public byte cAccumGreenBits;
    public byte cAccumBlueBits;
    public byte cAccumAlphaBits;
    public byte cDepthBits;
    public byte cStencilBits;
    public byte cAuxBuffers;
    public byte iLayerType;
    public byte bReserved;
    public int dwLayerMask;
    public int dwVisibleMask;
    public int dwDamageMask;
    }


PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR();
short pfdSize = (short)Marshal.SizeOf(typeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = pfdSize;
pfd.nVersion = 1;
pfd.dwFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER);
pfd.iPixelType = (byte)PFD_TYPE_RGBA;
pfd.cColorBits = (byte)GetDeviceCaps(hdc, BITSPIXEL);
pfd.cRedBits = 0;
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 0;
pfd.cAccumRedBits = 0;
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 32;
pfd.cStencilBits = 0;
pfd.cAuxBuffers = 0;
pfd.iLayerType = (byte)PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;

	int pixelformat = ChoosePixelFormat(hdc, ref pfd);

SetPixelFormat(hdc, pixelformat, ref pfd);
_hRC = wglCreateContext(_hDC);
wglMakeCurrent(_hDC, _hRC);



InitGL();


DrawScene();
SwapBuffers(_hDC);

  1. writing a managed wrapper in C++ to perform the native calls to OpenGL and platform SDK:

… The same setup for the PIXELFORMATDESCRIPTOR as mentioned before (inside the managed C++ wrapper class)…

In C#: this._proxi = new ManagedLib((this.Handle));
In managed C++: ManagedLib:: ManagedLib (System::IntPtr hwnd) {
_hWnd = (HWND)(hwnd.ToPointer());
_hDC = GetDC(_hWnd);
}
Once again, the same like before… ChoosePixelFormat, SetPixelFormat, wglCreateContext, wglMakeCurrent, … and so on…
(All calls to native C (OpenGL, WIN32) are done in managed extensions for C++ by IJW)

  1. using the TAO framework for MONO and .Net Version 1.2.0-1 to get the OpenGL stuff done (everything in C#)

  2. used an example form from the TAO framework as a MDI Child.

None of my endeavours has been successful…
Always the same effect: setting the form to be a child of an MDIparent causes calls to SwapBuffers to fail. No OpenGL drawing…
Moreover, the client area of the form is not repainted when you move or resize the window.
I played around with some form properties like
this.SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(System.Windows.Forms.ControlStyles.ResizeRedraw, true);
this.SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true);
this.SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer, true);
In addition, any combination of what I am guessing to make sense…
The only effect I could achieve was that the background of the form was cleared to black and no painting was done…

Even the examples from the TAO Framework do not work when the form.MDIParent property is set… The background is cleared, and no painting is performed afterwards.

I am absolutely out of ideas.

Is the form.MDIParent property messing up the device context???
Do I face a bug in .NET framework 1.1???

Any suggestions are welcome!
Thanks!

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.