Thread: SetTimer().. WM_TIMER window flickers

  1. #46
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    If you want to fix the flickering by using double-buffering, then you can try just using the WS_EX_COMPOSITED flag during window creation.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  2. #47
    Registered User
    Join Date
    Dec 2006
    Location
    Scranton, Pa
    Posts
    252
    Actually i need to redraw a portion of the window. I have five rectangles (4 have edit boxes, 1 has results table) in one window. Really i only need to update the results (the Fifth rectangle) every time thew user changes the values on the other 4 rectangles... Any suggestions on how to do this?
    Err, couldn't you simply use a static for your results table (use ss_simple | ss_noprefix)? I haven't read the entire topic, but it seems that the present design is bloated for no reason. With the static, there's no need to invalidate/update the cntl.

  3. #48
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by Oldman47 View Post
    Err, couldn't you simply use a static for your results table (use ss_simple | ss_noprefix)? I haven't read the entire topic, but it seems that the present design is bloated for no reason. With the static, there's no need to invalidate/update the cntl.
    I just read more about static controls, they more useful if only want to display something on them but no input... My code flickers as soon a i use the timer or InvalidateRect() to update window regardless whether i display something on the screen or draw a rectangle or insert edit controls... Just for a test, i drew one rectangle on client's window with four edit controls... That alone was enough to cause flickers... I don't know if static control can allow you to add other controls unto it (buttons/edit/etc...) if you treat them as rectangle areas...

  4. #49
    Registered User
    Join Date
    Dec 2006
    Location
    Scranton, Pa
    Posts
    252
    Probably not what you're looking for then. A static is an easy way to display/update text and/or some numerical value (ie. sendmessage or setdlgitemtext), though it can't accept keyboard input directly.

  5. #50
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Decided to write a much smaller program to test my double buffering experience learnt in the past few days to test whether or not am doing things wrong. To my amusement i managed to write a code which works 100% using off-screen DC (double buffering). The program rotates a line in a circle at a high speed... So this uses the timer & InvalidateRect. This program was flickering like the other without using double buffering....

    Code:
    // Rotate.c :
    //
    
    #include <windows.h>
    #include <math.h>
    
    #pragma hdrstop
    
    #define IDT_ROTATER 101
    
    //---------------------------------------------------------------------------
    const char *ClsName = "RADAR_01";
    const char *WndName = "Rotate Line";
    
    POINT SetPOINT(LONG radius);
    long ErrorHandler(char errorMessage[]);
    void Win32APIGDICircle (HDC hdc, LONG radius, int R, int G, int B);
    HDC MemoryDCForArea (HDC hdc, int iAreaWidth, int iAreaHeight, int iCommandWhatToDo );
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,WPARAM wParam, LPARAM lParam);
    
    // Globals
    int	angle=0;
    HICON		hIcon1;		
    POINT		ptOld;       
    UINT_PTR	uResult;    
    POINT		coord, ptCenter = {450,300};
    
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
    	MSG        Msg;
    	HWND       hWnd;
    	WNDCLASSEX WndClsEx;
    
    	// Create the application window
    	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
    	WndClsEx.lpfnWndProc   = WndProcedure;
    	WndClsEx.cbClsExtra    = 0;
    	WndClsEx.cbWndExtra    = 0;
    	WndClsEx.hIcon		   = LoadIcon(hInstance, MAKEINTRESOURCE(400)); 
    	WndClsEx.hCursor	   = LoadCursor(hInstance, MAKEINTRESOURCE(200)); 
    	WndClsEx.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
    	WndClsEx.lpszMenuName  = NULL;
    	WndClsEx.lpszClassName = ClsName;
    	WndClsEx.hInstance     = hInstance;
    	WndClsEx.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
    	// Register the application
    	RegisterClassEx(&WndClsEx);
    
    	// Create the window object
    	hWnd = CreateWindowEx(0,
    		ClsName,
    		WndName,
    		WS_OVERLAPPEDWINDOW,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		NULL,
    		NULL,
    		hInstance,
    		NULL);
    
    
    	if( !hWnd ) 
    		return FALSE; 
    
    	// Display the window to the user
    	ShowWindow(hWnd, nCmdShow);
    	UpdateWindow(hWnd);
    
    	while( GetMessage(&Msg, NULL, 0, 0) )
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    
    	return (int) Msg.wParam;
    }
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
    							  WPARAM wParam, LPARAM lParam)
    {
    	PAINTSTRUCT		ps;
    	HPEN			pen, oldPen;
    	HDC				hdc;
    	HDC				MemDC;
    	HBRUSH			hbrBkGnd;
    	HBITMAP			hBitmap, hOldBitmap;
    	RECT			rec;
    	long			radius=150;
    
    	double	xLimit = sqrt ((double) (radius * radius) / 2);
    
    	// Handle messagse
    	switch(Msg)
    	{
    	case WM_CREATE:
    
    		// Set the timer 
    		uResult = SetTimer(hWnd, IDT_ROTATER, (UINT) 0.015,(TIMERPROC) NULL); 
    
    		break;
    
    	case WM_PAINT:
    		{		
    			hdc = BeginPaint(hWnd, &ps);
    
    			/* Retrieve the client's area width and height */
    			GetClientRect(hWnd, &rec);
    
    			MemDC = CreateCompatibleDC (hdc);
    
    			hBitmap = CreateCompatibleBitmap (
    				hdc, rec.right-rec.left, rec.bottom-rec.top
    				);
    
    			hOldBitmap = SelectObject (MemDC, hBitmap);
    
    			// Force background color to grey 
    			hbrBkGnd = CreateSolidBrush( RGB(0xD3, 0xD3, 0xD3) );
    			FillRect(MemDC, &rec, hbrBkGnd);
    			DeleteObject(hbrBkGnd);
    
    			// Draw a circle
    			Win32APIGDICircle (MemDC, radius, 0, 255, 128);
    
    			// Create pen
    			pen = CreatePen(PS_SOLID, 2, RGB(128, 255, 128));	
    			oldPen = (HPEN)SelectObject(MemDC, pen);		
    
    			// Draw line
    			SetPOINT(radius);
    			MoveToEx(MemDC, ptCenter.x,ptCenter.y, NULL);		
    			LineTo(MemDC, coord.x, coord.y);
    			
    			// Delete Pen
    			SelectObject(MemDC, oldPen);
    			DeleteObject(pen);
    
    			/* Render circle to screen from memory DC */
    			BitBlt(hdc,0,0,rec.right,rec.bottom,MemDC,0,0,SRCCOPY);
    
    			// Delete & Release DCs
    			SelectObject(MemDC, hOldBitmap);
    			DeleteObject(hBitmap);
    			DeleteDC(MemDC);
    
    			EndPaint(hWnd, &ps);
    		}
    		break; 
    
    	case WM_TIMER: 
    		angle-=2;
    		InvalidateRect (hWnd, NULL, TRUE);
    		UpdateWindow(hWnd);
    
    		break;
    
    	case WM_DESTROY:
    		
    		KillTimer(hWnd, IDT_ROTATER); 
    		PostQuitMessage(WM_QUIT);
    		break;
    
    	case WM_ERASEBKGND:
    		{
    			return (LRESULT)1;
    		}
    
    	default:
    		// Process the left-over messages
    		return DefWindowProc(hWnd, Msg, wParam, lParam);
    	}
    	// If something was not done, let it go
    	return 0;
    }
    
    // Win32API GDI circle:
    void Win32APIGDICircle (HDC hdc, LONG radius,int R, int G, int B)
    {
    	HBRUSH hBrush = CreateSolidBrush (RGB (R,G,B));
    	HGDIOBJ hOldBrush = SelectObject (hdc, hBrush);
    
    	Ellipse (hdc, 
    		ptCenter.x - radius, 
    		ptCenter.y + radius,
    		ptCenter.x + radius,
    		ptCenter.y - radius);
    
    	SelectObject (hdc, hOldBrush);
    	DeleteObject (hBrush);
    }
    
    /* Calculate the line points */
    POINT SetPOINT(LONG radius)
    {
    	const double Deg2Rad = 0.017453292;
    	double degInRad;
    
    	degInRad = angle*Deg2Rad;   // Convert degrees to radians
    
    	// Finds the adjacent value
    	coord.x = (long)(ptCenter.x + (cos(degInRad)*radius));	
    
    	// Finds the hypotenuse value
    	coord.y = (long)(ptCenter.y - (sin(degInRad)*radius));	
    
    	return coord;
    }
    This is how the rendering on memory DC is done and it works 100% (no flickering at all)

    Now, i have tried to update my other project following the same steps... Still in vain, i think this may have to do with how i have used my variables (global vs local or memory related issues) which causes the flickering on edit controls as well (which is strange cause they not part of repaint)
    Last edited by csonx_p; 06-03-2008 at 08:18 AM.

  6. #51
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by csonx_p View Post
    Now, i have tried to update my other project following the same steps... Still in vain, i think this may have to do with how i have used my variables (global vs local or memory related issues) which causes the flickering on edit controls as well (which is strange cause they not part of repaint)
    I'm going to assume you didn't read the link I posted about the WS_EX_COMPOSITED flag. Seriously, it will do the double-buffering for you!
    That one tiny little change and then it'll be smooth, like magic - piece of cake!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #52
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by iMalc View Post
    If you want to fix the flickering by using double-buffering, then you can try just using the WS_EX_COMPOSITED flag during window creation.
    Code:
    : error C2065: 'WS_EX_COMPOSITED' : undeclared identifier

  8. #53
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by csonx_p View Post
    Code:
    : error C2065: 'WS_EX_COMPOSITED' : undeclared identifier
    Wow, you give up easily. Here's it's definition in the winuser.h header file:
    Code:
    #if(_WIN32_WINNT >= 0x0501)
    #define WS_EX_COMPOSITED        0x02000000L
    #endif /* _WIN32_WINNT >= 0x0501 */
    So all you have to do is define _WIN32_WINNT as 0x0501 or greater. All this means is that WS_EX_COMPOSITED only works on XP and later.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #54
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by iMalc View Post
    Wow, you give up easily. Here's it's definition in the winuser.h header file:
    Code:
    #if(_WIN32_WINNT >= 0x0501)
    #define WS_EX_COMPOSITED        0x02000000L
    #endif /* _WIN32_WINNT >= 0x0501 */
    So all you have to do is define _WIN32_WINNT as 0x0501 or greater. All this means is that WS_EX_COMPOSITED only works on XP and later.
    exactly what i did, i copied these three lines from WinUser.h but got same error... Isn't it interesting that other constants such as "WS_EX_OVERLAPPEDWINDOW" compile with no errors, which also happen to be in the same header file? I use XP.

  10. #55
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by iMalc View Post
    If you want to fix the flickering by using double-buffering, then you can try just using the WS_EX_COMPOSITED flag during window creation.
    Wow! Impressive iMalc.... I added this line
    Code:
     #define WS_EX_COMPOSITED        0x02000000L
    without the
    Code:
     #if(_WIN32_WINNT >= 0x0501) .... #endif
    , the code compiled and guess what! There was no more flickering...

    Thanks for insisting...

  11. #56
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Try defining
    NTDDI_VERSION = NTDDI_WINXP
    Or
    _WIN32_WINNT = 0x0501
    WINVER = 0x0501

    Hopefully that should make it compile for XP+ only, without the need to copy the macros out of the header.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #57
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by Elysia View Post
    Try defining
    NTDDI_VERSION = NTDDI_WINXP
    Or
    _WIN32_WINNT = 0x0501
    WINVER = 0x0501

    Hopefully that should make it compile for XP+ only, without the need to copy the macros out of the header.
    Can i just copy these lines _WIN32_WINNT = 0x0501
    WINVER = 0x0501 as they are, what you mean by defining... (do i need #define)

  13. #58
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You need #define, since they are defines.
    Like
    #define NTDDI_VERSION NTDDI_WINXP
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

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. Linking OpenGL in Dev-C++
    By linkofazeroth in forum Game Programming
    Replies: 4
    Last Post: 09-13-2005, 10:17 AM
  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