Thread: ValidateRect() and InvalidateRect()

  1. #1
    the Corvetter
    Join Date
    Sep 2001
    Posts
    1,584

    ValidateRect() and InvalidateRect()

    I was just reading about the WM_PAINT message and it was talking about the ways to go about getting, making, setting the invalid rectangle of the client area. By what it was explaining, I got this out of the first explanation (given hdc is defined as HDC):
    Code:
    case WM_PAINT:
    {
        hdc = BeginPaint(hwnd, &rect);
        [GDI functions here]
        EndPaint(hwnd, &rect);
    
        return 0;
    }
    And then the book was trying to introduce other functions like InvalidateRect() and ValidateRect(). My book said InvalidateRect() would invalidate the whole client area to redraw the whole area. Would this function be used like this:
    Code:
    case WM_PAINT:
    {
        InvalidateRect(hwnd, NULL);
    
        hdc = BeginPaint(hwnd, &rect);
        [GDI functions here ]
        EndPaint(hwnd, &rect);
    
        return 0;
    }
    Then (this is where I got confused a little) it introduced the ValidateRect() function. Would this function be used like this:
    Code:
    case WM_PAINT:
    {
        GetDC(hwnd, NULL);
        ValidateRect(hwnd, NULL);
        ReleaseDC(hwnd, hdc);
    
        return 0;
    }
    I'm now second guessing the parameters to some of these functions, but is this the general use of them? Please correct me if I'm wrong. Thanks.

    --Garfield
    1978 Silver Anniversary Corvette

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    I don't use ValidateRect().
    I use InvalidateRect() to cause a WM_PAINT to be sent to the callback of the Dlg I want redrawn.

    As InvalidateRect() and UpdateWindow() cause paint msg's I would not put them inside the paint function. (Cause an infinte loop)
    InvalidateRect() has THREE param's, the HWND of the dlg to be redrawn(to get the right callback), the RECT area to be redrawn and a BOOL flag to tell if the background needs erasing. As I tend to do my own HDC erase I set this to FALSE.
    If you have two or more controls with HDC's on a dlg then you can cause only one to be redrawn by invaldating only it's client rect.
    I use two HDC's, a frame that is drawn on by all my GDI functions and a buffer, onto which is copied the frame after I have finished drawing. The buffer is sent to the paint by a call to InvaidateRect() or UpdateWindow(). This means a thread can be doing a slow stretchblt() to the frame as the previous buffer is being shown on screen giving a smooth screen update.

    ValidateRect() can be used to stop paint on a certain area. if it gets a paint msg then you can stop it being redrawn.

    In the Paint function you will need something like
    Code:
    GetUpdateRect(hWnd, &theRect, 0);
    if (IsRectEmpty(&theRect))
    {
         GetClientRect(hWnd,&theRect);
    }
    BeginPaint(.......
    "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

  3. #3
    the Corvetter
    Join Date
    Sep 2001
    Posts
    1,584
    So, let me get this straight:

    Before you call BeginPaint(hwnd, &ps) (ps being PAINTSTRUCT) you:

    -call InvalidateRect(hwnd, NULL, FALSE)

    Okay, so the false flag says that you don't want to erase the backround because that could screw-up the controls by causing them not to be redrawn. Am I getting this right?

    Thanks.

    --Garfield
    1978 Silver Anniversary Corvette

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Not quite.

    The call to InvalidateRect() or UpdateWindow() CAUSES the paint to be called, so you don't have to.(Windows sends your callback a WM_PAINT msg for the RECT in InvalidateRect() ).

    Without the InvalidateRect() you could draw all the stuff to the screen you wanted but it would not be shown until the paint has been called. Only then is the screen updated.

    You never call beginpaint() except in response to an internal WM_PAINT msg.

    The FALSE flag you have got. Some handling of the WM_ERASEBKGND msg's will stop the flicker.
    "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

  5. #5
    the Corvetter
    Join Date
    Sep 2001
    Posts
    1,584
    Okay, I think I understand. So, really all InvalidateRect (and UpdateWindow) does is just cause the call of the WndProc with the WM_PAINT. Until then, it won't paint to the screen until WM_PAINT is called. Now do I have it? Thanks.

    --Garfield
    1978 Silver Anniversary Corvette

  6. #6
    of Zen Hall zen's Avatar
    Join Date
    Aug 2001
    Posts
    1,007
    Yes, more or less. InvalidateRect() will send a message and UpdateWindow() calls the WndProc() directly. BeginPaint() sets up the painting info (the clipping area etc) and EndPaint() validates to stop continual messages being sent.
    zen

  7. #7
    the Corvetter
    Join Date
    Sep 2001
    Posts
    1,584
    So, you just use BeginPaint and EndPaint in the WM_PAINT and to set HDC's elsewhere you would use SetDC and ReleaseDC, right?

    I guess I understand those functions now. Thanks.

    --Garfield
    1978 Silver Anniversary Corvette

Popular pages Recent additions subscribe to a feed