Thread: Window goes offscreen - messes up

  1. #1
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465

    Window goes offscreen - messes up

    I guess my problem can be best expressed by a screenshot.

    http://img.photobucket.com/albums/v2...1/e4656cd0.jpg

    This happens when I hold down the mouse over the caption, drag it down (window recieves WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED notifications) so the client area is below the start menu, and pull it back up. This whole thing I think is complicated by several factors. One is that this sort of a game application, so my message loop uses peekmessage and does a paintroutine while it idles between messages, I do not handle WM_PAINT messages. So, if I tried to just invalidaterect when I recieve these messages, it doesn't rect do anything. Also, I can change this if I need to, but I also have it so that WM_ERASEBKGND just returns and does not do anything. Is there any way that I can fix this problem?

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    903
    I have no idea what can cause that problem but I can suggest you to use the double-buffering technique and to clear the background (i.e. fill it with some color, usually black), just in case you aren't already doing it.

  3. #3
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>so my message loop uses peekmessage and does a paintroutine while it idles between messages, I do not handle WM_PAINT messages

    The issue is due to you not processing paint msgs or the paint msgs being ignored because of the larger number of mouse msgs in the OS msg queue.

    It probably fixes itselt as soon as you stop moving the mouse and the msg queue is no longer full of mouse msgs.

    I would try using UpdateWindow() and calling your drawing routine from WM_PAINT (as well as from the Idle msg). This may cause other issues though.....ie infinte loop of redraws

    InvalidateRect() //set this area to be redrawn
    UpdateWindow() //send a paint msg directly to the windows callback ie bypass the OS msg queue.
    "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

  4. #4
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    >> It probably fixes itselt as soon as you stop moving the mouse and the msg queue is no longer full of mouse msgs.

    Yep, probably. So, I rearranged to some of my WindowProc to have

    Code:
    		case WM_PAINT:
    		{
    			PAINTSTRUCT ps;
    			::BeginPaint(hwnd, &ps);
    			PaintRoutine(hwnd);
    			::EndPaint(hwnd, &ps);
    			break;
    		}
    		case WM_ERASEBKGND: 
    			return 1;
    And my message loop to

    Code:
    	while(true)
    	{
    		if(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			if(msg.message == WM_QUIT) break;
    
    			::TranslateMessage(&msg);
    			::DispatchMessage(&msg);
    		}
    		else
    		{
    			::UpdateWindow(hwnd);
    			::Sleep(100);
    		}
    	}
    And now it is smooth, I don't have the problem, it just takes a bit of CPU (30% - 40%) when I move the window around a bit. I don't think that's a problem?
    Last edited by Tonto; 07-20-2006 at 01:56 PM.

  5. #5
    Registered User divineleft's Avatar
    Join Date
    Jul 2006
    Posts
    158
    No, that cpu usage is normal when you move the screen.

  6. #6
    Registered User
    Join Date
    May 2005
    Location
    Texas
    Posts
    103
    Maybe the brush that paints the window, is NULL, or something that "Paints" is NULL....
    Be easy on me...only 14

  7. #7
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >.And now it is smooth, I don't have the problem, it just takes a bit of CPU (30% - 40%) when I move the window around a bit. I don't think that's a problem?

    Not unless you need to run other apps.

    PeekMessage() will return if there is not a msg for your app in the OS queue. You can then process/update and PeekMessage() is called again. This happens as fast as your PC can do this. Most PeekMessage() apps therefore use 100% CPU. Try taking out that sleep().....

    GetMessage() will not return _until_ there is a msg for your app. This allows the OS to time slice with other apps.
    "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

  8. #8
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Well the same increase in CPU usage seems to happen with other applications like iTunes, MSVC, blah blah blah, so I don't think it's a problem. I did change it to a GetMessage loop though, and the app doesn't have any visible performance loss.

  9. #9
    Registered User Queatrix's Avatar
    Join Date
    Apr 2005
    Posts
    1,342
    Tonto,

    Filtering Alert!!!

    K9 Web Protection got your image link as "Hacking/Proxy Avoidance", you might want to move to a different image hoster.

  10. #10
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Man, it's photobucket, filtering software is retarded (are you at school or something?). Okay, I don't think this is appropriate to make a new thread for, because it's a really bad question, and I don't actually want someone to help me unless they are really bored. Just look at all this as me thinking aloud unless your heart compells you to actually look at this.

    Here is what I thought my problem was: I thought that maybe somewhere, an object is being copied, instead of being assigned a reference. But it does appear that s.find returns a reference to a Thingy inside the vector (made known by alerting the value of the reference, and of 'this'), so I don't think this is the problem any more. So, let me explain a little.

    Okay, I have this, it detects whether you pressed an arrow key, and moves an object on the 'screen'. My 'screen' has a vector of things which all have ID values, which I can retrieve them by (throws exception if ID is not found). Each object has a method to move them in a direction. After I move them, I update the 'screen' (which adds the now changed object back to the screen grid) and then re paint the window.

    Code:
    		case WM_KEYDOWN:
    			try
    			{
    				Thingy & t = s.find(CIRCLE_ID);
    				switch(wParam)
    				{
    					case VK_UP: t.move(Thingy::up); break;
    					case VK_RIGHT: t.move(Thingy::right); break;
    					case VK_LEFT: t.move(Thingy::left); break;
    					case VK_DOWN: t.move(Thingy::down); break;
    				}
    
    				s.update();
    				::UpdateWindow(hwnd);
    			}
    			catch(std::exception & e)
    			{
    				ErrorMessage(_T("Error: %s"), e.what());
    			}
    			break;
    Here is how update is implemented, I'll figure out optimizing these methods later.

    Code:
    void Screen::update()
    {
    	for(int _i = 0; _i < _x; ++_i)
    		for(int _j = 0; _j < _y; ++_j)
    			scr[_i][_j] = RGB(0, 0, 0);
    
    	for(std::vector<Thingy>::iterator i = v.begin(); i != v.end(); ++i)
    		for(std::vector<Pixel>::iterator j = i->coords.begin(); j != i->coords.end(); ++j)
    			scr[j->c.x][j->c.y] = j->cr;
    }
    'scr' is a 2-D grid of COLORREF values. 'v' is an std::vector<Thingy> of the things stored on the screen. 'coords' is an std::vector<Pixel> which is a set of Pixels in the Thingy. Here is how some less important methods are implemented Screen::find, Thingy::move

    Code:
    Thingy & Screen::find(int id)
    {
    	for(std::vector<Thingy>::iterator i = v.begin(); i != v.end(); ++i)
    	{
    		if(i->getId() == id)
    		{
    			return *i;
    		}
    	}
    	throw std::exception("id not found");
    }
    Code:
    void Thingy::move(direction d)
    {
    	int x = 0, y = 0;
    	switch(d)
    	{
    		case up: y = -1;
    		case down: y = 1;
    		case left: x = -1;
    		case right: x = 1;
    	}
    
    	for(std::vector<Pixel>::iterator i = coords.begin(); i != coords.end(); ++i)
    	{
    		i->c.x += x;
    		i->c.y += y;
    	}
    }
    I can not see why it is not working now. The thingy on the screen displays fine, but I can not get it to move!

  11. #11
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Woops. Changed move()'s switch-case to have breaks. Still does not work.

    Code:
    void Thingy::move(direction d)
    {
        int x = 0, y = 0;
        switch(d)
        {
            case up: y = -1; break;
            case down: y = 1; break;
            case left: x = -1; break;
            case right: x = 1; break;
        }
    
        for(std::vector<Pixel>::iterator i = coords.begin(); i != coords.end(); ++i)
        {
            i->c.x += x;
            i->c.y += y;
        }
    }

  12. #12
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Some more audible thinking aloud. While I'm reassigning stuff to my 'screen' I now output debug info.

    Code:
    	for(std::vector<Thingy>::iterator i = v.begin(); i != v.end(); ++i)
    	{
    		OutputDebugString(_T("\nTest\n\n"));
    		for(std::vector<Pixel>::iterator j = i->coords.begin(); j != i->coords.end(); ++j)
    		{
    			ErrorMessage(_T("%d %d\n"), j->c.x, j->c.y);
    			scr[j->c.x][j->c.y] = j->cr;
    		}
    	}
    Apparently, everything should be working correctly. Here's the debug output:

    Test


    51 60
    51 40
    49 60
    49 40

    // Data clipped just to show you main idea //

    50 40
    60 50
    40 50

    ... 9 up keystrokes later ...


    Test


    51 51
    51 31
    49 51
    49 31

    // Data clipped again //

    50 31
    60 41
    40 41

  13. #13
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    I feel stoopid

    Code:
    		case WM_KEYDOWN:
    
    				...
    
    				s.update();
    				::InvalidateRect(hwnd, NULL, TRUE);
    
    				...
    
    			break;
    Now it works. The update region was empty so I guess a WM_PAINT message was not sent as I had hoped. Yarr.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. WM_CAPTION causing CreateWindowEx() to fail.
    By Necrofear in forum Windows Programming
    Replies: 8
    Last Post: 04-06-2007, 08:23 AM
  2. 6 measly errors
    By beene in forum Game Programming
    Replies: 11
    Last Post: 11-14-2006, 11:06 AM
  3. My Window Class
    By Epo in forum Game Programming
    Replies: 2
    Last Post: 07-10-2005, 02:33 PM
  4. Pong is completed!!!
    By Shamino in forum Game Programming
    Replies: 11
    Last Post: 05-26-2005, 10:50 AM
  5. OpenGL Window
    By Morgul in forum Game Programming
    Replies: 1
    Last Post: 05-15-2005, 12:34 PM