Jump to content
  • Advertisement
Sign in to follow this  
Nokturnal

Win32 Window Corruption [WM_PAINT] ?

This topic is 4649 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I have currently implemented a checkers game using win32 as gui. The game works perfectly.But there is a small problem i am facing. When the EXE is launched and moved around the desktop (i.e. apart from the position it was originally launched at numerous times) or when another application window is moved around it , it ends up corrupting the entire display (i.e. ever thing turns like Snow white's theme , every thing appears white-washed).On closing the application , things get back to normal. Here is a section of WM_PAINT , i reckon some where here is the culprit.

	case WM_PAINT: 
		{
		hdc = BeginPaint(hwnd,&ps);	 
		int i,j;
		////DrawBoard
		RECT rect;
		int x=0,int y=0;
		for(i=0;i<8;i++)
		{

			for(j=0;j<8;j++)
			{
			rect.top =x;
			rect.left=y;
			rect.bottom=x+50;
			rect.right=y+50;

			if((i+j)%2==0)
			FillRect(hdc, &rect, CreateSolidBrush(RGB(255,255,255)));
			
			if((i+j)%2==1)
			FillRect(hdc, &rect, CreateSolidBrush(RGB(0,0,0)));

			y=y+50;
			}
		x=x+50;
		y=0;
		}

		////Draw pieces

		x=0;y=0;

		for(i=0;i<8;i++)
		{
			for(j=0;j<8;j++)
			{
			rect.top =x;
			rect.left=y;
			rect.bottom=x+50;
			rect.right=y+50;
			
				switch(board[j])
				{
				case WHITE:
					SelectObject(hdc,CreateSolidBrush(RGB(0,0,255)));
					Ellipse(hdc,rect.top,rect.left,rect.bottom,rect.right);
					break;
				case BLACK:
					SelectObject(hdc,CreateSolidBrush(RGB(255,0,0)));
					Ellipse(hdc,rect.top,rect.left,rect.bottom,rect.right);
					break;
				case BKING:
					SelectObject(hdc,CreateSolidBrush(RGB(255,0,0)));
					Ellipse(hdc,rect.top,rect.left,rect.bottom,rect.right);
					SelectObject(hdc,CreateSolidBrush(RGB(0,0,0)));
					Ellipse(hdc,rect.top+10,rect.left+10,rect.bottom-10,rect.right-10);
					break;
				case WKING:
					SelectObject(hdc,CreateSolidBrush(RGB(0,0,255)));
					Ellipse(hdc,rect.top,rect.left,rect.bottom,rect.right);
					SelectObject(hdc,CreateSolidBrush(RGB(0,0,0)));
					Ellipse(hdc,rect.top+10,rect.left+10,rect.bottom-10,rect.right-10);

				default : 
					break;
				}
				y=y+50;
			}
			x=x+50;
			y=0;
		}
		

		
        EndPaint(hwnd,&ps);

		


		return(0);
   		} break;



and here is my window , creation / message loop.

int WINAPI WinMain(	HINSTANCE hinstance,
					HINSTANCE hprevinstance,
					LPSTR lpcmdline,
					int ncmdshow)
{

WNDCLASSEX winclass; // this will hold the class we create
HWND	   hwnd;	 // generic window handle
MSG		   msg;		 // generic message


winclass.cbSize         = sizeof(WNDCLASSEX);
winclass.style			= CS_DBLCLKS | CS_OWNDC | 
                          CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc	= WindowProc;
winclass.cbClsExtra		= 0;
winclass.cbWndExtra		= 0;
winclass.hInstance		= hinstance;
winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
winclass.lpszMenuName	= NULL;
winclass.lpszClassName	= WINDOW_CLASS_NAME;
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);



if (!RegisterClassEx(&winclass))
	return(0);


if (!(hwnd = CreateWindowEx(NULL,                  // extended style
                            WINDOW_CLASS_NAME,     // class
						    "Checkers!", // title
						    WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
					 	    0,0,	    // initial x,y
						    406,448,  // initial width, height
						    NULL,	    // handle to parent 
						    LoadMenu(hinstance,MAKEINTRESOURCE(IDR_MENU1)),	    // handle to menu
						    hinstance,// instance of this application
						    NULL)))	
return(0);


ShowWindow(hwnd,ncmdshow);
UpdateWindow(hwnd);


while(TRUE)
	{
	
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	   { 
       if (msg.message == WM_QUIT)
           break;
	   TranslateMessage(&msg);
	   DispatchMessage(&msg);
	   }
	Sleep(10);
	} // end while


return(msg.wParam);

} // end WinMain



