Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / March 2008

Tip: Looking for answers? Try searching our database.

What property defines a controls paint bounds?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Tom P. - 27 Feb 2008 21:20 GMT
I am creating a custom control and I'm trying to get the painting of
it correct. I'd like to simply use:
e.Graphics.FillRectangle(Brushes.White, DisplayRectangle);
... or ...
e.Graphics.FillRectangle(Brushes.White, ClientRectangle);
... or ...
e.Graphics.FillRectangle(Brushes.White, Bounds);

But each of those fails to draw a rectangle all the way around (most
are 1 pixel off). Instead I find myself having to use:
e.Graphics.FillRectangle(Brushes.White, DisplayRectangle.X,
DisplayRectangle.Y, DisplayRectangle.Width - 1,
DisplayRectangle.Height - 1);

What am I really supposed to use? How do I get that last pixel
correct?

Tom P.
Matt - 27 Feb 2008 23:10 GMT
> I am creating a custom control and I'm trying to get the painting of
> it correct. I'd like to simply use:
[quoted text clipped - 14 lines]
>
> Tom P.

What is wrong with e.Graphics.FillRectangle( Brushes.White,
e.ClipRectangle);

?
Matt
Tom P. - 28 Feb 2008 18:58 GMT
> > I am creating a custom control and I'm trying to get the painting of
> > it correct. I'd like to simply use:
[quoted text clipped - 20 lines]
> ?
> Matt

The same thing that's wrong with everything else - it's off by one
pixel.

Tom P.
Peter Duniho - 27 Feb 2008 23:11 GMT
> I am creating a custom control and I'm trying to get the painting of
> it correct. I'd like to simply use:
[quoted text clipped - 12 lines]
> What am I really supposed to use? How do I get that last pixel
> correct?

Just what you're doing.  Either DisplayRectangle or ClientRectangle are  
appropriate, depending on your specific need (by default, they are the  
same).  And you need to subtract one from the width and height to get the  
whole rectangle to draw.

This may seem arbitrary, but there's actually a good reason for it.  
Graphical coordinates are treated as being the intersection of 0-width  
lines in a grid.  The pixels are _between_ these lines.  A line drawn from  
(0,0) to (0,100) for example will fill all of the pixels just to the right  
of that 0-width vertical line between those coordinates, inclusive.

When you try to draw a rectangle a specific width and height, all of the  
pixels are being drawn to the right and below of any coordinate that  
describes the rectangle.  This means that on the right and bottom of the  
rectangle, if you've specified coordinates that are actually the absolute  
outer bounds of the area in which the control can draw, those pixels fall  
outside of the control and aren't drawn.

The fix is to reduce the width and height of the rectangle you're trying  
to draw by the width of one pixel, so that the pixels drawn for that  
rectangle fall within the control's drawable area.

Pete
Tom P. - 28 Feb 2008 18:59 GMT
On Feb 27, 5:11 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> > I am creating a custom control and I'm trying to get the painting of
> > it correct. I'd like to simply use:
[quoted text clipped - 36 lines]
>
> Pete

I guess you're right. There's nothing else I can find to change this.
There should be a "DrawRectangle" property for this type of
situation.  Oh, well... thanks.

Tom P.
Peter Duniho - 28 Feb 2008 19:13 GMT
> I guess you're right. There's nothing else I can find to change this.
> There should be a "DrawRectangle" property for this type of
> situation.  Oh, well... thanks.

I don't understand what you mean.  There is a DrawRectangle() method, but  
it just outlines the rectangle rather than filling it.

There's not an actual problem here with .NET.  The only issue is that you  
need to comprehend the API differently.  Once you understand that  
coordinates you provide don't refer to pixels, but rather to the grid  
between pixels, everything makes sense.

If you don't understand that, then yes...you'll continue to believe a  
problem exists, even though none does.

Pete
Tom P. - 28 Feb 2008 20:00 GMT
On Feb 28, 1:13 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> > I guess you're right. There's nothing else I can find to change this.
> > There should be a "DrawRectangle" property for this type of
[quoted text clipped - 12 lines]
>
> Pete

I know there is a method DrawRectangle(), but I was talking about a
property that describe the ACTUAL painting region. In the same units,
or relationship, as the method is going to use it. What use have I for
a description of an area I have to adjust before using? Why provide me
with measurements that are close to what I need, but don't finally
describe the area I want? There are no fewer than four rectangles that
describe areas one pixel larger than the Displayed area of a control.
You mean to tell me they couldn't find it in their hearts to provide
one single property that depicts the ACTUAL area that methods like
DrawRectangle() are expecting? It doesn't seem like that big a deal.

