6

I'm new to native c++. Right now, I made it so when I press the left mouse button, it has a for loop that does InvalidateRect and draws a rectangle, and increments X by the box size each time it iterates. But, C++ is so much faster and efficient at drawing than C# that, it draws all this instantly. What I would like is for it to invalidate the rectangle, show the rectangle, wait 50ms, then continue the loop. I tried Sleep(50) but it still waits until painting is done before showing the result. I also tried PeekMessage but it did not change anything. Any help would be appreciated. Thanks

Kim Gräsman
  • 7,438
  • 1
  • 28
  • 41
jmasterx
  • 52,639
  • 96
  • 311
  • 557

2 Answers2

18

DoEvents basically translates as:

void DoEvents()
{
    MSG msg;
    BOOL result;

    while ( ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE ) )
    {
        result = ::GetMessage(&msg, NULL, 0, 0);
        if (result == 0) // WM_QUIT
        {                
            ::PostQuitMessage(msg.wParam);
            break;
        }
        else if (result == -1)
        {
             // Handle errors/exit application, etc.
        }
        else 
        {
            ::TranslateMessage(&msg);
            :: DispatchMessage(&msg);
        }
    }
}
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 3
    +1, almost correct, except that the return value of GetMessage is not checked and WM_QUIT is not correctly handled. – Filip Navara Sep 12 '09 at 13:23
  • 2
    If GetMessage return 0, then the WM_QUIT message needs to be reposted (http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx). GetMessage can also return -1, which should be handled. – Filip Navara Sep 12 '09 at 13:29
  • 1
    @FilipNavara I had intended for this to just show the basics, but you're absolutely right - edited to show all 3 possible cases. – Reed Copsey Nov 25 '11 at 21:08
  • @FilipNavara That being said, `Application.DoEvents` is actually closer to my original... It *should* do this, but it doesn't... – Reed Copsey Nov 25 '11 at 21:14
2

I am a bit rusty in Win32 API, but the asynchronous way of doing this would be:

  • Invalidate the rect
  • Set a timer (see below) to send a message after 50ms
  • Return to the event loop to let WM_PAINT events happen
  • On receiving the timer message, move the rect, then repeat

This way integrates nicely with being event driven. I realize this is not exactly what you ask for, but I thought I'd mention it as a possible solution anyway :)

EDIT: A quick google turns up the Windows API call [SetTimer](http://msdn.microsoft.com/en-us/library/ms644906(VS.85,loband).aspx) which you can use to facilitate this. The message will be a WM_TIMER one.

Magnus Hoff
  • 21,529
  • 9
  • 63
  • 82