Animation With MFC

I have a program written using MFC, and I am having problems animating it. I can draw each scene appropriately, but I can’t get MFC to redraw the scene unless I resize the window, or pull down a menu. I guess what I am looking for is a way to call OnDraw() or OnPaint whenever the program is idle. Does anyone know how I would go about this? I have been able to do this with an Invalidate( FALSE ) call, but this causes other problems so I am hoping to find another way around this problem.

-Drew

Windows is an event driven system.
I am not sure how to set it up in MFC, but you have a timmer type event.

On_Event_timmer() //do something

Event_timmer( int intervals ) // trigger a event every X intervals
// Run’s sending a Event signal, until a null value is sent

Something that that effect.

Originally posted by jleffelm:
[b]I have a program written using MFC, and I am having problems animating it. I can draw each scene appropriately, but I can’t get MFC to redraw the scene unless I resize the window, or pull down a menu. I guess what I am looking for is a way to call OnDraw() or OnPaint whenever the program is idle. Does anyone know how I would go about this? I have been able to do this with an Invalidate( FALSE ) call, but this causes other problems so I am hoping to find another way around this problem.

-Drew[/b]

Originally posted by nexusone:
[b]Windows is an event driven system.
I am not sure how to set it up in MFC, but you have a timmer type event.

On_Event_timmer() //do something

Event_timmer( int intervals ) // trigger a event every X intervals
// Run’s sending a Event signal, until a null value is sent

Something that that effect.

[/b]

Thank you very much for setting me in the right direction. Things seem to be working now.

-Drew

There are other ways besides using a timer. See www.mcfogl.com

Okay, I have tried the method on mfcogl.com, and came across a bunch of problems. But for this question, let’s assume that I had it correcct, and it was working, I guess I am curious which is better, to do it similiar to the mfcogl method(which I didn’t comprehend enough to see what is going on) or to just use MFC OnTimer event to call the OnPaint or OnDraw function with a delay of 1 or 0 milliseconds? Just curious, thank you for your time and effort.

-Drew

OnInitDialog()
{
this->SetTimer()
}

OnTimer()
{
SendMessage(WM_PAINT);
}

jleffelm,

The OnTimer() relies on Windows timers that are Windows OS dependent. NT and W2K aren’t the same as W95 or W98. Therefore if you want to set and control an accurate frame rate you need to build your own timer function see www.mfcogl.com for a hi-res timer. Most of the mfcogl animation demo simply use Invalidate calls to put the windows message loop in an infinite loop and the OpenGL frames are drawn as fast as Windows can process the messages to draw the OpenGL scenes. Some get bothered by the fact that this eats up close to 100% of the cpu cycles. This is usually of no concern, but you can allow other processes more cycles by using Sleep(xx). Sleep again depends on grainy OS depedent timers and you won’t get millisecond accuracy, see MSDN or your compilers help files.

Originally posted by cwc36:
[b]OnInitDialog()
{
this->SetTimer()
}

OnTimer()
{
SendMessage(WM_PAINT);
}[/b]

Thank you all for replying, I am getting a better understanding of things. I have one more question, and this probably isn’t the right forum for it, but since it was brought up. You menitoned

OnTimer()
{
SendMessage(WM_PAINT);
}[/b]

What is the difference between the SendMessage(WM_PAINT) (see I am new to windows programming!) and just making an OnPaint() call? Does it matter? And does setting the timer to 0 milliseconds do pretty much the same thing as calling INVALIDATE( FALSE )? Just curious, thanks for all the input.

-Drew

Originally posted by jleffelm:
[b]I have a program written using MFC, and I am having problems animating it. I can draw each scene appropriately, but I can’t get MFC to redraw the scene unless I resize the window, or pull down a menu. I guess what I am looking for is a way to call OnDraw() or OnPaint whenever the program is idle. Does anyone know how I would go about this? I have been able to do this with an Invalidate( FALSE ) call, but this causes other problems so I am hoping to find another way around this problem.

-Drew[/b]

There is a settimer API … use that to generate a message every n milliseconds, that will call function ONTIMER, in which you redraw the scene, using your own function, & swapbuffer(DC).

I must come here with right answers.

First. Timer Fuctions are bad as hell. Why? They have the lowest
priority of all messages that are in the message queue. So try running
a mouse very fast or dragging a different window. The Timer messages
will be ignored since more important messages are in the queue.

Another very important question. What is the difference between Send
Message and InvalidateRect.

The difference is big. InvalidateRect doesn’t wait for the message to
be executed, and SendMessage does!! This is very importand when You
draw i.e. four windows with i.e. four different views of an object.
Then if You’re using InvalidateRect then the first window will send 10
messages while the rest of the windows will send only 2 or 1. When
You’re using SendMessage then every window will be drawn exactly the
same times. A pain lies in the way that SendMessage(WM_PAINT is
posted. You must use another WM (different from WM_PAINT to post it
(i.e WM_TIMER ).
There was a time when I managed to run these four windows in the same
time properly. The trick is to make your own message queue managed by
separate threat, that is sending SendMessage to specified windows.

And that all.

C Ya. I hope it will help you in finding the right way.

Bonzaj

Invalidate(FALSE)

Put that right after you call your draw function in OnPaint()

What “other problems” do you have when using Invalidate() ? In my opinion, (as far as the app is concerned) Windows can and will be invalidating client areas at unexpected times - which have to be accommodated. The OnDraw() routine merely draws the “state” of the data and should not cause any side effects.

With this in mind, you then could override the CWinApp::OnIdle() routine. In that routine, you then could do something like go thru all your applicable document templates and simply call UpdateAllViews() for each document. This can be further refined by utilizing hints. Lots of possibilities here.