OpenGL, Win32, and Menus...

I’m trying to get a basic OpenGL/Win32 framwork setup so that I have somplace to drop my code as I’m learing OpenGL. I’ve got the window creation and everything going just fine, but I hit a snag with the Windows menuing system. I just want to have standard drop down menus (stuff like “start simulation”, “stop simulation”, etc.) as an easy means of controlling my code. The SuperBible (old edition I’m sure) mentions that double buffered windows can’t be used with the Windows GDI, so I wasn’t really surprised when I loaded up my app and got spasmatic menus (they drew just fine, I think, but they were getting constantly overwritten by my OpenGL display code). I know that there are examples in the SuperBible where there’s OpenGL code running in a window with menus. So I loaded up some example code from early in the book and sure enough there’s a double buffered window with menus working just fine. At this point I become confused. The code looks just like mine. So I load up my orignial framework app again, only this time the menus work fine.

So my question is, what the heck happened? I was pretty sure that menus wouldn’t work (they’re drawn by the GDI, right?) but I thought I’d try it anyway. When they didn’t work (I thought) I understood. Now that they work, well, I’m confused. Especially as I didn’t conciously change any configs on the system. I’m happy to have it working, but I’d really like to understand what happened.

Um, help?

Oh, I suppose I should add that I’m running Windows ME with a Geforce3 card, compiling in VC++ 6.0, and the app in question seems to be using the NVidia ICD (though it is using the Microsoft generic glut - dunno if that’s normal or not, stupidly I didn’t check up front).

[This message has been edited by kabir (edited 08-02-2001).]

Gimme youre GF3 and I’ll help you j/k.
I just pause the entire thing, in other words, I don’t swop the buffers, and then go into a loop where the menu gets displayed. Thereby you don’t have stuff overdrwing the menu. The only thing is that you can’t have movement on the screen whilst the menu is pulled down. I suppose you can order youre stuff so that youre menu gets redrawn each time after youre scene is redrawn, but I don’t know how this is gonna affect the mouse selection of the menu story. I haven’t tried it that way yet.

Originally posted by RedZen:
I just pause the entire thing, in other words, I don’t swap the buffers, and then go into a loop where the menu gets displayed. Thereby you don’t have stuff overdrwing the menu.

That seems like a reasonable enough idea, and
it’s probably what I’ll end up doing as my weird flickering behaviour is back. Oddly though, it now applies to dialog boxes as well. If I pop a dialog box over the GL window it gets overwritten. I though Dialogs were subwindows and would thus be unaffected by the buffering problem… maybe I was wrong?

In any case it’s failing (in the expected, right way) again, so I feel a touch better. Still wish I knew why it worked for a while though…

Thanks for the suggestion!

Keep in mind that youre screen is a 2D platform. If one object gets redrawn, and one on top of it not after it, then you are going to get the original top object now being below the other.

I had the same problem as you awhile ago while doing a Win32 app. If I remember correctly, I fixed it by placing a ValidateRect at the end of my drawing function.

Hi,
Have you tried changing the properties of the dialog to ‘PopUp’ ? This, I think places the dialog above the windows behind it. Your problem seems kinda strange. Having Windows menu items overlapping an OpenGL drawn window is OK while the window is not being drawn, but I’d imagine a conflict if the window is being painted and so is the menu.

Originally posted by Barrie:
Hi,
Have you tried changing the properties of the dialog to ‘PopUp’ ?

Yes, I’ve set the dialog to ‘PopUp’ but it still gets overdrawn. I had been under the impressions that dialogs were seperate windows (with their own GC, etc.) and thus would not be affected by the buffering of the parent window, but I guess this isn’t true. Or I’ve managed to create the dialog in such a way that it’s not true for me

[This message has been edited by kabir (edited 08-02-2001).]

If you are using InvalidateRect() to cause your screen to get redrawn, and NOT calling ValidateRect() at the end of your drawing code, the window is never “validated” so it continously tries to update.

That is if you do not use BeginPaint to get your HDC.

From MSDN:
The BeginPaint function automatically validates the entire client area. Neither the ValidateRect nor ValidateRgn function should be called if a portion of the update region must be validated before the next WM_PAINT message is generated.

The system continues to generate WM_PAINT messages until the current update region is validated.

When I had this problem, I also had the problem where my scene was constantly updating, even though I had my drawing code in the WM_PAINT message, no timers, and nothing in the message loop that should have caused further updates. Anyway, it’s worth at least trying…

Originally posted by Deiussum:
When I had this problem, I also had the problem where my scene was constantly updating, even though I had my drawing code in the WM_PAINT message, no timers, and nothing in the message loop that should have caused further updates. Anyway, it’s worth at least trying…

The relevent portion of my code:

static HDC hdc;

case WM_CREATE:
hdc = GetDC( hWnd );

break;

case WM_PAINT:

RenderScene();
SwapBuffers( hdc );

ValidateRect( hWnd, NULL );
break;

The odd thing is, sometimes it my menus and dialog boxes draw just fine, and sometimes they don’t. It’s completely random, but it’s consistant for the life of the program.
So I can run the same executable multiple times and get different results (though they tend to come in groups).

Pretty much what I’ve decided is that Windows menus + openGL are bad news so I’m just going to avoid them. Maybe there’s an MFC way to deal with this, but I’ve got other stuff to learn first

Try changing to something like this and see if it makes a difference…

static HDC hdc;
PAINTSTRUCT ps;

case WM_CREATE:
hdc = GetDC( hWnd );

ReleaseDC(hdc);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RenderScene();
SwapBuffers( hdc );
EndPaint(hWnd, &ps);
// This probably isn’t needed with Begin/End paint
// ValidateRect( hWnd, NULL );
break;

I don’t have any of my old Win32 code with Menus and OGL on this machine, at the moment so I can’t double check exactly how I fixed the problem again.

if((MAIN . hDC[N] = GetDC(MAIN . hWnd[N])) == NULL) { C_Catch_Error(“ERROR in GetDC() <GL_Init_OGL_PIXFORMAT>”); }
if((pf = ChoosePixelFormat(MAIN . hDC[N], &pfd)) == 0) { C_Catch_Error(“ERROR in ChoosePixelFormat() <GL_Init_OGL_PIXFORMAT>”);}
if(SetPixelFormat(MAIN . hDC [N], pf, &pfd) == FALSE) { C_Catch_Error(“ERROR in SetPixelFormat <GL_Init_OGL_PIXFORMAT>”); }
if((MAIN . hRC [N] = wglCreateContext(MAIN . hDC[N])) == NULL) { C_Catch_Error(“ERROR in wglCreateContext <GL_Init_OGL_PIXFORMAT>”); }
if(wglMakeCurrent(MAIN . hDC[N], MAIN . hRC [N]) == FALSE) { C_Catch_Error(“ERROR in wglMakeCurrent <GL_Init_OGL_PIXFORMAT>”); }
}

Do not release your DC keep it static or global. Moreover move your drawing stuff in WinMain while loop like this.

while(TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
for( i = 0; i < cnt; i++){
wglMakeCurrent(wOGL_CHILD.MAIN.hDC[i], wOGL_CHILD.MAIN.hRC[i]);
if(i%2)
draw();
else
P_Particle();
SwapBuffers(wOGL_CHILD.MAIN.hDC[i]);
}
}
Then do whatever you want even 20 or 50 Ogl windows everything work just excellent. Only one thing do not place gui over Ogl client area put it in gdi
|----------------------------|

MENU
OGL
----------------
OGL
----------------
OGL
----------------------------

Hope it’ll help.