Hi All, I'd really appreciate some help for drawing precision images.
I'm trying to draw gridlines and have them perfectly spaced. I've
provided some code at the end to simulate the issues I'm facing.
In psuedo-code (where I am splitting up the control into four (using
three gridlines), I take the width of the controls client ares, and
calculate the position of each gridline. I do this by allowing for a
border of 1 pixel either side, and three gridlines = 5 pixels taken up
by lines. I then divide the remainder by the number of segments (4).
So:
float segmentWidth = (float)(this.clientRectangle - (5)) / 4;This
works fine when the grid is wide. As soon as you start adding to the
number of segments, or make the control smaller - it visiblly shows
the segments not being the same width. (Try the sample code I've
provided, by pasting into a new cotnrol and dropping it on to a form,
anchor it to all sides and run, then resize the form a few times).
I suspect it's because the precision of using floats means that the
display cannot draw the required number of pixels accurately???
The problem gets worse when you try to add blocks to fill the segment
(i'm trying to devise a timeline control). I calculate the width
required for the block by using the segment's size (and allowing for
any gridlines it crosses). This works OK until the gridlines start
falling out of place and the two seperate drawings (the gridlines and
the blocks) do not correspond.
Any ideas on the best way to go forwards with this guys / gals???
Thanks
protected override void OnPaint(PaintEventArgs pe)
{
Int32 i32GridLineWidth = 1;
RectangleF rectGrid = new RectangleF(0, 0,
this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
SizeF vertLineSize = new SizeF();
SizeF horzLineSize = new SizeF();
SizeF segmentSize = new SizeF();
Int32 i32NumberOfHorzSegements = 15;
Int32 i32NumberOfVertSegements = 10;
//Define the vertical of the gridline
vertLineSize.Height = (float)rectGrid.Height;
vertLineSize.Width = (float)i32GridLineWidth;
//Define the hoizontal gridline
horzLineSize.Height = (float)i32GridLineWidth;
horzLineSize.Width = (float)rectGrid.Width;
//calulate the width (allowing for the gridlines aswell
segmentSize.Width = (float)(rectGrid.Width -
(i32NumberOfHorzSegements * vertLineSize.Width)) /
i32NumberOfHorzSegements;
segmentSize.Height = (float)(rectGrid.Height -
(i32NumberOfVertSegements * horzLineSize.Height)) /
i32NumberOfVertSegements;
//Draw the gridlines
using (Pen gridlinePen = new Pen(Color.Gray,
i32GridLineWidth))
{
//Draw the vertical gridlines.
for (Int32 i32Line = 1; i32Line <=
i32NumberOfHorzSegements - 1; i32Line++)
{
float fltXpos = (float)((vertLineSize.Width *
(i32Line - 1)) + (i32Line * segmentSize.Width));
pe.Graphics.DrawLine(gridlinePen, fltXpos,
rectGrid.Top, fltXpos, rectGrid.Height);
}
//Draw the horizontal gridlines.
for (Int32 i32Line = 1; i32Line <=
i32NumberOfVertSegements - 1; i32Line++)
{
float fltYpos = (float)((horzLineSize.Height *
(i32Line - 1)) + (i32Line * segmentSize.Height));
pe.Graphics.DrawLine(gridlinePen, rectGrid.Left,
fltYpos, rectGrid.Width, fltYpos);
}
//Draw the outer control border.
pe.Graphics.DrawRectangles(gridlinePen, new
RectangleF[] { rectGrid });
}
//Draw some bars.
using (SolidBrush segmentBrush = new
SolidBrush(Color.Crimson))
{
Int32 i32VertSegment = 1;
Int32 i32HorzSegment = 3;
Int32 i32Length = 10;
RectangleF segmentToFill = new RectangleF(
rectGrid.X + (i32HorzSegment * (i32GridLineWidth +
segmentSize.Width)),
rectGrid.Y + ((i32VertSegment - 1) *
(i32GridLineWidth + segmentSize.Height)) + i32GridLineWidth,
rectGrid.X + (i32Length * (i32GridLineWidth +
segmentSize.Width)) - (2 * i32GridLineWidth),
rectGrid.Y + (1 * (i32GridLineWidth +
segmentSize.Height)) - (2 * i32GridLineWidth));
pe.Graphics.FillRectangle(segmentBrush,
segmentToFill);
}
// Calling the base class OnPaint
//base.OnPaint(pe);
}
protected override void OnResize(EventArgs e)
{
//base.OnResize(e);
this.Invalidate();