Jump to content
  • Advertisement
Sign in to follow this  
szecs

win32 not to redraw while resize (openGL)+custom window skin+others

This topic is 3016 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 all! The question is the opposite as usual: why is the window redrawing constantly when resized/moved? I know this is the behavior most of us want, but I don't (for performance reasons). And a related question: I'm not sure that my redrawing (WM_PAINT) stuff is good at all. The program should redraw, only if I want it to. (So no constant updates) The old version worked as expected: it didn't redraw, while the left button were pressed during resize/move. The updates woks as expected otherwise. Old message loop:
while( !EscapeGame )
{	
	if( PeekMessage(&msg,NULL,0,0,PM_REMOVE) )
	{
						
		if( msg.message==WM_QUIT )
			EscapeGame = true;

		else
		{	TranslateMessage(&msg);
				DispatchMessage(&msg);
		}
		continue;
	}
		
	Display();//if I comment this out, and use WM_PAINT/UpdateWindow in windProc, the problem is the same
	WaitMessage();
}





New message loop:
while( GetMessage( &msg, NULL, 0, 0 ) )
    { 
        if (msg.message==WM_QUIT)
        {
            break;
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }





WindProc:
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_ACTIVATE:
		if( !GameOver && GameStarted )
		{	int minimized = HIWORD(wParam);

			if ( minimized && win_state.Active )
			{		
				PauseTimeStart = timeGetTime();
				win_state.Active = false;
			}
			else if( !minimized && !win_state.Active )
			{	
				TimeStart += (timeGetTime() - PauseTimeStart);
				TimerFunc();
				
				win_state.Active = true;
			}
		}

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_CLOSE:
		
		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_GETMINMAXINFO:
		{
			PMINMAXINFO minmax;

			minmax = (PMINMAXINFO)lParam;

			minmax->ptMinTrackSize.x = 400;
			minmax->ptMinTrackSize.y = 300;

		}
		//InvalidateRect(win_state.hWnd, NULL, FALSE);
		//UpdateWindow(win_state.hWnd);
		return 0;

	case WM_TIMER:

		//the old version didn't redraw, even when the timer expired
		// timer values are about 0.5 seconds (quite slow)

		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_SIZE:
		if( wParam != SIZE_MINIMIZED )
		{
			SCRN_WDTH = LOWORD(lParam);
			SCRN_HGHT = HIWORD(lParam)-MENUBAR_HEIGHT;
			ResizeWindow(SCRN_WDTH, SCRN_HGHT);

			//InvalidateRect(win_state.hWnd, NULL, FALSE);
			//UpdateWindow(win_state.hWnd);//redraws, even when commented
		}
		return 0;

	case WM_LBUTTONDOWN:
		Lft_Btn = true;
		SetCapture(win_state.hWnd);

		if( Rgt_Btn )
			Lft_Rgt_Dwn = true;

		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);
		return 0;

	case WM_MBUTTONDOWN:
		Mdl_Btn = true;
		SetCapture(win_state.hWnd);

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);
		return 0;

	case WM_RBUTTONDOWN:
		Rgt_Btn = true;
		if( Lft_Btn )
			Lft_Rgt_Dwn = true;
		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_LBUTTONUP:
		Lft_Btn = false;
		if( !Mdl_Btn )
			ReleaseCapture();
		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_MBUTTONUP:	
		Mdl_Btn = false;
		if( !Lft_Btn )
			ReleaseCapture();

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_RBUTTONUP:
		Rgt_Btn = false;
		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_MOUSEMOVE:
		MouseX = (int)(short)LOWORD(lParam); 
		MouseY = (int)(short)HIWORD(lParam);

		MouseDX = MouseX - MousePrevX;
		MouseDY = MouseY - MousePrevY;

		MousePrevX = MouseX;
		MousePrevY = MouseY;

		...
		
		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_MOUSE_ROLL:	
		CurrentChar = wParam;

		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_CHAR:
		CurrentChar = wParam;
		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_KEYDOWN:
		CurrentChar = wParam;
		...

		InvalidateRect(win_state.hWnd, NULL, FALSE);
		UpdateWindow(win_state.hWnd);

		return 0;

	case WM_PAINT: // WM_PAINT, and UpdateWindow is only used with the new version of the message loop

		Display();
		ValidateRect(win_state.hWnd, NULL);

		return 0;
	}

	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}





