Re: how to minimize processing when repainting

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Mon, 4 Apr 2005 08:15:03 -0700, Joe Doyle
<JoeDoyle@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:

>"Severian" wrote:
>
>> On Fri, 1 Apr 2005 13:55:03 -0800, Joe Doyle
>> <JoeDoyle@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
>>
>> >Say an app should redraw a part of itself when, for example, it receives some
>> >data from a socket. One way to do it is to call Invalidate(), causing the
>> >entire window to be repainted. But if it's a lot of work to repaint the
>> >entire window, and almost always the repaint only needs to redraw a small
>> >part of the window, there's a lot of unnecessary processing going on. So,
>> >instead you call InvalidateRect() with only the small rectangle that needs to
>> >get updated, and you make your paint handler a little smarter so it only
>> >repaints what needs to be repainted. Great...but now say, there's two small
>> >rectangles that need to be repainted, say a 30x30 rectangle at the top left
>> >and a 30x30 at the bottom right. You call InvalidateRect() two times, once
>> >with each of the rectangles, you get one WM_PAINT, and the invalid rectangle
>> >is (not surprisingly) the entire window, since GDI unioned the two together
>> >into one WM_PAINT. Back to square one.
>> >
>> >so, the fundatmental question is, how do you keep track of what triggered a
>> >WM_PAINT message, so that the paint handler can be certain it needs to only
>> >repaint those two small rectangles? you can't just set a bit somewhere and
>> >have the paint handler assume if it's set, it can just redraw the rectangles,
>> >because something else (i.e., another window being dragged across your
>> >window) might really have invalidated an area other than those two
>> >rectangles, in which case you really do have to redraw everything in the clip
>> >rectangle.
>> >
>> >I'd prefer not to go the UpdateWindow() route, because I'd like Windows to
>> >keep painting a low priority event, occurring only when nothing else is going
>> >on, and have it automagically accumulate invalid regions.
>> >
>> >I'm leaning towards Invalidate()'ing each small rectangle separately, i.e.,
>> >first invalidating one rectangle, and if the subsequent paint message's clip
>> >rectangle is identical to the first invalidated rectangle, invalidating the
>> >second rectangle, and so on. If the processing of multiple, but small, paint
>> >messages for a single app update, is faster than repainting the entire window
>> >in one shot, then this should work. It's not particularly elegant though, and
>> >no doubt others have run into this before. Any tips, suggestions, or
>> >criticism would be appreciated.
>>
>> One solution:
>>
>> Use the update region, divide your painting into sections (strips or
>> tiles), and draw only the sections that intersect the update region.
>>
>> Note that you must call GetUpdateRgn() BEFORE BeginPaint().
>>
>> Something like:
>>
>> PAINTSTRUCT ps;
>> HRGN hrgn = CreateRectRgn(0,0,0,0);
>> if (GetUpdateRgn(hwnd, hrgn, eraseornot) != NULLREGION) {
>> HDC hdc = BeginPaint(hwnd, &ps);
>> RECT rc;
>> /* for each tile or strip */ {
>> SetRect(rc, ...);
>> if (RectInRgn(hrgn, &rc)) {
>> /* Paint section */
>> }
>> }
>> }
>> EndPaint(hwnd, &ps);
>> DeleteObject(hrgn);

>Thanks for the reply, didn't know about the GetUpdateRgn() call...and now
>for a new twist: the app is written in .NET. It doesn't look like
>GetUpdateRgn is wrapped by Control, and I'm willing to bet that BeginPaint is
>called well before Control's paint event handling code gets to a point where
>the app could call a DllImport'ed GetUpdateRgn. Is there a way for the app
>hook into the message loop and check for paints before Control gets to them?

Sorry, I'm not familiar with .NET. You might want to ask on one of the
microsoft.public.dotnet newsgroups, or perhaps someone else will join
in with info for .NET.

--
Phillip Crews aka Severian
Microsoft MVP, Windows SDK
Posting email address is real
.



Relevant Pages

  • Re: how to minimize processing when repainting
    ... the app could call a DllImport'ed GetUpdateRgn. ... But if it's a lot of work to repaint the ... >>instead you call InvalidateRect() with only the small rectangle that needs to ...
    (microsoft.public.win32.programmer.gdi)
  • Re: how to minimize processing when repainting
    ... >>entire window to be repainted. ... But if it's a lot of work to repaint the ... >>instead you call InvalidateRect() with only the small rectangle that needs to ...
    (microsoft.public.win32.programmer.gdi)
  • Re: how to minimize processing when repainting
    ... >entire window to be repainted. ... But if it's a lot of work to repaint the ... >instead you call InvalidateRect() with only the small rectangle that needs to ...
    (microsoft.public.win32.programmer.gdi)
  • how to minimize processing when repainting
    ... entire window to be repainted. ... But if it's a lot of work to repaint the ... instead you call InvalidateRect() with only the small rectangle that needs to ...
    (microsoft.public.win32.programmer.gdi)
  • Re: Getting/Setting a Windows Size/Position
    ... My app will create a transparent window over the other app for the ... Rectangle object referenced by GetBoundsRect. ... I believe my problem lies in the 'flags' attribute of GetBoundsRect. ...
    (microsoft.public.dotnet.languages.csharp)