PDA

View Full Version : MFC problem (not really OpenGl related... please help)



clucches
04-18-2001, 09:30 AM
I'm using an SDI app, and I draw my opengl Scene with a subclass of CView.
Visit www.retre.it/opengl (http://www.retre.it/opengl) to have an idea.

1) When I want to redraw the entire scene i use

Invalidate(FALSE);

And all works good.
But when I resize the window or when i move a window over my app, it
flickers.
It seams that someone called

Invalidate(TRUE);

So the screen is first cleaned with windows sistem bg color and then the
scene is drawn.
Who called that function?? Is there an Expose Func I can override??

2) I wanna rendering continuosly my scene to test performances.
I do:

void OnPaint()
{
.....
Draw The scene
.....
Invalidate(FALSE);
}

This doesn't look so good, but it works. The only problem is then Toolbar is
not refreshed. Why?

3) I wanna open a common dialog from a floating panel (modeless tool
window).
The CHOOSECOLOR common dialog doesn't appear until I press <ALT>. Why??
(maybe because i'm opening a modal diaog from a modeless one?)

thanks

Deiussum
04-18-2001, 11:34 AM
There's a simple solution to your problem. Override OnEraseBkgnd() and make it always return TRUE. This tells the framework that you are handling the clearing yourself so it will not attempt to do it for you (by clearing the scene to the background color and causing the flickering.)

Korval
04-18-2001, 11:59 AM
When you say that the toolbar is not refreshed, I assume that you mean that, during the animation, you still want to process messages. To do that, you'll have to, after every animation cycle, check the message queue for messages. If there are any, process them.

BTW, invalidating the window at the end of the OnPaint loop will cause an infinite loop, I think. I'll assume that there is an if-statement that will exit the loop once the animation is finished.

A cleaner way would be to use the OnIdle function in the CWinApp-derived class. It is only called when the message loop is empty, and it will check the queue before each call to OnIdle, so you won't have to do it yourself. The OnIdle function can call some animate procedure of yours in the CView-derived class.

kehziah
04-18-2001, 12:18 PM
Hi
I got the same problem with dialog boxes not showing properly over the gl window ( and I was coding with Win32 API (no MFC) and I was trying to open a modal dialog box).
The strange thing is that the problem appeared when the scene was a bit complex : ie with a single sphere (not too tesselated) the dialog box opened as it should, but if I put say 50 or more spheres, then I had to press ALT to make it appear... As if the message was somehow 'lost' by the dialog because your app had a lot of other things to do. Seems really strange but who can tell what happens in Windows messages handling system...

The only thing I can think of is that you send a SW_SHOW message to your dialog to force it to appear (with ShowWindow() (can't remember if it is the same in MFC)). (or you can use SetWindowPos() with probably the same effect)

If someone can explain the why and give a better way to avoid this, I'd be glad to learn it as well.

Hope this helps

NeoTuri
04-18-2001, 12:35 PM
are you using WS_CLIPCHILDREN and WS_CLIPSIBLINGS http://www.opengl.org/discussion_boards/ubb/smile.gif

Glossifah
04-18-2001, 12:37 PM
Outstanding!

Kehziah, I have had this problem for many months (at some point I posted to the board to see if anyone had a solution), and have yet to find a Real solution.

My workaround (read: Hack Job) was done by wrapping the drawing code in an m_bActive toggle, and when the main frame is defocused, m_bActive goes low, and allows the message box to properly pop up. The obvious drawback to this method is that anytime someone clicks off of the window, the rendering stops. I also tried the solution you mentioned, which works with CDialog objects, but it doesn't provide a way to "force" an SW_SHOW event for a dialog created with a MessageBox() call (which I tend to use a lot). In my fleeting hopes of finding a solution, I created a class that allows for the explicit creation of a dialog box with a string displayed, which forces SW_SHOW, but it's a bit too many hoops for me to go through IMHO.

Do me a favor, if you come up with a solution, can you post it here? I'll do these same if I figure out a long term solution.

Regards,

Glossifah

P.S. Yes, I'm specifying WS_CLIPCHILDREN and WS_CLIPSIBLINGS in CMyView::PreCreateWindow().

[This message has been edited by Glossifah (edited 04-18-2001).]

Eric
04-18-2001, 10:49 PM
Glossifah, Kenziah, clucches,

I have been developing applications using both MFC and OpenGL for almost 3 years now and I have never had this problem with dialog boxes and the <ALT> key. I have had an awful lot of problems (mostly because of MFC, as you might guess !) but not this one...

I was wondering if one of you could e-mail me a sample app that shows the behaviour your describe (with source) so that I can compare it with my own code ?

I am sorry but I cannot post my code: it is part of commercial applications. Actually, I think I have a cut-down version of my framework that I used to send a bug report to nVidia... I'll have to dig this one out.

Best regards.

Eric

martin_marinov
04-18-2001, 11:49 PM
Hi,
I also program using MFC and OpenGL and I've never had this problem - I've written a small demo, which uses dialog boxes(the Color Dlg too), which may be displayed over the ogl window during the animation. No problems with the dialog boxes. But I've heard also that other people have the same problem like you.... However, the ON_UPDATE_COMMAND handlers are executed when there is idle time in the application... So if you use the processor at 100%, you may never update the enabled/checked state of your buttons(commands).
If you wish, you can download my demo from my home site: http://medo.dir.bg (Animating implicit surfaces)
Hope this helps
Martin

[This message has been edited by martin_marinov (edited 04-19-2001).]

clucches
04-19-2001, 07:23 AM
Originally posted by Deiussum:
There's a simple solution to your problem. Override OnEraseBkgnd() and make it always return TRUE. This tells the framework that you are handling the clearing yourself so it will not attempt to do it for you (by clearing the scene to the background color and causing the flickering.)

Ok, that was the right solution!
I found it by myself just 5 min before reading this.

thanks
( if you know how to solve the other problems...)

Leo
04-19-2001, 07:29 AM
I've had a problem with MFC thats been driving me nuts for over a year. I've written a multi-windowed CAD interface using windows derived from CWnd. Sometimes, the windows crop the left or bottom of the windows with a black border.

The viewport is correctly centered and black is not the clear color or window background color. The uncropped viewport area is of a fixed size, so to make the cropped are go away the window has to resized to cover it.

The error is not in the resize function because some of the windows are OK, and others are broken!!!

The only thing that I though it could be was using the same GL context to draw in multiple windows. If anyone wants to see it I can email the app.

anyone got any ideas

Leo

clucches
04-19-2001, 07:31 AM
Originally posted by Korval:

A cleaner way would be to use the OnIdle function in the CWinApp-derived class. It is only called when the message loop is empty, and it will check the queue before each call to OnIdle, so you won't have to do it yourself. The OnIdle function can call some animate procedure of yours in the CView-derived class.

1) I thougth OnIdle is called only the first time the message-queue is empty (this is not enough..)
2) At first I tought to a problem of message handling, but all other messages (WM_LBUTTONDOWN ...) are processed immediately!!! (maybe they have an higher priority?)

clucches
04-19-2001, 07:37 AM
Originally posted by Glossifah:
Outstanding!

Kehziah, I have had this problem for many months (at some point I posted to the board to see if anyone had a solution), and have yet to find a Real solution.

My workaround (read: Hack Job) was done by wrapping the drawing code in an m_bActive toggle, and when the main frame is defocused, m_bActive goes low, and allows the message box to properly pop up. The obvious drawback to this method is that anytime someone clicks off of the window, the rendering stops. I also tried the solution you mentioned, which works with CDialog objects, but it doesn't provide a way to "force" an SW_SHOW event for a dialog created with a MessageBox() call (which I tend to use a lot). In my fleeting hopes of finding a solution, I created a class that allows for the explicit creation of a dialog box with a string displayed, which forces SW_SHOW, but it's a bit too many hoops for me to go through IMHO.

Do me a favor, if you come up with a solution, can you post it here? I'll do these same if I figure out a long term solution.

Regards,

Glossifah

P.S. Yes, I'm specifying WS_CLIPCHILDREN and WS_CLIPSIBLINGS in CMyView::PreCreateWindow().

[This message has been edited by Glossifah (edited 04-18-2001).]

I've already tryed with SW_SHOW and it seems it works, but i would like to solve the problem at the source and not to try forcing the app to obey my rules...

Glossifah
04-19-2001, 11:08 AM
All,

Regarding this thread:

I believe that Martin's "100% CPU" post points to the problem.

After looking through my own code, dating back several months, I noticed that the trend began occuring as I started using MFC and writing performance-oriented code. Meaning as soon as the drawing routine completed, the rendering surface was invalidated and the process occurred all over again. This issue does not occur, however, in code where I implemented a timer (high resolution or otherwise) to gate the invalidation of the surface.

Long story short, it's fixed. It's simply a matter of using some type of timer to call Invalidate(false) and force a redraw of the scene. This may not be the best solution for applications which guage performance of a particular implementation, but it works for all others.

Does this sound like a long term solution? Or has anyone found something better, which allows the message pump to properly update and show the dialog box?

Regards,

Glossifah

Eric
04-19-2001, 10:42 PM
Glossifah,

I have always used a timer in my MFC apps for animation. As Martin stated, if you do not do that, the UI messages (redrawing buttons, toolbars, ...) won't get processed (because of the 100% CPU).

As far as I am concerned, I have always done it this way and hence would say this is not only a long-term solution but this should be the way to go !

Regards.

Eric

clucches
04-20-2001, 07:29 AM
Originally posted by martin_marinov:
Hi,
I also program using MFC and OpenGL and I've never had this problem - I've written a small demo, which uses dialog boxes(the Color Dlg too), which may be displayed over the ogl window during the animation. No problems with the dialog boxes. But I've heard also that other people have the same problem like you.... However, the ON_UPDATE_COMMAND handlers are executed when there is idle time in the application... So if you use the processor at 100%, you may never update the enabled/checked state of your buttons(commands).
If you wish, you can download my demo from my home site: http://medo.dir.bg (Animating implicit surfaces)
Hope this helps
Martin

[This message has been edited by martin_marinov (edited 04-19-2001).]
1)
Your program has the same problem: when i click on |?| button the about bos doesn't appear untill i press <ALT> key.
2)
Timer for animation... is it the fastest way???
3)
you open the common dialog from the main SDI window. I open common dialogs from the main window whitout problems. troubles arises when i try to open them form a method of a floating panel... I tried to force drawing with ShowWindow(?S_SHOW); Invalidate::; Now All the window is drawn [B] BUT BORDERS [\B]


[This message has been edited by clucches (edited 04-20-2001).]

[This message has been edited by clucches (edited 04-20-2001).]

kehziah
04-20-2001, 08:14 AM
Timer for animation... is it the fastest way???
From my own experimentations, I'd say that standard timers (ie those created with SetTimer) are good if you don't need high framerates. 20-25 fps (ie timer with 50-40 ms delay) seems to be the limit : under 40 the timer will not send the message fast enough (or your app's message pump won't process it fast enough).

So if you want more than 25 fps, I suggest you overload the OnIdle function. Each time it is called, you check with the performance counter if your delay has elapsed or not and call your rendering method if necessary.

martin_marinov
04-20-2001, 08:18 AM
Originally posted by clucches:
1)
Your program has the same problem: when i click on |?| button the about bos doesn't appear untill i press <ALT> key.

Yes, you are right - In face I've never tested the about box. I faked myself, since the color dlg worked without problems.



2)
Timer for animation... is it the fastest way???


Standart timers - no - their resulotion is too big.
I worked over the problem - so it really seems that ShowWindow(SW_SHOW) is solving the problem, even if I don't use timers(instead I call Invalidate() in the end of OnDraw() )
I'll find some time to update the demo on my site today.

Regards
Martin