Note, that this means the window is updated on almost every events, but I will make it to redraw only when I want it to. Or is it something with the validate/invalidate pairs? How can I get back to the "default" redraw behavior? Thanks for answers in advance! [Edited by - szecs on March 16, 2010 5:15:25 AM]

Share this post


Link to post
Share on other sites
Advertisement
An other question:
Is there a way to define custom skin for a window (titlebar +borders +minimize/close buttons)?

Or I have to make a window with no title bar, and draw the stuff myself + reimplement all the functions? (that's okay, but I don't want to jump into it, if there's a much simpler solution)

Share this post


Link to post
Share on other sites
Quote:
Original post by szecs
Is there a way to define custom skin for a window (titlebar +borders +minimize/close buttons)?

Or I have to make a window with no title bar, and draw the stuff myself + reimplement all the functions? (that's okay, but I don't want to jump into it, if there's a much simpler solution)


The only way I know to do it is to do it all yourself. Create your window barebones with the WS_POPUP style, paint the whole thing, even the stuff that constitutes the "non-client area", in WM_PAINT, and handle WM_NCHITTEST appropriately. WM_NCHITTEST is what tells Windows that the user is, for example, dragging the title bar; it's the key to whole thing.

Share this post


Link to post
Share on other sites
Quote:

And a related question: I'm not sure that my redrawing (WM_PAINT) stuff is good at all.


I'd need to see what the Display() function in your WM_PAINT handler is doing. I'm not following the code: don't understand how Display() is not getting the window's HWND, because aren't you going to have to call BeginPaint() with a window handle?

Share this post


Link to post
Share on other sites
hi there

1. Why don't you just leave windows OnPint() empty since you are using a timer?
like this :

LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL &)
{
CPaintDC dc();
return 0;
}




2. When you resize to shrink a WIN32 window, the system very likely wont issue a WM_PAINT message, since your DC is larger than current window size, so no re-paint is needed (the larger part will be clipped anyway)

3. Same as above, when you MOVE a window you should not received WM_PAINT either, since the window DC size is not changed. (Drag while showing content?)

4. InvalidateRect() is just enough and i dont think update window is necessary

5. custom window skin : google 'Layered Window' may help

just my two cents anyway.

Share this post


Link to post
Share on other sites
Oh, sorry, completely forgot to mention: I use openGL for drawing. So it has its device context set up at initialization.

Thanks for your tip about WM_NCHITTEST, it seems a bit hard (MSDN doesn't explain the use of it in detail), but I have a GUI anyway, so I can implement the stuff there. It's just i don't want to update the window when WM_SIZE, because the rendering is quite slow. It's okay in the program, but can be annoying, when even moving/resizing the window is choppy.

Share this post


Link to post
Share on other sites
Quote:
Original post by Pet123
hi there

1. Why don't you just leave windows OnPint() empty since you are using a timer?
like this :
*** Source Snippet Removed ***

2. When you resize to shrink a WIN32 window, the system very likely wont issue a WM_PAINT message, since your DC is larger than current window size, so no re-paint is needed (the larger part will be clipped anyway)

3. Same as above, when you MOVE a window you should not received WM_PAINT either, since the window DC size is not changed. (Drag while showing content?)

4. InvalidateRect() is just enough and i dont think update window is necessary

just my two cents anyway.
That's the problem, I don't want to update the window when moving/resizing (I don't call update in WM_SIZE), but it updates regardless of it.
Yes, InvalidateRect is enough, but the problem is the same.

Share this post


Link to post
Share on other sites
An other question: for some reason MSDN isn't clear for me about this one:
Does SetTimer issue WM_TIMER messages repeatedly, or just issues one message?
My guess is that it issues messages repeatedly, but I'm not sure, maybe there's a bug somewhere in my code.

Sorry, I don't want separate threads for these small questions.

EDIT: yup, repeatedly. I should have tried before asking...

[Edited by - szecs on March 16, 2010 5:18:51 AM]

Share this post


Link to post
Share on other sites
The original question is still a mystery for me. I mean how can the window be updated, when I don't call update/invalidaterect in the WM_SIZE handler?

The Layered Window stuff will be needed, so thanks for that.

Share this post


Link to post
Share on other sites
Quote:
Original post by szecs
The original question is still a mystery for me. I mean how can the window be updated, when I don't call update/invalidaterect in the WM_SIZE handler?


Off the top of my head, I don't know. Are you concerned about the time that the redraws take or is is that they are creating a flicker? Because if it's a flicker you want to get rid of, you could double-buffer in your WM_PAINT.

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!