I have made the window as WS_POPUP as i didnot want the user to resize and create a bigger mess. I have put in sleep as the application was trying to burn the cpu using 100% of it. In the game , on mouse capture , i am invalidating the entire client area using getClientRect / InvalidateRect. Any help is apprecited . Thanks!

Share this post


Link to post
Share on other sites
Advertisement
Quote:
or when another application window is moved around it , it ends up corrupting the entire display

I'm not sure I understand this part. You mean the WM_PAINT is not sent when there's window moving over it ?. You can check for this by placing a MessageBox () in WM_PAINT, it should be sent a WM_PAINT message when the client area needs redrawing (in this case).

Also:
  • You're not using ps, you can just provide it as NULL in BeginPaint ().
  • When calling InvalidateRect (), you can specify NULL for both fields to invalidate the whole client area. There's no need to call GetClientArea ().
  • You can get the HDC once as a static variable in WinProc and use that variable as a replace for BeginPaint () and EndPaint (). That way you can store the DC settings for use in future redrawings, then call ValidateRect () at the end of WM_PAINT to validate the client area. BeginPaint () and EndPaint () themselves basically do the same thing:
    static HDC hDC = GetDC (hWnd) ;

    switch (Msg)
    {
    case WM_PAINT:
    {
    ValidateRect (hWnd, 0) ;
    }
    case WM_CLOSE:
    {
    ReleaseDC (hWnd, hDC) ;
    }
    }

    Share this post


    Link to post
    Share on other sites
    Your WM_PAINT code looks almost allright. How do you check for mouse activities? Make sure you're not calling InvalidateRect all the time.

    Another bug: The brushes you create with CreateSolidBrush must be destroyed! Store the old HBRUSH you get from SelectObject, draw with the new brush, select the old HBRUSH back in and use DeleteObject with the created brush! Otherwise Windows gets out of brush handles pretty fast!

    Also, you should not store the HDC. Do it as you do now. HDCs are a rare resource (esp. on 9x systems), so get/create one and release/delete them once you're done with them.

    Share this post


    Link to post
    Share on other sites
    The problem is your program is using too many resources; everytime you get a WM_PAINT message, you're creating too many brushes in the for loop and never deleteing those brushes.


    xeddiex

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Endurion
    Also, you should not store the HDC. Do it as you do now. HDCs are a rare resource (esp. on 9x systems), so get/create one and release/delete them once you're done with them.


    Not really, the number of DCs are limited in per-thread basis (around 6 if I recall exactly - and in Win9x). The number of DCs allowed in the system are restricted by the amount of avalable memory only.

    You may need to CreateSolidObject () only once then store the old handle at the beginning of WM_PAINT, after drawing you select the original object then delete that solid object:
    case WM_PAINT:
    {
    HBRUSH const hOldBrush = SelectObject (hDC, CreateSolidObject (...)) ;

    //...Drawing code goes here

    DeleteObject (SelectObject (hDC, hOldBrush)) ;
    //or...
    //HBRUSH const hNewBrush = SelectObject (hDC, hOldBrush) ;
    //DeleteObject (hNewBrush) ;
    }

    Share this post


    Link to post
    Share on other sites
    Cheers !

    It worked like a charm. As mentioned above , all i did was remove the dynamically created brushes and replaced them with normal(initialized ,i.e. HBRUSH h = CreateSolidBrush(...)) and deleted them at the end of the paint message. I guess the program was messing up the resources.

    Thanks Guys!

    Share this post


    Link to post
    Share on other sites
    Sign in to follow this  

    • Advertisement
    ×

    Important Information

    By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

    We are the game development community.

    Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

    Sign me up!