views:

73

answers:

1

I am writing a function that applies special formatting to predetermined keywords when printing a string. For example, in the string - "Why won't this work?" I might need to print the word "Why" underlined and in blue.

I've had to implement this in pieces, printing each segment of a string with a separate call to print. This approach works with one problem - I cannot get the spacing correct when printing the strings. My keywords print over top of previous default text and are overlapped in turn by text printed afterward.

I am using bounding rectangles to place my strings on the printed page.

RectangleF rectKeywordBounds = new RectangleF( 60.0,  60.0, 550.0, 1200.0);

Once I've printed a segment of the string, I modify the size of the rectangle by the number of characters drawn and I print the next segment of the string.

EArgs.Graphics.DrawString(strFragment, fontBlueItalics, Brushes.Blue, rectKeywordBounds );
iLastPrintIndex = strFragment.Length + iLastPrintIndex;

I've used this method to change the print position of the new string segment:

rectKeywordBounds = new Rectangle(rectKeywordBounds .X + iLastPrintIndex, rectKeywordBounds .Y, rectKeywordBounds .Width, rectKeywordBounds .Height);

And I've used this one:

properSpacing = new SizeF(-((float)iLastPrintIndex), 0.0f);
rectKeywordBounds .Inflate(properSpacing);

Both methods result in the same overlapping of segments. The following code advances a bounding rectangle in the fashion I expect, so why doesn't the concept work when printing text within the rectangle?

Rectangle rectKeywordBounds = new Rectangle(90, 90, 800, 100);

for (int x = 0; x < 6; x++)
{
    EventArgs.Graphics.DrawRectangle(Pens.BlueViolet, rectKeywordBounds );
    rectKeywordBounds = new Rectangle(rectKeywordBounds .X + 15, rectKeywordBounds .Y + 200, rectKeywordBounds .Width, rectKeywordBounds .Height);               
}
+1  A: 

You don't say how you are calculating how far to advance the rectangle -- you seem to be using the length of the string, which won't work as this is a character count rather than a coordinate value.

Instead, you should use the Graphics.MeasureString method to calculate how much space is required to print the current segment, and advance the rectangle that much. You may also be able to do this all in one go using Graphics.MeasureCharacterRanges if you are using the same font for all segments.

By the way, if you have the option to use WPF instead of GDI+, then the TextBlock class will take care of all measurement and layout for you.

itowlson
Thanks, itowlson. That's done the trick!
GFalcon