Thread: WinMain() just after message loop...

  1. #1
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879

    WinMain() just after message loop...

    My program is acting kinda funny.. this is part of my code:

    Code:
    struct BUFFER
    {
         HDC dcFront;   //screen
         HDC dcBack;   //back buffer
         HDC dcBitmap;   //never mind about this one for now
         (...)
    };
    Code:
    //somewhere in WinMain():
    
    while(!done)
    {
         if(PeekMessage(...))
              (...)
         else
         {
               drawBG();   //displays the background (a bitmap)
               ship.move();  //changes ship.pos, which is a POINT
               ship.draw(buff);  //displays the bitmap of the ship
               swapBackBuffer(buff, true);   //BitBlt()'s dcBack into dcFront
         }
    }
    If I try running this, it freezes the program. But, if I add "Sleep(1);" after swapBackBuffer() (or any sleep except for 0), it will run ok. Does anybody know why?
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Could have something to do with PeekMessage() returning a TRUE if there is a msg and not removing PAINT msg's until their update region is validated by BeginPaint().
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    It shouldn't be, because under WM_PAINT I have BeginPaint() and EndPaint(). Besides, why would a Sleep() fix it?...
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Only WM_TIMER msg's have lower priority in the que than PAINT and there is a limit to the number in the que (8 I think). So if they may not get removed from the que straight away. The sleep() may post a lower priority msg that allows them to be removed?

    Are you calling for a paint msg after the 'else' section, doing the drawing? (InvalidateRect() not UpdateWindow() as this bypasses the msg que, AFAIK)

    Maybe there are no messages in the que. Your Sleep() posts one.

    Could be the freeze is the 'else' loop being run over and over with no change in the ships position.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  5. #5
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Hmm... I'll give that a thought. Actually, I don't use InvalidateRect(), or UpdateWindow() either for that matter... I used to use RedrawWindow(), but not right now. I'm just using GetDC() to get the HDC for the screen, and storing it in the BUFFER struct. Then I SelectObject() a bitmap into dcBitmap (in the BUFFER), BitBlt() that into dcBack as well as whatever else, then BitBlt() dcBack into dcFront (the screen). Should I be doing something differently?

    oh yeah... I don't know about the ship's position not changing, because when you press W, A, S, or D, it sets different bools to true, and when you release them, it sets them to false. Then ship.move() checks if they are true, and if they are, then it changes the ship's position.

    And I don't see how Sleep() posting a message would help, because if it posts a message, wouldn't it skip the else?... besides, I'm not using any timers.
    Last edited by Hunter2; 05-31-2002 at 04:59 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>because when you press W, A, S, or D, it sets different bools to true, and when you release them, it sets them to false.

    Which will be WN_KEYDOWN msg's. There for PeekMesage() will return TRUE. So the 'else' will not run. The ship will not move. The WM_KEYUP will come and the 'else' will not run again. And now the flag is FALSE again.

    If using mouse msg's make sure you are SetCapture()'ing. Beware of debugging with ClipCursor() on (ClipCursor(NULL) to remove)

    I would for the DC's
    (I am doing this from memory so check the params)
    Code:
    //on create
    hdc=GetDC(hWnd);//or null for default display
    buff.hdcScreen=CreateCompatibleDC(hdc);
    
    //if not loading from file
    buff.bmpScreen=CreateCompatibleBitmap(hdc);//store the bmps in the struct as well
    
    //get bitmap in there
    buff.bmpScreenOriginal =SelectObject( buff.hdcScreen, buff.bmpScreen);// catch the original
    
    ReleaseDC(hdc);
    //repeat for other DC's
    
    //do drawing on  buffer DC
    //copy buffer to screen DC
    //call for paint
    
    //in paint 
    GetUpdateRect(hWnd,&Rect)
    if(IsRectEmpty(&Rect))
       GetClientRect(hWnd,&Rect);//or area used to create DC
    //BeginPaint catch the HDC or use the one returned in the paint struct
    //BitBlt() screen to paint DC
    //end paint
    
    //on close
    //SelectObject(buff.hdcScreen,  buff.bmpScreenOriginal);
    DeleteObject(buff.bmpScreen);
    DeleteDC(buff.hdcScreen);
    
    //repeat for other DC's
    Or similar
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  7. #7
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Umm, but isn't WM_KEYDOWN only posted once when you press the key? So once the bool(s) are set to true, the WM_KEYDOWN is gone and the WM_KEYUP hasn't been posted yet. So then, there are no messages and the 'else' runs, changing the ship's position... besides, (yet again!) why would the Sleep() fix it?
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  8. #8
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    from MSDN
    >>Because of the autorepeat feature, more than one WM_KEYDOWN message may be posted before a WM_KEYUP message is posted.

    0-15 lparam
    Specifies the repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.

    >>So then, there are no messages and the 'else' runs,

    Except the paint the else generates as it redraws the screen. Remember that it may redraw the screen without you actually seeing the changes.

    Why not put the drawing functions in the callback called in response to the correct WM_KEY*** msg?
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  9. #9
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    *correction* ok, so there's more than one WM_KEYDOWN posted. But between messages, shouldn't there be an interval in which the else gets run? (and so... why does the sleep() help?)

    And I wanted the drawing done in the else, because it's supposed to be space invaders, and the aliens are constantly moving, not just when a key is pressed.

    BTW, how does a screen get redrawn without me seeing changes? (and BTW #2, I'm pretty sure my else doesn't generate a WM_PAINT - all the drawing/painting is done with GetDC() as of the moment.)
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  10. #10
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    You can change the HDC but not have it drawn properly. Particularly if using the debugger while drawing. Try putting a break point in a paint function to see what I mean (will put you in an endless loop).

    Try testing your paint function in a standard response (ie to the WM_KEYDOWN in the callback) and ensure it works, then put it back in the loop.

    I don't think your design is 100%. I don't know if PeekMessage() is timed and with the msg's it may/may not find will return at a constant interval. If it does not the invaders will not move at a constant rate.

    I do video from still jpg images and just use a timer msg to tell me when to update the screen.

    why not
    Code:
    PeekMessage()
    {
        if(UserInput)
            DoPlayerStuff()
        MoveInvaders()
        RedrawScreen()
    }
    >>why does the sleep() help

    You are using PM_REMOVE? The paint msg's are not removed from the que until the area is validated by a call to BeginPaint(). Until then they are in the que. The que holds only about 8 msg's and the sleep may allow them to be cleared.
    Last edited by novacain; 06-05-2002 at 09:57 PM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  11. #11
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    I've tried putting my paint in WM_KEYDOWN and it works fine. And no, my design isn't "100%" (whose are?).

    When my program hits a WM_PAINT, it *should* call BeginPaint() and EndPaint(), although there's nothing between them.

    The timer thing sounds like a good idea, though But I'm sort of using a different method... (and by the way, is this the problem?)

    This is the else:

    Code:
    else
    	{
    		_timeb time;
    		_ftime(&time);
    		long counter = time.time * 1000 + time.millitm;
    		drawBG(hWnd);
    		moveAliens(hWnd);
    		ship.move();
    
    		drawAliens(buff);
    		ship.draw(buff);
    
    		swapBackBuffer(buff, true);
    
    		_ftime(&time);
    		if(20 - ((time.time * 1000 + time.millitm) - counter) > 1)
    			Sleep(15 - ((time.time * 1000 + time.millitm) - counter));
    		else
    			Sleep(1);
    	}
    *the Sleep(1) is just so that no matter what the prog won't freeze.
    Last edited by Hunter2; 06-06-2002 at 02:15 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  12. #12
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Again, I think the else is the problem. No game I have seen uses an else in the msg loop (based on the return from PeekMessage()).

    Try taking it out.

    (GetTickCount() is the WIN32 time function. Returns in millsec.)

    >>if(20 - ((time.time * 1000 + time.millitm) - counter) > 1)
    Sleep(15 - ((time.time * 1000 + time.millitm) - counter));

    could generate a -ve time.

    (20-18 is greater than 1, 15-18 = sleep(-3))
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  13. #13
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Whoops, forgot to change the 20 to a 15... Thanks about the GetTickCount() thingee too!

    I used to just use this:

    Code:
    while(PeekMessage())
    {
            ....
    }
    
    (whatever else, such as drawing, etc...)
    and I think it used to do the same thing. I'll try it again though - I only used the else because I saw it in a tutorial and assumed that that was how it should be done. How do you usually set it up?
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. syntax question
    By cyph1e in forum C Programming
    Replies: 19
    Last Post: 03-31-2006, 12:59 AM
  2. Scope And Parameter Passing
    By djwicks in forum C Programming
    Replies: 6
    Last Post: 03-28-2005, 08:26 PM
  3. problem with open gl engine.
    By gell10 in forum Game Programming
    Replies: 1
    Last Post: 08-21-2003, 04:10 AM
  4. Help, the window gets killed......
    By incognito in forum Game Programming
    Replies: 2
    Last Post: 05-28-2002, 02:22 PM