invalidate rectangle

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rushiraj
    New Member
    • Jul 2006
    • 1

    invalidate rectangle

    hi,

    In my Doc/view appication I want to user invalidate rectangle value in ondraw()
    function.


    can any one help me.

    Thanks in advance.

    Regards
    Rushiraj.
  • AdrianH
    Recognized Expert Top Contributor
    • Feb 2007
    • 1251

    #2
    Originally posted by rushiraj
    hi,

    In my Doc/view appication I want to user invalidate rectangle value in ondraw()
    function.


    can any one help me.

    Thanks in advance.

    Regards
    Rushiraj.
    Hi, I'm not positive, but I don't think you can or should invalidate in the OnDraw() function as this is the function that is called when a portion of the screen is invalidated which would cause infinite recursion, resulting in blowing your stack.

    Try doing it from somewhere else that is not called by OnDraw().


    Adrian

    Comment

    • Banfa
      Recognized Expert Expert
      • Feb 2006
      • 9067

      #3
      Hi as I read it you do not want to call InvalidateRect in OnDraw but you want access to the rectangle that InvalidateRect was called with.

      If this is the case then it is possible, but first you need to understand how the underlying windows messages work a bit (MFC is just a wrapper for the standard way windows works).

      When a WM_PAINT message is received you have to call BeginPaint which returns you an HDC (handle to a device context) and populates a PAINTSTRUCTURE object. Then you have to call EndPaint when you have finished. The PAINTSTRUCTURE contains a member rcPaint which is the region of the screen that it is being redrawn.

      In MFC this is enbodied in the OnPaint handler (internal to CView) which instantiates a CPaintDC object, this subclasses CDC and automatically calls BeginPaint and EndPaint. A pointer to this class is passed to OnDraw (the handler in you code probably) via a CDC pointer (CDC *).

      Now here is the tricky bit because OnDraw is not only used for redrawwing the screen, it is also used for printing and when OnDraw is called for a printer the CDC pointer points to a CDC object not a CPaintDC object.

      So what you need to do is in OnDraw verify that you have a pointer to a CPaintDC, you can do this using the member function IsKindOf which is inherited from CObject. If it is a CPaintDC then you can access the PAINTSTRUCTURE via the member m_ps and then access the area being redrawn through rcPaint.

      However the complications do not stop there, unfortuneately. If there has only been 1 call to InvalidateRect since the last OnDraw then the rcPaint rectangle will be the same as the data passed to InvalidateRect. However WM_PAINT messages are low priority and are only handled if there are no other messages in the applications input queue of a higher priority (which is just about all other messages) so it is possible that there has been 2 calls to InvalidateRect since the last call to OnDraw.

      If there have been 2 or more calls to InvalidateRect (or any other Invalidate... function) since the last call to OnDraw then rcPaint is not the rectangle that was passed to InvalidateRect but smallest rectangle containing the union of all areas invalidated. It is however the area of the screen being redrawn which is I suspect what you want.

      Comment

      • AdrianH
        Recognized Expert Top Contributor
        • Feb 2007
        • 1251

        #4
        Originally posted by Banfa
        If there have been 2 or more calls to InvalidateRect (or any other Invalidate... function) since the last call to OnDraw then rcPaint is not the rectangle that was passed to InvalidateRect but smallest rectangle containing the union of all areas invalidated. It is however the area of the screen being redrawn which is I suspect what you want.
        Hi Banfa,

        I got everything you said except the last sentence. What do you mean by "It is however the area of the screen being redrawn"?


        Adrian

        Comment

        • Banfa
          Recognized Expert Expert
          • Feb 2006
          • 9067

          #5
          Sorry should have said window not screen.

          The CPaintDC::m_ps. rcPaint structure (which is of type RECT) defines the area on the window that is being redrawn. In fact Windows sets the clipping region for the window so that areas out side this rectangle can not be redrawn. This may be the entire client area of the screen, for instance if Invalidate() is called in which case

          CPaintDC::m_ps. rcPaint.left = 0
          CPaintDC::m_ps. rcPaint.top = 0
          CPaintDC::m_ps. rcPaint.right = client area width
          CPaintDC::m_ps. rcPaint.bottom = client area height

          However if you called InvalidateRect with RECT(10, 20, 300, 400) it would be

          CPaintDC::m_ps. rcPaint.left = 10
          CPaintDC::m_ps. rcPaint.top = 20
          CPaintDC::m_ps. rcPaint.right = 300
          CPaintDC::m_ps. rcPaint.bottom = 400

          and if you called InvalidateRect twice with RECT(10, 20, 300, 400) and RECT(340, 200, 600, 500) it would be the smallest rectangle that contains the union of these 2 areas or

          CPaintDC::m_ps. rcPaint.left = 10
          CPaintDC::m_ps. rcPaint.top = 20
          CPaintDC::m_ps. rcPaint.right = 600
          CPaintDC::m_ps. rcPaint.bottom = 500

          The point is that drawing to the screen is rather slow compared to everything else, Windows compensates for this by

          1. Making most messages take priority over screen redraw messages so that redrawing only tends to take place if the program is idle (which most programs are most of the time).

          2. Only redrawing the area of the window that is actually required rather than redrawning the whole window.

          Imagine you have a programme that displays a circle that is a lot smaller than the window traveling from left to right on the window with a complex bitmap in the background. At each step the previous image must be erased and the circle displayed in a new location.

          If you have to erase the entire screen and redraw the entire screen it will take a lot longer than if you just erase the current location and new location and redraw the image in the new location.


          So Windows only redraws those parts of the window that are marked as needing redrawing and it passes that information via the PAINTSTRUCTURE so the OnDraw function can be written efficiently and not redraw those bits of the screen that are not being updated.

          Does that make it clearer?

          Comment

          • AdrianH
            Recognized Expert Top Contributor
            • Feb 2007
            • 1251

            #6
            Originally posted by Banfa
            Sorry should have said window not screen.
            Ahh, that makes more sense.
            Originally posted by Banfa
            Does that make it clearer?
            Hey, I've programmed in MFC before so it is clear to me. Question is, is it clear to rushiraj?

            Well rushiraj, what do you think?


            Adrian

            Comment

            Working...