Bug: DrawRectangle...*or* Rectangle

  • Thread starter Thread starter James F. Bellinger
  • Start date Start date
J

James F. Bellinger

DrawRectangle draws from Left to Right, it appears.
However, Rectangle seems to think the rectangle does
not include the pixel referred to in its Right property..
the range includes Left and every pixel up to but not
including Right.

You can see this strange inconsistency (though at which
of the two it should be changed, I'm not sure ... I'd say
DrawRectangle, and then Rectangle needs to have clearer
documentation (largely because going:

for (int i = r.Top; i < r.Bottom; i ++)

Seems the way one would normally do things. You can see it
by doing a DrawRectangle, constructing a Rectangle using
the override that accepts a Size parameter. The right and bottom
edges of the rectangle will be one pixel off. :-)

Have a nice day :)
Jim Bellinger
 
Hi James,
I've found this inconsisitency only with pens with width of 1. If you create
a pen with width more the 1 (2 let say) and set pen's alignment to
PenAlignment.Inset the rectangle will be exactly Rectangle.Width pixels wide
and Rectangle.Height pixels high.
In the book "Programming MS Windows with c#" Charles Petzold gives some
unclear explanation why when the pen's width is set to 1 the rectangle is 1
pixel higher and 1 pixel wider, which makes me think that MS finds this
reasonable. Anyways, I remember the way he explained to us the off-by-1
error in GDI in his book about Win32 and I feel that in his new book about
..NET he just tries the get off the subject as quick as it possible.

In GDI the drawing functions draw objects from the first point, up to the
last point but not including the last point. This decision was made to make
drawing connected lines with LineTo easier. If the last point was drawn this
would cause some points to be drawn twice, which in some ROPs could be
unallowable.

In GDI+ there are no ROPs so the lines can be drawn including the last
point. And it is as is. The same doesn't go for rectangles though. Let say
we want to draw a grid which lines are 1 pixel wide (I dare to say most of
the grids use lines 1 pixel wide ).
It could be done in several ways. And one of them is to use DrawRectangle or
DrawRectangles methods do draw the grid cells.
One posible drawing of grid 2x2 is:

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);
Pen pen = new Pen(Color.Red,1);

Rectangle[] r = new Rectangle[4]{new Rectangle(10, 10, 10, 10), new
Rectangle(20, 10, 10, 10), new Rectangle(10, 20, 10, 10), new Rectangle(20,
20, 10, 10)};
e.Graphics.DrawRectangles(pen, r);
}

The numbers used for the rectangles are pretty obvious and the the grid
looks exactly how it has to look. If it wasn't that off-by-1 the grid will
be surrounded with 1-pixel-wide line and the internal lines will be 2 pixels
wide or we would have used some others *not so obvious* numbers.

According to what MS did in Win32's GDI I believe this is the main reason
for this strange inconsisitency.

B\rgds
100
 
100 said:
Hi James,
I've found this inconsisitency only with pens with width of 1. If you create
a pen with width more the 1 (2 let say) and set pen's alignment to
PenAlignment.Inset the rectangle will be exactly Rectangle.Width pixels wide
and Rectangle.Height pixels high.
In the book "Programming MS Windows with c#" Charles Petzold gives some
unclear explanation why when the pen's width is set to 1 the rectangle is 1
pixel higher and 1 pixel wider, which makes me think that MS finds this
reasonable. Anyways, I remember the way he explained to us the off-by-1
error in GDI in his book about Win32 and I feel that in his new book about
.NET he just tries the get off the subject as quick as it possible.

In GDI the drawing functions draw objects from the first point, up to the
last point but not including the last point. This decision was made to make
drawing connected lines with LineTo easier. If the last point was drawn this
would cause some points to be drawn twice, which in some ROPs could be
unallowable.