Tom P.
Peter Duniho - 28 Feb 2008 20:47 GMT
> [...]
>> There's not an actual problem here with .NET.  The only issue is that  
[quoted text clipped - 10 lines]
> I know there is a method DrawRectangle(), but I was talking about a
> property that describe the ACTUAL painting region.

The relationship between ClientRectangle, DisplayRectangle, etc. and the  
visible area of the control is very well defined.  Because of the way the  
_graphical_ API works, it's true that those rectangles can't be passed  
directly to the graphical API if you want to draw a line that is contained  
within that area.  But they do exactly describe the actual painting region  
itself.

> In the same units,
> or relationship, as the method is going to use it. What use have I for
> a description of an area I have to adjust before using?

I'm sorry you don't see the use for ClientRectangle, etc.  Suffice to say,  
those properties are in fact very useful, and if they behaved differently,  
they wouldn't be.

> Why provide me
> with measurements that are close to what I need, but don't finally
> describe the area I want?

Because the rectangle you get _is_ an exact description of the Control  
instance.  It would be far worse to have a ClientRectangle return (for  
example) a rectangle that's only 639 pixels wide by 479 pixels high when  
the control is actually 640 pixels wide by 480 pixels high.

As things are now, the rectangle you get is exactly correct.  You would  
prefer that it be wrong just for your convenience in one specific scenario?

> There are no fewer than four rectangles that
> describe areas one pixel larger than the Displayed area of a control.

You're incorrect that they "describe areas one pixel larger than the  
displayed area of a control".  They describe an area _exactly_ the same  
size as the displayed area of the control.  It's just that the graphical  
API always fills pixels to the right and left of whatever grid coordinates  
you've specified.

If your control tells you that the ClientRectangle is 100 pixels wide,  
then if you count the pixels on the screen you will find there are exactly  
100 pixels of width there.  Not 101.  And definitely not 99.  Exactly 100  
pixels.

> You mean to tell me they couldn't find it in their hearts to provide
> one single property that depicts the ACTUAL area that methods like
> DrawRectangle() are expecting? It doesn't seem like that big a deal.

Well, I'm sorry you aren't able to see that it's a big deal, but it is.  
Those properties must describe the actual size of the Control precisely.  
It would be wrong for them to return a rectangle that's one pixel smaller  
in width and height than the control actually is.

At the same time, it's inappropriate for the graphical API to sometimes  
fill pixels inside the description of a shape and sometimes fill pixels  
outside the description of a shape.  That API needs to be consistent, and  
if it did what you apparently would prefer it did, it wouldn't be.  For  
example, you can think of a rectangle as four lines.  But if a rectangle  
got drawn inside the boundary specified by the rectangle, rather than just  
following the lines defined by the rectangle and drawing it the same way  
as any other line, you wouldn't be able to get the same results drawing  
the individual lines as you get drawing the rectangle itself.

This would be really bad.  It's critical that a graphical API not have  
inconsistencies like this.  There's a very good reason that all of the  
major graphical APIs, including all of Apple's Quickdraw iterations along  
with Carbon and Cocoa, all of the Windows graphical APIs, Java, etc.  
behave exactly this way.  It's a mathematically pure, consistent API that  
allows a developer to produce reliable results.

Is it really that big of a deal to have to subtract your pen size (one  
pixel by default, of course) from the width and height of the rectangle  
you want to be visible?  It seems to me that you could easily write a  
short method that handles this for you, if you really find it that hard to  
just do it explicitly when needed.

Pete
Tom P. - 28 Feb 2008 21:07 GMT
On Feb 28, 2:47 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> > [...]
> >> There's not an actual problem here with .NET.  The only issue is that
[quoted text clipped - 85 lines]
>
> Pete

