Click to See Complete Forum and Search --> : periodically drawing in view


Exp
May 31st, 1999, 05:44 PM
hello,
I need to draw periodically and fast a line pixel by pixel. I tried WM_TIMER, but I can't get fast updates. I tried calling Invalidate in the OnDraw() but I have update problems in the view, namely the menu bar and status bar. Can someone help me out with this.
Thanks in advance.

Dan Haddix
May 31st, 1999, 07:00 PM
Look into Multimedia Timers they are faster and more accurate then standard timers.

Josh Handley
June 1st, 1999, 11:12 AM
I find that doing my drawing in the OnIdle() method of my CWinApp derived class is much faster than using WM_TIMER messages. The problem with timers is that if you set your timer frequency to be fairly high you end up getting your message queue clogged full of WM_TIMER messages that build up. This slows the processing of other messages and means you don't get idle messages that update the state of the UI.

Basically in my OnIdle method I check the time elapsed since the last time I did a redraw and if it is greater than the rate at which I want to draw then I do a draw. For this to work you need to always return true from OnIdle otherwise OnIdle will stop getting called when the mouse isn't moved. The only time I return false is when the application is not active (minimized). Here's a code snippet:


BOOL CMyApp::OnIdle(LONG lCount)
{
BOOL bMore = CWinApp::OnIdle(lCount);

// if time since last draw is greater than 1/graphics_rate
// do drawing here.

if (((CMainFrame *) m_pMainWnd)->isAppActive())
{
// We always want idle messages when we can get them.
// If we return false we won't get idle messages again
// until MFC gets a message that triggers idle processing again.
return TRUE;
}
else
{
// If app isn't active then we don't need idle messages for graphics stuff
// - we can wait until it gets active again.
return bMore;
}
}




CMainFrame::isAppActive() is a method I added to my CMainFrame class that returns the value of a flag that is set whenever CMainFrame::OnActivateApp() is called.

I also added my own version of CWinApp::IsIdleMessage(). If you use the default version then you will stop getting idle messages when you activate the app via alt-tab.


// This is overriden from CWinThread so that we can get
// idle messages as long as app is active.
// The logic in OnIdle gets us most of the way there
// but it fails if you deactivate and activate the app
// using alt-tab.
BOOL CWinApp::IsIdleMessage(MSG* pMsg)
{
if (m_pMainWnd)
{
if (((CMainFrame *) m_pMainWnd)->isAppActive())
return TRUE;
}

return CWinApp::IsIdleMessage(pMsg);
}




Using this I'm able to get consistent updates at thirty hz - I haven't tried pushing it any further. If you need something more than this the multimedia timers are precise up to a millisecond on NT. Using them gets a bit more complicated since the timer callback gets executed in a different thread.

Josh

Harvey Hawes
June 1st, 1999, 12:03 PM
Hi,

I use the multimedia timer (but that OnIdle reply was cool...) like others have mentioned. With it I can maintain refresh rates of > 30Hz for 16 lines. You have to be careful of a few things... like:

1) The threading issue
2) Use CDC clipping regions for updating data
3) use memoryDCs (there are good "real-time" examples on this site-- look in the misc section. For timing see Hans' microsecond delay... or use a multimedia timer. For drawing see the oscilliscope [sp?] example. There are others as well)
4) You can fool the user: humans can only distinguish 30 frames per sec. If you want to simulate drawing faster than that, set you max refresh rate to 30 Hz, but draw two points at a time (to simulate 60 Hz) or three (90 Hz) etc...

I don't call OnDraw to update my lines. I create my own dc and draw in the timer handler (callback). I use OnDraw to redraw the entire screen only(i.e. when the user sizes window).

HTH,



Harvey Hawes

Software Engineer
BioScience Analysis Software Ltd.

Masters Candidate
Cardiovascular/Respiratory Sciences
Faculty of Medicine
University of Calgary
Calgary, Alberta, Canada