It does make sense for lines... though I can't think of any real-life
use for an XOR pen. :-)
In GDI+ there are no ROPs so the lines can be drawn including the last
point. And it is as is. The same doesn't go for rectangles though. Let say
we want to draw a grid which lines are 1 pixel wide (I dare to say most of
the grids use lines 1 pixel wide ).
It could be done in several ways. And one of them is to use DrawRectangle or
DrawRectangles methods do draw the grid cells.
One posible drawing of grid 2x2 is:

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);
Pen pen = new Pen(Color.Red,1);

Rectangle[] r = new Rectangle[4]{new Rectangle(10, 10, 10, 10), new
Rectangle(20, 10, 10, 10), new Rectangle(10, 20, 10, 10), new Rectangle(20,
20, 10, 10)};
e.Graphics.DrawRectangles(pen, r);
}

The numbers used for the rectangles are pretty obvious and the the grid
looks exactly how it has to look. If it wasn't that off-by-1 the grid will
be surrounded with 1-pixel-wide line and the internal lines will be 2 pixels
wide or we would have used some others *not so obvious* numbers.

Regardless of whether the numbers are obvious or not, it's patently absurd
that you've just told it the rectangles are 10x10 and it is painting them
11x11. :-)
The pixels should be two wide in that example, because you've asked it to
make a bunch of boxes that are 10x10, 10 pixels apart from each other.
Ugh. *does not compute*. ;)

There's no reason for them to keep this, except that Windows Forms (and
System.Drawing by extension) is a cheesy hack over Win32's forms, albeit one
nice in some areas like the designer support (though it's hard to forgive
the fact
that some controls work like .Net ones and some don't -- just today I
encountered
the fact that ClientSize does not work for ListViews... joy...).

At best, I would think it could at least not lie in the Width and Height
parameters.
When I give it a Size parameter saying it needs to be 10 wide and 10 tall,
it should
do that. :-) But I know, it won't. :-)
According to what MS did in Win32's GDI I believe this is the main reason
for this strange inconsisitency.

B\rgds
100

Thanks :)
Jim Bellinger
 
Hi James,
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);
Pen pen = new Pen(Color.Red,1);

Rectangle[] r = new Rectangle[4]{new Rectangle(10, 10, 10, 10), new
Rectangle(20, 10, 10, 10), new Rectangle(10, 20, 10, 10), new Rectangle(20,
20, 10, 10)};
e.Graphics.DrawRectangles(pen, r);
}

The numbers used for the rectangles are pretty obvious and the the grid
looks exactly how it has to look. If it wasn't that off-by-1 the grid will
be surrounded with 1-pixel-wide line and the internal lines will be 2 pixels
wide or we would have used some others *not so obvious* numbers.

Regardless of whether the numbers are obvious or not, it's patently absurd
that you've just told it the rectangles are 10x10 and it is painting them
11x11. :-)
The pixels should be two wide in that example, because you've asked it to
make a bunch of boxes that are 10x10, 10 pixels apart from each other.
Ugh. *does not compute*. ;)

Hmm, it depends on what you are going to use the grid for. If I use the grid
just to rule a page I would cound the pixels for the first line up to the
next line no including the last one otherwise I have to count the last line
twise when I start counting the pixels in the next column. Which doesn't
make a lot of sense to me. Unfortunately we cannot draw lines between the
pixels.
In this case all cells in the grid are 10 pixels wide and 10 pixels high.

You say the System.Drawing is a hack over the GDI. it is true, but in this
case I dare to say it is different. In Win32's GDI the off-by-1 error works
in the oposite direction. It drawns one pixel less as the oposite to the
GDI+ where the off-by-1 error is one pixel more. ;)

I can recall a lot of post in the Win32 news groups programmers complaining
of off-by-1 error in GDI. I strongly believe that there would be as many
complaints if we didn't (don't) have this off-by-1. So what I want to say is
that some times it might work for you some times it might not it depends on
the logic of the program.

I think this is not a bug. They just have to explain more clear that the pen
alignment works diferently for pens 1 pixel wide.

B\rgds
100
 
Back
Top