Thread: Drawing problem, getting flickers

  1. #1
    Registered User
    Join Date
    Aug 2004
    Posts
    77

    Drawing problem, getting flickers

    All the program does, is create a plain window and draw a couple of rectangles in it. When the window is resized the rectangles are redrawn to match the size of the window, pretty simple.

    The trouble is when you resize the window with the contents showing. The 'Show Window contents while dragging' effect is turned on.

    When this happens, the window gets bombarded with redraw messages. In the attempt to draw the rectangles you get this flickering of the window's contents. You may need to compile and run the program to see this.

    Any ideas how I can get the contents to draw correctly under these conditions? I know its possible to disable the show contents setting for the program, but it seems to me that this shouldn't be necessary.

    Here is the code I'm working with:
    Code:
    #include <windows.h>
    
    LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    int WINAPI WinMain(HINSTANCE hiInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
    {
        WNDCLASS wcClass;
        HWND Handle;
        MSG msgMessage;
    
        char pcClassName[] = "MDLN-GUI";
    
        wcClass.hInstance = hiInst;
        wcClass.lpszClassName = pcClassName;
        wcClass.lpfnWndProc = WinProc;
        wcClass.style = CS_DBLCLKS;
        wcClass.hIcon = LoadIcon(0, "MW_ICON");
        wcClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wcClass.lpszMenuName = NULL;
        wcClass.cbClsExtra = 0;
        wcClass.cbWndExtra = 0;
        wcClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
    
        if (RegisterClass(&wcClass) == 0)
        {
            return;
        }
        
        Handle = CreateWindow("MDLN-GUI", "", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, NULL, NULL, hiInst, NULL);
    
        UpdateWindow(Handle);
        ShowWindow(Handle, SW_SHOW);
        
        while(GetMessage(&msgMessage, NULL, 0, 0) != 0)
        {
            TranslateMessage(&msgMessage);
            DispatchMessage(&msgMessage);
        }
        
        return 0;
    }
    
    LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
            //case (WM_MOVE) :
            case (WM_SIZE) :
            {
                InvalidateRect(hwnd, NULL, FALSE);
                break;
            }
            case (WM_PAINT) :
            {
                PAINTSTRUCT sPaint;
                RECT sRect;
                LOGBRUSH sBrush;
                HBRUSH hBrush;
    
                BeginPaint(hwnd, &sPaint);
                GetClientRect(hwnd, &sRect);
                
                sBrush.lbStyle = BS_SOLID;
                sBrush.lbColor = RGB(0, 255, 0);
                sBrush.lbHatch = 0;
                sRect.top += 25;
                sRect.left += 25;
                sRect.bottom -= 25;
                sRect.right -= 25;
                hBrush = CreateBrushIndirect(&sBrush);
                FillRect(sPaint.hdc, &sRect, hBrush);
                DeleteObject(hBrush);
                
                sBrush.lbStyle = BS_SOLID;
                sBrush.lbColor = RGB(0, 0, 255);
                sBrush.lbHatch = 0;
                sRect.top += 25;
                sRect.left += 25;
                sRect.bottom -= 25;
                sRect.right -= 25;
                hBrush = CreateBrushIndirect(&sBrush);
                FillRect(sPaint.hdc, &sRect, hBrush);
                DeleteObject(hBrush);
                
                EndPaint(hwnd, &sPaint);
                
                return 0;
            }
            case (WM_DESTROY) :
            {
                PostQuitMessage(0);
                break;
            }
            default :
            {
                return DefWindowProc(hwnd, uMsg, wParam, lParam);
            }
        }
    
        return 0;
    }
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

  2. #2
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    Interesting. Consider painting whatever you want to a bitmap, select it into a device context, and then bitblt it to the window's device context. Right now you're repainting everything.

    Kuphryn

  3. #3
    Registered User
    Join Date
    Aug 2004
    Posts
    77
    I haven't tried that, and I'll be honest I'm not entirely sure how. I've never painted to a bitmap, or did much with bitblt.

    As a test of that (using what I know and the model as I understand it) I changed the program so that it drew in a similar manner. Essentially with the bitblt you draw offscreen then paint it to the window all in one shot. For my test I did one draw, a single rectangle, and got the same flicker effect.

    My assumption at this point is the window just isn't able to handle the drawing load from all the repaints sent by the WM_SIZE messages. If you take the InvalidateRect() call out of that event it doesn't flicker, but the display is rarely correct. Is there a way to trim down the number of redraws, or have the redraws not erase teh window when a WM_PAINT message is recieved?

    [EDIT]
    I think I spoke to soon on that. If you block the WM_ERASEBKGND message from being processed, and then do a single draw as suggested it looks like things run smoothely. I'll have to play around a bit more with this.

    Any suggested reading for the drawing to bitmaps and bitblt() functions?
    [/EDIT]
    Last edited by Exile; 02-16-2005 at 12:54 PM.
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

  4. #4
    Registered User
    Join Date
    Aug 2004
    Posts
    77
    Success! Thanks kuphryn, that ended up working after all.

    I needed to add this to the switch in WinProc:
    Code:
    case (WM_ERASEBKGND) :
    {
    	break;
    }
    And the handling of the WM_PAINT message needed t obe changed to:
    Code:
    case (WM_PAINT) :
    {
    	PAINTSTRUCT sPaint;
    	RECT sRect;
    	LOGBRUSH sBrush;
    	HBRUSH hBrush;
    	HDC dcBitmap;
    	HBITMAP hBitmap;
    	int Height, Width;
    
    	BeginPaint(hwnd, &sPaint);
    	GetClientRect(hwnd, &sRect);
    	
    	Height = sRect.bottom - sRect.top;
    	Width = sRect.right - sRect.left;
    	
    	dcBitmap = CreateCompatibleDC(sPaint.hdc);
    	hBitmap = CreateCompatibleBitmap(sPaint.hdc, Width, Height);
    	SelectObject(dcBitmap, hBitmap);
    	
    	sBrush.lbStyle = BS_SOLID;
    	sBrush.lbColor = RGB(200, 200, 200);
    	sBrush.lbHatch = 0;
    	hBrush = CreateBrushIndirect(&sBrush);
    	FillRect(dcBitmap, &sRect, hBrush);
    	DeleteObject(hBrush);
    	
    	sBrush.lbStyle = BS_SOLID;
    	sBrush.lbColor = RGB(0, 255, 0);
    	sBrush.lbHatch = 0;
    	sRect.top += 25;
    	sRect.left += 25;
    	sRect.bottom -= 25;
    	sRect.right -= 25;
    	hBrush = CreateBrushIndirect(&sBrush);
    	FillRect(dcBitmap, &sRect, hBrush);
    	DeleteObject(hBrush);
    	
    	sBrush.lbStyle = BS_SOLID;
    	sBrush.lbColor = RGB(0, 0, 255);
    	sBrush.lbHatch = 0;
    	sRect.top += 25;
    	sRect.left += 25;
    	sRect.bottom -= 25;
    	sRect.right -= 25;
    	hBrush = CreateBrushIndirect(&sBrush);
    	FillRect(dcBitmap, &sRect, hBrush);
    	DeleteObject(hBrush);
    	
    	BitBlt(sPaint.hdc, 0, 0, Width, Height, dcBitmap, 0, 0, SRCCOPY);
    	
    	EndPaint(hwnd, &sPaint);
    	
    	DeleteDC(dcBitmap);
    	DeleteObject(hBitmap);
    	
    	return 0;
    }
    It now draws everythign correctly, and no flicker.
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  2. Replies: 5
    Last Post: 11-07-2005, 11:34 PM
  3. searching problem
    By DaMenge in forum C Programming
    Replies: 9
    Last Post: 09-12-2005, 01:04 AM
  4. half ADT (nested struct) problem...
    By CyC|OpS in forum C Programming
    Replies: 1
    Last Post: 10-26-2002, 08:37 AM