CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11

Thread: Flooded WndProc

  1. #1
    Join Date
    Jul 2009
    Posts
    154

    Flooded WndProc

    Hello,

    I have this situation on Windows XP:

    My program is a window, so it has an entry in the task bar.

    If you rightmouse click on the item in taskbar (so that menu appears with Close, Maximize, Minimize, etc), then the window freezes because the WndProc gets flooded.

    1. WM_NCHITTEST
    2. WM_SETCURSOR
    3. WM_MOUSEMOVE
    and then start at 1. again. Infinitely until the rightmouse menu is gone again.

    How to prevent this? The messages get passed to the "return DefWindowProc()", so my code doesnt even handle the message in my WndProc.

    Code:
    while( DoAllPeekMessage() ) //<--- stuck here because flooded with message see above
    {
       Render(); //<-- never gets here in the stuck situation so window looks 'frozen'
    
       //etc.
    }
    Thank you for your time.
    Last edited by ProgrammerC++; June 29th, 2011 at 05:24 PM.

  2. #2
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Flooded WndProc

    What's in DoAllPeekMessage?
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  3. #3
    Join Date
    Jul 2009
    Posts
    154

    Re: Flooded WndProc

    Code:
    BOOL CWindow::DoAllPeekMessage()
    {
    	MSG msg;
    	while( PeekMessageA( &msg, NULL, 0, 0, PM_REMOVE ) )
    	{
    			if( msg.message == WM_QUIT )
    				bExit = TRUE;
    
    			TranslateMessage( &msg );
    			DispatchMessageA( &msg );
    	}
    
    	return !bExit;
    }

    By the way on Windows 7 it's also possible by holding the Caption Bar of the Window and then move it around, will freeze the Window (flooding messages) until you let mouse go

  4. #4
    Join Date
    Jul 2009
    Posts
    154

    Re: Flooded WndProc

    Nevermind, it's a 'feature' of Windows.

    I'll see if I can build a workaround.

  5. #5
    Join Date
    Jul 2002
    Posts
    2,543

    Re: Flooded WndProc

    The standard way is to render window on WM_PAINT message and not at idle time. If you need to redraw window constantly, execute multimedia timer and update the window on every timer tick. Drawing is still done in paint message handler.

  6. #6
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: Flooded WndProc

    Quote Originally Posted by ProgrammerC++ View Post
    Nevermind, it's a 'feature' of Windows.

    I'll see if I can build a workaround.
    No. Its a bug in your program. Do you think everyone is writing 'workarounds' for something as simple as right clicking on the task bar entry??

  7. #7
    Join Date
    Jul 2009
    Posts
    154

    Re: Flooded WndProc

    Quote Originally Posted by Martin O View Post
    No. Its a bug in your program. Do you think everyone is writing 'workarounds' for something as simple as right clicking on the task bar entry??
    No my program is a game and the code is not bugged.

    This 'feature' of windows occurs on many games actually I can confirm.

  8. #8
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: Flooded WndProc

    Quote Originally Posted by ProgrammerC++ View Post
    No my program is a game and the code is not bugged.

    This 'feature' of windows occurs on many games actually I can confirm.
    Not 'bugged', except for the problem you just posted that is? Can you post a simplified project demonstrating the problem so people can actually confirm this instead of just having to take your word for it? Can you name any other *known* software, games, whatever, that you say also show this so called 'feature'? I mean, actually name them? Help us out here, otherwise no-one can help you fix your problem. Because there's certainly no problem right clicking on any of the Win32 / MFC programs I've ever written or even used. I've never needed to write any workarounds for that. You're not still flailing around with basic Win32 message loops are you? I remember you from a post last year 'SetTimer serious bug' ...'guess I found a pretty serious bug'...then it turned out you really didn't even know what you were doing:
    http://www.codeguru.com/forum/showthread.php?t=492477

  9. #9
    Join Date
    Jul 2009
    Posts
    154

    Re: Flooded WndProc

    Games like Half-Life 1, Counterstrike I tested on aswell.

    You can reproduce the bug simply by making a new standard Win32 Application project in Visual Studio.

    Then, make the following changes to the code:

    In InitInstance(HINSTANCE hInstance, int nCmdShow), make "HWND hWnd" a global parameter.

    And replace:
    Code:
    	// Main message loop:
    	while (GetMessage(&msg, NULL, 0, 0, PM_REMOVE))
    	{
    		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    With:
    Code:
    	// Main message loop:
    	int i = 0;
    
    	do
    	{
    		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    			{
    				TranslateMessage(&msg);
    				DispatchMessage(&msg);
    			}
    		}
    
    		i++;
    
    		char title[32];
    		wsprintfA(title, "&#37;d", i );
    
    		SetWindowTextA(hWnd, title);
    
    	} while(true);
    Then run the program, and in the Task Bar (Windows XP) right click window item and you'll see the Window Caption does not get updated with the new number (meaning message infinite). Also on all Window version, while moving the window (leftmouseclick on Caption bar of Window) the message loop also gets infinitely spammed with message until you let mouse go.

    Proven, known issue with Windows I figured on GameDev.net already, there are only some work arounds using WM_TIMER. Most commercial games don't even bother it though.

  10. #10
    Join Date
    Jul 2002
    Posts
    2,543

    Re: Flooded WndProc

    Yes, game developers like to make idle time rendering. If you are happy to have the same bug as in many other games, it is OK This is just incorrect Windows programming. In one of my projects (though it was not a game) I needed to redraw window constantly with the same frequency as screen refresh rate (well known image tearing problem) using Direct3D. I did this using multimedia timer (note - multimedia timer, not WM_TIMER).
    Don't break Windows programming rules, don't be afraid to write better than other programmers.

  11. #11
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556

    Re: Flooded WndProc

    I agree with others here that the offending code is yours, and it's not a bug/feature of Windows.

    Your code uses the so-called "gaming loop", which relies on PeekMessage:
    Quote Originally Posted by ProgrammerC++
    Code:
    while( DoAllPeekMessage() ) //<--- stuck here because flooded with message see above
    {
       Render(); //<-- never gets here in the stuck situation so window looks 'frozen'
    
       //etc.
    }
    The stated purpose of the "gaming loop" is that the rendering will take place at as fast a frame rate as the machine permits while there are no messages in the message queue, and when messages arrive in the queue, they are handled with priority over rendering.

    But as you have found, that's not the way it works in practice:
    Quote Originally Posted by ProgrammerC++ View Post
    By the way on Windows 7 it's also possible by holding the Caption Bar of the Window and then move it around, will freeze the Window (flooding messages) until you let mouse go
    Rendering actually will not take place at all, i.e., a zero frame rate, whenever you hold the caption bar or whenever you do something (like re-size or move) that causes the application to enter a modal state.

    And that's the flaw with the "gaming loop": It completely overlooks well-documented Windows behavior about applications that enter a modal loop. Applications enter a "modal loop" under a viariety of circumstances, such as whenever they display a modal dialog (like a raw API call to ::MessageBox or ::DialogBox), or whenever the user clicks the window's title bar or sizing border, or whenever the window passes the WM_SYSCOMMAND message to DefWindowProc. While in a "modal loop", the application's own message loop is bypassed, and all messages to the application are handled internally by Windows, in a message pump that guarantees that the application remains modal.

    So, the reason that you are seeing this behavior is well-known, and is because your application is in a modal loop that completely bypasses your own message loop.

    The "gaming loop" is flawed for this reason, and others have noted it before.

    Moreover, the basic principle of the gaming loop is frankly unfair to other applications running on the machine. It's frankly unfair to allow any one application to grab all the processing power available in the machine in order to render at as high a frame rate as possible. I have seen these applications proudly display frame rate numbers in the corner of the display as high as several hundreds of frames per second. Who needs a frame rate that high anyway?

    The fix is to use better code. Alex F has correctly suggested timers that invalidate the window at a predetermined high rate that is fair to all applications running on the machine.

    Mike
    Last edited by MikeAThon; July 2nd, 2011 at 02:35 PM. Reason: To disable smilie rendition of ::DialogBox and to delete reference to MsgWaitForMultipleObjects, which wouldn't solve this

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured