Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. BeginPaint issues

BeginPaint issues

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestiongraphicsjsonannouncement
10 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    Waldermort
    wrote on last edited by
    #1

    I've created a custom control, using the low level win32 api, which displays an animation. Using a thread I render a frame, or rather update the parts need it, and call InvalidateRect passing the area that was changed. In the main thread I handle WM_PAINT with the BeginPaint EndPaint pair AND use the paintstruct's rect to repaint only the area required. The rendering is backed by a TimerQueue, an event and a thread that waits on the event. I couldn't work out why my CPU usage was hovering around 80%. Each frame involves a lot of alpha blending hence the need to only update the changed parts. After 2 days I've narrowed the problem to BeginPaint. MSDN states, and this is GDI 101, when handling a WM_PAINT message BeginPaint and EndPaint should be called to validate the invalid rect, otherwise windows will continue to post the message. Well, it's just not happening. The window has not been validated and my code has been rendering the full client area (lot's of work) on each call. If I add a ValidateRect in my handler the problem goes away and CPU down to 0-1%. My question is why? Is this a bug or am I missing something?

    Waldermort

    T C 2 Replies Last reply
    0
    • W Waldermort

      I've created a custom control, using the low level win32 api, which displays an animation. Using a thread I render a frame, or rather update the parts need it, and call InvalidateRect passing the area that was changed. In the main thread I handle WM_PAINT with the BeginPaint EndPaint pair AND use the paintstruct's rect to repaint only the area required. The rendering is backed by a TimerQueue, an event and a thread that waits on the event. I couldn't work out why my CPU usage was hovering around 80%. Each frame involves a lot of alpha blending hence the need to only update the changed parts. After 2 days I've narrowed the problem to BeginPaint. MSDN states, and this is GDI 101, when handling a WM_PAINT message BeginPaint and EndPaint should be called to validate the invalid rect, otherwise windows will continue to post the message. Well, it's just not happening. The window has not been validated and my code has been rendering the full client area (lot's of work) on each call. If I add a ValidateRect in my handler the problem goes away and CPU down to 0-1%. My question is why? Is this a bug or am I missing something?

      Waldermort

      T Offline
      T Offline
      TheGreatAndPowerfulOz
      wrote on last edited by
      #2

      WalderMort wrote:

      a ValidateRect in my handler the problem goes away

      I think that's the correct way. Don't know if it's a bug or not.

      If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
      You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun

      W 1 Reply Last reply
      0
      • W Waldermort

        I've created a custom control, using the low level win32 api, which displays an animation. Using a thread I render a frame, or rather update the parts need it, and call InvalidateRect passing the area that was changed. In the main thread I handle WM_PAINT with the BeginPaint EndPaint pair AND use the paintstruct's rect to repaint only the area required. The rendering is backed by a TimerQueue, an event and a thread that waits on the event. I couldn't work out why my CPU usage was hovering around 80%. Each frame involves a lot of alpha blending hence the need to only update the changed parts. After 2 days I've narrowed the problem to BeginPaint. MSDN states, and this is GDI 101, when handling a WM_PAINT message BeginPaint and EndPaint should be called to validate the invalid rect, otherwise windows will continue to post the message. Well, it's just not happening. The window has not been validated and my code has been rendering the full client area (lot's of work) on each call. If I add a ValidateRect in my handler the problem goes away and CPU down to 0-1%. My question is why? Is this a bug or am I missing something?

        Waldermort

        C Offline
        C Offline
        Chuck OToole
        wrote on last edited by
        #3

        Well, if the documentation says you have to do it and the experimentation shows that you have to do it, seems like it's working as designed. Not a bug, the rules.

        W 1 Reply Last reply
        0
        • T TheGreatAndPowerfulOz

          WalderMort wrote:

          a ValidateRect in my handler the problem goes away

          I think that's the correct way. Don't know if it's a bug or not.

          If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
          You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun

          W Offline
          W Offline
          Waldermort
          wrote on last edited by
          #4

          The BeginPaint function automatically validates the entire client area.[^] So having to manually add a ValidateRect is not the correct way because BeginPaint should have done it for me.

          Waldermort

          T 1 Reply Last reply
          0
          • C Chuck OToole

            Well, if the documentation says you have to do it and the experimentation shows that you have to do it, seems like it's working as designed. Not a bug, the rules.

            W Offline
            W Offline
            Waldermort
            wrote on last edited by
            #5

            Chuck O'Toole wrote:

            Well, if the documentation says you have to do it and the experimentation shows that you have to do it, seems like it's working as designed. Not a bug, the rules.

            But the documentation doesn't say that, infact it says that since I am calling BeginPaint there is no need to call ValidateRect. http://msdn.microsoft.com/en-us/library/dd145194(VS.85).aspx[^]

            Waldermort

            C 1 Reply Last reply
            0
            • W Waldermort

              Chuck O'Toole wrote:

              Well, if the documentation says you have to do it and the experimentation shows that you have to do it, seems like it's working as designed. Not a bug, the rules.

              But the documentation doesn't say that, infact it says that since I am calling BeginPaint there is no need to call ValidateRect. http://msdn.microsoft.com/en-us/library/dd145194(VS.85).aspx[^]

              Waldermort

              C Offline
              C Offline
              Chuck OToole
              wrote on last edited by
              #6

              Well, you don't show how you do the re-drawing of the area in your WM_PAINT processing. Where did you place the call to ValidateRect()? Immediately on entry or just before the EndPaint()? Is it possible that you are calling some other functions that cause the invalidate to happen (explicitly or implicitly) before the call to ValidateRect()?

              W 1 Reply Last reply
              0
              • C Chuck OToole

                Well, you don't show how you do the re-drawing of the area in your WM_PAINT processing. Where did you place the call to ValidateRect()? Immediately on entry or just before the EndPaint()? Is it possible that you are calling some other functions that cause the invalidate to happen (explicitly or implicitly) before the call to ValidateRect()?

                W Offline
                W Offline
                Waldermort
                wrote on last edited by
                #7

                It's too much code to simply paste here. You'll have to take my word for it that there is no way for the rect to be invalidated other than when I explicitly call for it. My code works like this. bitmap A is updated from a thread. Thread calls InvalidateRect when done updating a frame. bitmap B contains the window background and doesn't change. bitmap C is a double buffer. When WM_PAINT arrives, call BeginPaint, alpha blend bitmap A with B onto C and BitBlt bitmap C to the screen. When done call EndPaint. Like I said this is GDI 101, and I have never had a problem like this with previous versions of windows or Visual Studio. As it stands now, calling ValidateRect from anywhere in the WM_PAINT handler solves the problem. I currently have it after the call to EndPaint. Without this call, WM_PAINT is being sent from window creation and always with the full client area. Even though at that time my drawing routines have not yet begun. And yes I do call Begin End on EVERY WM_PAINT. On another note, passing the message onto DefWindowProc, after those two calls, also results in undesired behaviour. rectangles are being validated but not those that are in the paint struct. I'm really beginning to think this is a bug.

                Waldermort

                C 1 Reply Last reply
                0
                • W Waldermort

                  The BeginPaint function automatically validates the entire client area.[^] So having to manually add a ValidateRect is not the correct way because BeginPaint should have done it for me.

                  Waldermort

                  T Offline
                  T Offline
                  TheGreatAndPowerfulOz
                  wrote on last edited by
                  #8

                  Hmpf! I stand corrected. I was going off of faint memory. Like I said, "I thought".

                  If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
                  You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun

                  1 Reply Last reply
                  0
                  • W Waldermort

                    It's too much code to simply paste here. You'll have to take my word for it that there is no way for the rect to be invalidated other than when I explicitly call for it. My code works like this. bitmap A is updated from a thread. Thread calls InvalidateRect when done updating a frame. bitmap B contains the window background and doesn't change. bitmap C is a double buffer. When WM_PAINT arrives, call BeginPaint, alpha blend bitmap A with B onto C and BitBlt bitmap C to the screen. When done call EndPaint. Like I said this is GDI 101, and I have never had a problem like this with previous versions of windows or Visual Studio. As it stands now, calling ValidateRect from anywhere in the WM_PAINT handler solves the problem. I currently have it after the call to EndPaint. Without this call, WM_PAINT is being sent from window creation and always with the full client area. Even though at that time my drawing routines have not yet begun. And yes I do call Begin End on EVERY WM_PAINT. On another note, passing the message onto DefWindowProc, after those two calls, also results in undesired behaviour. rectangles are being validated but not those that are in the paint struct. I'm really beginning to think this is a bug.

                    Waldermort

                    C Offline
                    C Offline
                    Chuck OToole
                    wrote on last edited by
                    #9

                    Of course, if this were a newly introduced bug in Windows (not saying that it isn't) then we'd expect to see a lot more programs going into high cpu usage processing WM_PAINT messages. Theory goes that the EndPaint() call will take care of the ValidateRect() on the .rcPaint member of the PAINTSTRUCT you received in BeginPaint(). Is that the same thing you are using in your manual ValidateRect() call? Is there a possibility that it is being clobbered during your paint processing? If .rcPaint changed between Begin and End that would explain what you see. You say you use that member to do your re-drawing, read-only?

                    W 1 Reply Last reply
                    0
                    • C Chuck OToole

                      Of course, if this were a newly introduced bug in Windows (not saying that it isn't) then we'd expect to see a lot more programs going into high cpu usage processing WM_PAINT messages. Theory goes that the EndPaint() call will take care of the ValidateRect() on the .rcPaint member of the PAINTSTRUCT you received in BeginPaint(). Is that the same thing you are using in your manual ValidateRect() call? Is there a possibility that it is being clobbered during your paint processing? If .rcPaint changed between Begin and End that would explain what you see. You say you use that member to do your re-drawing, read-only?

                      W Offline
                      W Offline
                      Waldermort
                      wrote on last edited by
                      #10

                      Chuck O'Toole wrote:

                      Theory goes that the EndPaint() call will take care of the ValidateRect() on the .rcPaint member of the PAINTSTRUCT you received in BeginPaint(). Is that the same thing you are using in your manual ValidateRect() call? Is there a possibility that it is being clobbered during your paint processing? If .rcPaint changed between Begin and End that would explain what you see. You say you use that member to do your re-drawing, read-only?

                      BeginPaint() actually. Like you said though, if it were a bug... which makes me think there must be a problem in my code somewhere. Anyway, found it! Deep in there was a legacy debug routine to update the entire screen. Now to find out who made it and then... Thanks for the suggestions though.

                      Waldermort

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups