Thread: Invalidaterect

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    930

    InvalidateRect ()

    Im trying to draw a rectangle around an arrow with InvalidateRect(hwnd, lpRect, FALSE)
    It compiles without error but it keeps flashing and it invalidates the whole client area not only
    the rectangle i want.
    I guess the problem must be that InvalidateRect(hwnd, lpRect, FALSE) takes a CONST RECT* for rectangle
    coordinates while the RECT structure is only of type RECT.
    So i must be doing something wrong.
    Thanks for any help.

    Code:
    
    #include<windows.h>
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
    {
    static TCHAR szAppName[] = TEXT ("Invalidaterect") ;
    HWND hwnd ;
    MSG msg ;
    WNDCLASS wndclass ;
    wndclass.style = CS_HREDRAW | CS_VREDRAW ;
    wndclass.lpfnWndProc = WndProc ;
    wndclass.cbClsExtra = 0 ;
    wndclass.cbWndExtra = 0 ;
    wndclass.hInstance = hInstance ;
    wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
    wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
    wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;
    wndclass.lpszMenuName = NULL ;
    wndclass.lpszClassName = szAppName ;
    if (!RegisterClass (&wndclass))
    {
     
    return 0 ;
    }
     
    hwnd = CreateWindow (szAppName, // window class name
    TEXT ("The Hello Program"), // window caption
    WS_OVERLAPPEDWINDOW, // window style
    CW_USEDEFAULT, // initial x position
    CW_USEDEFAULT, // initial y position
    CW_USEDEFAULT, // initial x size
    CW_USEDEFAULT, // initial y size
    NULL, // parent window handle
    NULL, // window menu handle
    hInstance, // program instance handle
    NULL) ; // creation parameters
    
    ShowWindow (hwnd, iCmdShow) ;
    UpdateWindow (hwnd) ;
     
    while (GetMessage (&msg, NULL, 0, 0))
    {
    TranslateMessage (&msg) ;
    DispatchMessage (&msg) ;
    }
    return msg.wParam ;
    }
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    HDC hdc ;
    PAINTSTRUCT ps ;
    RECT rect ;
    HBRUSH hBrush, hOld ;
    POINT points [7] = {{20, 50},{180, 50},{180, 20},{230, 70},
    {180, 120},{180, 90},{20, 90}}; 
    int cpt = 7 ;
    CONST RECT* lpRect = 0 ;
    rect.left = 10;
    rect.top = 40;
    rect.right = 200;
    rect.bottom = 140;
    
    switch (message)
    { 
    case WM_PAINT: 
    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rect); 
    hBrush = CreateSolidBrush (RGB(20,170,20)) ;
    hOld = (HBRUSH) SelectObject (hdc,hBrush) ;
    InvalidateRect(hwnd, lpRect, FALSE) ;
    FillRect (hdc, &rect, hBrush) ;
     
    hBrush = CreateHatchBrush (HS_FDIAGONAL, RGB(200,170,20)) ;
    hOld = (HBRUSH) SelectObject (hdc,hBrush) ;
    Polygon(hdc, points, cpt); 
    SelectObject (hdc,hOld) ;
    DeleteObject (hBrush) ;
    EndPaint(hwnd, &ps);
    return 0 ;
     
    case WM_DESTROY:
    PostQuitMessage (0) ; 
    return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    Last edited by Ducky; 10-22-2008 at 09:49 AM.
    Using Windows 10 with Code Blocks and MingW.

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Here's a few ideas for you...

    Code:
    CONST RECT* lpRect = 0 ;
    rect.left = 10;
    rect.top = 40;
    rect.right = 200;
    rect.bottom = 140;
    in this section, you declare lpRect as 0(NULL), and set values for another rectangle called rect. Then, in the following section:
    Code:
    GetClientRect(hwnd, &rect); 
    hBrush = CreateSolidBrush (RGB(20,170,20)) ;
    hOld = (HBRUSH) SelectObject (hdc,hBrush) ;
    InvalidateRect(hwnd, lpRect, FALSE) ;
    you fill rect with values returned by GetClientRect(), making your previous efforts to fill it with values pointless, and then you send lpRect, which is still NULL to InvalidateRect(), which probably defaults to making the entire object referred to by hwnd invalid.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    How is it that you've worked out that
    Code:
    FillRect (hdc, &rect, hBrush);
    takes the address of a rect, but haven't realised the same for
    Code:
    InvalidateRect(hwnd, lpRect, FALSE);
    That second param should be &rect, just the same as the first. Both take a pointer to a rect a.k.a LPRECT.
    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"

  4. #4
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Is this what you're trying to do?

    Code:
    #include<windows.h>
    
    #define ID_TIMER  101
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT ("Invalidaterect") ;
        HWND hwnd ;
        MSG msg ;
        WNDCLASS wndclass ;
        wndclass.style = CS_HREDRAW | CS_VREDRAW ;
        wndclass.lpfnWndProc = WndProc ;
        wndclass.cbClsExtra = 0 ;
        wndclass.cbWndExtra = 0 ;
        wndclass.hInstance = hInstance ;
        wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
        wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
        wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;
        wndclass.lpszMenuName = NULL ;
        wndclass.lpszClassName = szAppName ;
        if (!RegisterClass (&wndclass))
        {
            return 0 ;
        }
        hwnd = CreateWindow (szAppName, // window class name
            TEXT ("The Hello Program"), // window caption
            WS_OVERLAPPEDWINDOW, // window style
            CW_USEDEFAULT, // initial x position
            CW_USEDEFAULT, // initial y position
            CW_USEDEFAULT, // initial x size
            CW_USEDEFAULT, // initial y size
            NULL, // parent window handle
            NULL, // window menu handle
            hInstance, // program instance handle
            NULL) ; // creation parameters
    
        ShowWindow (hwnd, iCmdShow) ;
        UpdateWindow (hwnd) ;
    
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg) ;
            DispatchMessage (&msg) ;
        }
        return msg.wParam ;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static BOOL bFlipFlop = FALSE ;
        HDC hdc ;
        PAINTSTRUCT ps ;
        RECT rect ;
        HBRUSH hBrush, brDiagonal;
        POINT points [7] = {{20, 50},{180, 50},{180, 20},{230, 70},
            {180, 120},{180, 90},{20, 90}}; 
    
    
        int cpt = 7 ;
        switch (message)
        { 
            case WM_CREATE:
                SetTimer (hwnd, ID_TIMER, 1000, NULL);
                break;
            case WM_TIMER :
                bFlipFlop = !bFlipFlop ;
                rect.left = 15;
                rect.top = 15;
                rect.right = 235;
                rect.bottom = 125;
                InvalidateRect (hwnd, &rect, FALSE) ;
                return 0 ;
            case WM_PAINT: 
                hdc = BeginPaint(hwnd, &ps);
                GetClientRect(hwnd, &rect); 
                hBrush = CreateSolidBrush (bFlipFlop ? RGB(255,0,0) :
                    RGB(0,0,255)) ;
                FillRect (hdc, &rect, hBrush) ;
                Polygon(hdc, points, cpt); 
                brDiagonal  = CreateHatchBrush (bFlipFlop ? HS_FDIAGONAL :
                    HS_BDIAGONAL, bFlipFlop ? RGB(0,0,255) :RGB(255,0,0)) ;
                SelectObject(hdc, brDiagonal);
                Polygon(hdc, points, cpt); 
                DeleteObject(brDiagonal);
                DeleteObject (hBrush) ;
                EndPaint(hwnd, &ps);
                return 0 ;
            case WM_DESTROY:
                KillTimer (hwnd, ID_TIMER) ;
                PostQuitMessage (0) ; 
                return 0 ;
        }
        return DefWindowProc (hwnd, message, wParam, lParam) ;
    }

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thank you Elkvis, Malc and Bob for the explanation, i modified the code according it.

    Quote Originally Posted by BobS0327 View Post
    Is this what you're trying to do?
    Yes, thanks a lot Bob, this is it.
    And this is how i imagined it.
    It executes as intended but then it starts flickering.
    I think the problem is that i cant dereference lpRect like *lpRect, in InvalidateRect(hwnd, *lpRect, FALSE).
    When i do it wont compile.
    I mean that i should dereference it to get the value instead of the address. Right?
    So i dont understand.

    But now i study your version of dereferencing.
    I dont get it entirely yet.
    Code:
    #include <windows.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         static TCHAR szAppName[] = TEXT ("Invalidaterect") ;
         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;
    
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = 0 ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;
    
         if (!RegisterClass (&wndclass))
         {
              
              return 0 ;
         }
         
         hwnd = CreateWindow (szAppName,                  // window class name
                              TEXT ("The Hello Program"), // window caption
                              WS_OVERLAPPEDWINDOW,        // window style
                              CW_USEDEFAULT,              // initial x position
                              CW_USEDEFAULT,              // initial y position
                              CW_USEDEFAULT,              // initial x size
                              CW_USEDEFAULT,              // initial y size
                              NULL,                       // parent window handle
                              NULL,                       // window menu handle
                              hInstance,                  // program instance handle
                              NULL) ;                     // creation parameters
         
         ShowWindow (hwnd, iCmdShow) ;
         UpdateWindow (hwnd) ;
         
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
         return msg.wParam ;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
          HDC         hdc ;
          PAINTSTRUCT ps ;
          RECT        rect ;
          CONST RECT* lpRect ;
          HBRUSH      hBrush, hOld ;
          POINT points [7] = {{20, 60},{180, 60},{180, 30},{230, 80},
                                         {180, 130},{180, 100},{20, 100}}; 
          int cpt = 7 ;
         
          rect.left   =  10 ;
          rect.top    =  10 ;
          rect.right  = 250 ;
          rect.bottom = 160 ;
          lpRect = &rect ;
    
          switch (message)
          {
          case WM_PAINT:
               hdc = BeginPaint(hwnd, &ps) ;
               hBrush = CreateSolidBrush (RGB(20,10,200)) ;
               hOld   = (HBRUSH) SelectObject (hdc,hBrush) ;
               InvalidateRect(hwnd, lpRect, FALSE) ;
               FillRect (hdc, lpRect, hBrush) ;
               
               hBrush = CreateHatchBrush (HS_FDIAGONAL, RGB(200,170,20)) ;
               hOld   = (HBRUSH) SelectObject (hdc,hBrush) ;
               Polygon(hdc, points, cpt); 
               SelectObject (hdc,hOld) ;
               DeleteObject (hBrush) ;
               EndPaint(hwnd, &ps);
               return 0 ;
    
          case WM_DESTROY:
                 PostQuitMessage (0) ;              
                 return 0 ;
          }
          return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    Last edited by Ducky; 10-24-2008 at 06:48 AM.
    Using Windows 10 with Code Blocks and MingW.

  6. #6
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    The reason it is flickering is because you're calling InvalidateRect while you're processing the WM_PAINT message. Calling this function forces another WM_PAINT message to be sent to the window. Finish processing one WM_PAINT message and you've got another WM_PAINT message waiting to be processed. For lack of a better description, you're stuck in a WM_PAINT message loop.

    If you try to add more functionality to this app such as adding a menu which displays a dialog box, You'll notice, that at the VERY best, the app runs very jerkily.


    Code:
    case WM_PAINT:
               hdc = BeginPaint(hwnd, &ps) ;
               hBrush = CreateSolidBrush (RGB(20,10,200)) ;
               hOld   = (HBRUSH) SelectObject (hdc,hBrush) ;
               InvalidateRect(hwnd, lpRect, FALSE) ;           
              FillRect (hdc, lpRect, hBrush) ;
               
               hBrush = CreateHatchBrush (HS_FDIAGONAL, RGB(200,170,20)) ;
               hOld   = (HBRUSH) SelectObject (hdc,hBrush) ;
               Polygon(hdc, points, cpt); 
               SelectObject (hdc,hOld) ;
               DeleteObject (hBrush) ;
               EndPaint(hwnd, &ps);
               return 0 ;

  7. #7
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Of course, InvalidateRect calls WM_PAINT! Plus i knew that before. Just forgot about it.
    Thanks for refreshing my memory.

    One more thing that i dont understand is when you call GetClientRect you change the values of rect to the values of the clientarea.
    So how come that FillRect fills up the little rectangle then?
    And if i dont call GetClientRect, it wont even draw the little rectangle. Its confusing.

    Code:
     case WM_PAINT: 
                hdc = BeginPaint(hwnd, &ps);
                GetClientRect(hwnd, &rect);            
                hBrush = CreateSolidBrush (bFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
                FillRect (hdc, &rect, hBrush) ;
                Polygon(hdc, points, cpt); 
                brDiagonal  = CreateHatchBrush (bFlipFlop ? HS_FDIAGONAL :
                    HS_BDIAGONAL, bFlipFlop ? RGB(0,0,255) :RGB(255,0,0)) ;
                SelectObject(hdc, brDiagonal);
                Polygon(hdc, points, cpt); 
                DeleteObject(brDiagonal);
                DeleteObject (hBrush) ;
                EndPaint(hwnd, &ps);
                return 0 ;
    Last edited by Ducky; 10-25-2008 at 03:24 PM.
    Using Windows 10 with Code Blocks and MingW.

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Many Windows API functions take a pointer to a RECT. In some cases they do this because the RECT is effectively an out parameter. In other places it is passed by pointer because that is more efficient. In all cases though, you must simply define a RECT, and pass the address of it. You never declare an LPRECT for any of them.

    Before calling GetClientRect, your rect probably has coordinates of all zeros, so if you try and do a FillRect with that, you'll get nothing.
    After calling it, you'll have the rect coordinates set to that of the window, and you can then pass those coords to FillRect and it will paint the window for you.

    In other words, treat InvalidateRect just like FillRect.
    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. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thank you iMalc! Duly noted.
    Using Windows 10 with Code Blocks and MingW.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    A better tip for you:
    The documentation says what arguments it expects and if it's information IN or OUT.
    The windows headers also uses these evil pointer typedefs, which might make it somewhat unclear that it is indeed pointers to something it expects, and not some alien type.
    Everything that begins with "LP" means basically, it's a pointer of the preceding type.
    So LPRECT basically means RECT*.
    Some functions also take CONST SOMETHING. CONST is just another upper-case define/typedef for the keyword const which tells the compiler the argument passed to the function will not, shall not, be modified or changed.

    To get the address of something, you prefix &. Prefix & to T and you get T*.
    Prefix * to dereference a pointer. Prefix * to T* and you get T.
    It is important to know this. The functions expect the address of a struct to access its information. You can't just define a pointer and dereference it. What do you think that will accomplish or do?

    And in the future, indent your code properly before posting it.
    Last edited by Elysia; 10-26-2008 at 02:02 PM.
    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.

  11. #11
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    The functions expect the address of a struct to access its information.
    Thank you Elysia. That makes it clear to understand.
    Using Windows 10 with Code Blocks and MingW.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 12
    Last Post: 05-28-2008, 04:10 AM
  2. Is InvalidateRect the correct API?
    By Joelito in forum Windows Programming
    Replies: 6
    Last Post: 05-15-2007, 07:44 AM
  3. using InvalidateRect()
    By agerealm in forum Windows Programming
    Replies: 6
    Last Post: 04-17-2003, 07:43 AM
  4. New to Windows & C++ - InvalidateRect Problem
    By Guardian in forum Windows Programming
    Replies: 1
    Last Post: 04-23-2002, 11:26 PM
  5. ValidateRect() and InvalidateRect()
    By Garfield in forum Windows Programming
    Replies: 6
    Last Post: 11-01-2001, 12:04 PM