Re: Invalidating a region and having only that region drawn
- From: Andrew <Andrew@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 8 Jun 2005 17:29:03 -0700
Hi Doug and Bob,
Having 'returned' from another section of my project, I have now had a
better chance to digest the responses that have been provided on my original
post.
I now have a clearer understanding of how painting works, however my
original question still remains ie just where does one place one's drawing
code such that it does not get unncessarily called during the paint event
handling operation ?
I have placed my layer drawing routines in my TabPage derived OnPaint
handler because that drawing code requires a Graphics object and without
resorting to CreateGraphics() where else can I get a graphics object other
than from the PaintEventArgs object of OnPaint ??
My application has five such TabPage derived classes which exist in a
TabControl. Clicking on any TabPage draws that 'view' by calling specific
drawlayer routines such as the one I originally described. Because OnPaint is
called quite often (such as just after window creation, window resizing(not
relevant here), window refocus; this was another reason for placing my
drawlayer routines in OnPaint becasue it effectivley displays an initial
number of graphical objects. When such initial detail is displayed, the stage
is set on that view for users to alter the appearance, add delete to the
initial content. And as the designer, I want the 'behind the scenes' drawing
operation to be as efficient as possible.
Take one such example where this initial view portrays a large rectangle
with ruler lines and dimension numbers - that represent a plan view of the
building outer. Now within this exist say half a dozen pairs of small
rectangles that represent the structural supports of the building outer. A
user selects one of these support rectangles which changes both their color
(and that of their dimensions/rulers) from gray to blue ie the select color.
The user can then reposition that support rectangle pair.
Behind the scenes: A. for the object selecting operation, I invalidate two
rectangles that represent the rectangle pair and its ruler/dimension situated
above that pair.
B. For the resizing code, after data
validation, I invalidate the entire client area because many other support
rectangles could also be moved.
The problem is that with operation A. I believe that the clip region of
PaintEventArgs contains both of my invalidated regions and hence I would only
expect those parts of the view to be redrawn - however because my drawlayer
code is situated in OnPaint (for the reasons mentioned above) the entire
initial structure is redrawn. It looks fine however I only want the
invalidated sections to be redrawn.
I am now writing small graphical objects which will represent locks (that
will act to lock the position of any selected support frame pair) and I
certainly do not want to have to redraw the entire initial structure when the
user simply clicks to change to graphical appearance of one of these lock
objects.
So considering all of the above, do you have any suggestions regarding how
to handle the objectives of initial display and fine detail update ?
Many thanks
Andrew.
"Doug Forster" wrote:
> Hi Andrew,
>
> I could be wrong but I get the feeling you haven't fully understood what Bob
> was saying. You shouldn't be attempting to use clipping at all to manipulate
> the logical content of a window. The job of a paint handler is *just* to
> paint part or all of a window with the correct content of the moment as
> ascertained from state maintained external to the whole painting paradigm.
> You should remember that Windows itself can invalidate any part of your
> window at any time. This is not specific to .NET but is simply how Windows
> has always worked.
>
> Cheers
> Doug Forster
>
> "Andrew" <Andrew@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
> news:18697CA9-3687-425F-8458-1E9FA99BAC84@xxxxxxxxxxxxxxxx
> > Thanks,
> >
> > I will need to rethink my drawing strategy paying closer attention to the
> > clipping region.
> >
> >
> > "Bob Powell [MVP]" wrote:
> >
> >> Painting works like this:
> >>
> >> The system stores the results of invalidate calls internally. Invalidate
> >> without parameters will mark a whole window for refreshing, invalidate
> >> with
> >> parameters will add regions to the list of "dirty" areas maintained by
> >> the
> >> system.
> >>
> >> When the queue is empty and there is nothing else to do, the system
> >> checks
> >> for dirty areas and issues a WM_PAINT message if any are found, otherwise
> >> it
> >> issues a WM_ENTERIDLE message to kick-off idle time processing.
> >>
> >> In all cases the result of the WM_PAINT message, for Windows Forms
> >> programs,
> >> is to run the OnPaint override which in turn kicks of the Paint event.
> >>
> >> The clipping region set in the OnPaint event arguments will be the sum of
> >> all the regions or the whole window depending on whether Invalidate was
> >> called without parameters.
> >>
> >> It's up to your code to either keep a list of its own dirty rectangles /
> >> regions OR to do output based on the bounds of the clipping region
> >> provided
> >> by the paint event arguments. Whatever paint strategies you devise, such
> >> as
> >> only drawing partial content or layers, is entirely up to you and needs
> >> to
> >> be managed by you. The system doesn't care about reporting anything
> >> except
> >> that there is an area of screen marked as being in need of a refresh.
> >>
> >> --
> >> Bob Powell [MVP]
> >> Visual C#, System.Drawing
> >>
> >> Find great Windows Forms articles in Windows Forms Tips and Tricks
> >> http://www.bobpowell.net/tipstricks.htm
> >>
> >> Answer those GDI+ questions with the GDI+ FAQ
> >> http://www.bobpowell.net/faqmain.htm
> >>
> >> All new articles provide code in C# and VB.NET.
> >> Subscribe to the RSS feeds provided and never miss a new article.
> >>
> >>
> >>
> >>
> >>
> >> "Andrew" <Andrew@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
> >> news:B82AC0B1-5BFF-4867-A7A6-B8E0DB074432@xxxxxxxxxxxxxxxx
> >> > Hello,
> >> >
> >> > In my application I perform all the drawing operations from within the
> >> > form's
> >> > OnPaint method (the form is ultimately a TabPage derivative) ie
> >> >
> >> > protected override void OnPaint(PaintEventArgs e)
> >> > {
> >> > base.OnPaint(e);
> >> > //the base class LayerView.OnPaint handles things like
> >> > AutoScrollPosition
> >> > int s = 1; // temporary dummy scale value
> >> > m_building.DrawBuildingLayer(g,s,this.Name);
> >> > m_columns.DrawColumnsLayer(g,s,this.Name);
> >> > }
> >> >
> >> > The drawing works well and smoothly handles operations such as
> >> > scrolling.
> >> >
> >> > It is my understanding that when Invalidate() is called ie with no
> >> > parameters, the entire client area of the form is added to the update
> >> > region
> >> > and a paint message is sent that raises the Paint event which is
> >> > handled
> >> > by
> >> > the OnPaint handler. OK
> >> >
> >> > When Invalidate(region) is called, I believe that only that region is
> >> > added
> >> > to the form's update region resulting in only that region being redrawn
> >> > at
> >> > the next Paint message.
> >> >
> >> > Either way, calling Invalidate results in OnPaint to be executed.
> >> >
> >> > When I call Invalidate() the entire client area is redrawn with both
> >> > drawing
> >> > functions called and this is exactly the outcome that I want for that
> >> > scenario.
> >> >
> >> > The problem is that when I only want to redraw a invalidated region of
> >> > this
> >> > form,
> >> > the entire form is redrawn( which is causing objects to be appear
> >> > incorrectly).
> >> >
> >> > ie When I call Invalidate(with a specific region) in order to only have
> >> > that
> >> > region redrawn I do NOT intend for the likes of DrawBuildingLayer nor
> >> > DrawColumnsLayer
> >> > to be called. Obviously they are being called because of their presence
> >> > in
> >> > OnPaint().
> >> >
> >> > I cannot think of any other place where I could call these draw
> >> > functions
> >> > other than OnPaint and I want to steer clear of CreateGraphics.
> >> >
> >> > Are there any suggestions regarding a strategy of how I could call
> >> > Invalidate(region) and only have that region redrawn ?
> >> >
> >> >
> >> > Thanks
> >> >
> >> > Andrew.
> >> >
> >>
> >>
> >>
>
>
>
.
- Follow-Ups:
- Re: Invalidating a region and having only that region drawn
- From: Doug Forster
- Re: Invalidating a region and having only that region drawn
- Prev by Date: PrintDocument lines per page calculation
- Next by Date: Re: Invalidating a region and having only that region drawn
- Previous by thread: Re: Invalidating a region and having only that region drawn
- Next by thread: Re: Invalidating a region and having only that region drawn
- Index(es):
Relevant Pages
|