I think I am being misunderstood (and over something this picayune, -1
isn't really that hard). I never advocated the current methods or
properties be changed, just that an additional one be provided that
bridged the apparent discrepancy between what is provided and what is
drawn. I understand that there are reasons to describe the contents of
a control as inclusive. Much like you posited, it would not do for a
control to say it was 101 pixels wide when it wasn't.

I understand it's the same concept as a List object, there's a
difference between the Count and the index of an item. If a List has
100 items they are 0 through 99.

Understanding all that, what is wrong with saying the PaintingArea is
from (x, y) 0, 0 to (width, height) 99, 99?

But I think your last statement gives me some insight into my issue
(and a better way to paint the object, so thank you) The particular
rectangles provided are only 1 pixel too small because the pen I am
using is 1 pixel. They are, in point of fact, "Pen.Width" smaller. I
should not be subtracting 1, I should be subtracting the Pen.Width to
ensure the entire pen falls within the paintable area regardless of
what size the pen is. To that end I thank you for helping me
understand exactly what is being presented and how to use it.

Tom P.
Peter Duniho - 28 Feb 2008 21:12 GMT
> [...]
> Understanding all that, what is wrong with saying the PaintingArea is
> from (x, y) 0, 0 to (width, height) 99, 99?

Because that would describe an area only 99 pixels wide and 99 pixels high  
(9801 pixels total), when in fact the "painting area" (that is, the area  
that the control is responsible for painting) is 100 pixels wide by 100  
pixels high (10000 pixels total).

> But I think your last statement gives me some insight into my issue
> (and a better way to paint the object, so thank you) The particular
[quoted text clipped - 3 lines]
> ensure the entire pen falls within the paintable area regardless of
> what size the pen is.

Yes, that's exactly right.

> To that end I thank you for helping me
> understand exactly what is being presented and how to use it.

You're welcome.

Pete
Tom P. - 29 Feb 2008 14:19 GMT
Crap, now I'm back to not understanding. I tried putting Pen.Width in
my calculations and it worked, for pens with a width of 1. If the user
changes the border size the X, Y, gets messed up. And the great thing
about this is, it's messed up by "half" the pen width. Is there a good
tutorial that presents all these little control drawing issues so
people can understand them? I just know there's some scale variable
that I'm missing that would make everything fall in line. At this
point I think I need a tutorial and some instruction.

Tom P.
Peter Duniho - 29 Feb 2008 18:52 GMT
> Crap, now I'm back to not understanding. I tried putting Pen.Width in
> my calculations and it worked, for pens with a width of 1. If the user
> changes the border size the X, Y, gets messed up. And the great thing
> about this is, it's messed up by "half" the pen width. Is there a good
> tutorial that presents all these little control drawing issues so
> people can understand them?

Bob Powell's web site is the one I see referenced often.  It's not  
perfect, but I've seen lots of good advice there.  It's the closest I've  
seen to what you're asking for.
http://www.bobpowell.net/

I didn't see anything on his site that specifically addresses the GDI/.NET  
coordinate system, but I only took a quick look.  You might browse around  
and see if there's something there that's useful to you.

It seems I've misremembered the effect of pen width as it relates to the  
coordinates.  This discussion in the GDI+ docs suggests so anyway:  
http://msdn2.microsoft.com/en-us/library/ms533855(VS.85).aspx.  "When the  
rectangle is drawn, the pen is centered on the rectangle's boundary".

In other words, in GDI+ you actually need to inset the whole rectangle by  
half the pen width, rather than insetting the right and bottom by a whole  
pen width (note that you still need to reduce the width and height of the  
drawn rectangle by the pen width in total to get it to fit within the  
displayable area...it's just where you make the reduction is different).

This actually simplifies things, as the Rectangle struct has an Inflate()  
method that can be used to do just that, rather than having to adjust the  
width and height explicitly.  It will preserve the center of the rectangle  
while adjusting the boundary of the rectangle in all four directions by  
the values passed in.  Just pass in half the pen width, and that method  
will fix your rectangle so it draws the way you want.

Sorry for any confusion...the perils of working with a wide variety of  
graphical APIs, I guess.  It's hard to keep the exact behaviors of each  
straight.  :(

Pete
Family Tree Mike - 28 Feb 2008 00:58 GMT
> I am creating a custom control and I'm trying to get the painting of
> it correct. I'd like to simply use:
[quoted text clipped - 14 lines]
>
> Tom P.

It looks like you really could do it with e.Graphics.Clear(Color.White);
Tom P. - 28 Feb 2008 18:57 GMT
On Feb 27, 6:58 pm, Family Tree Mike
<FamilyTreeM...@discussions.microsoft.com> wrote:
> > I am creating a custom control and I'm trying to get the painting of
> > it correct. I'd like to simply use:
[quoted text clipped - 16 lines]
>
> It looks like you really could do it with e.Graphics.Clear(Color.White);

That's fine for clearing the control to white but what would I use to
draw the black outline?

Tom P.
Family Tree Mike - 01 Mar 2008 13:51 GMT
> > It looks like you really could do it with e.Graphics.Clear(Color.White);
>
> That's fine for clearing the control to white but what would I use to
> draw the black outline?
>
> Tom P.

I just let the control's border property take care of that.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.