TextRenderer.DrawText with TextFormatFlags.ModifyString
-
Hi all! I am creating a simple user control which renders text within its paint event handler. Under some circumstances (when the output rectangle is very small) the exception "The object is already in use elsewhere." occurs...Which does not make any sense because a) the program is not multithreaded and b) it isn't particuarly complex. This crashing began when I started using the
TextFormatFlags.ModifyString
flag, and the problem is likewise immediately cured by removing this flag. Am I using the flag in an incorrect fashion? TheitemLabel
string is actually updated correctly (end ellipsis is added when displayed).// Force duplication of string, the original value is changed otherwise.
string itemLabel = new string(item.Label.ToCharArray());// Use text renderer to output required text.
TextRenderer.DrawText(ctx.Graphics, itemLabel, activeFont, Rectangle.Round(extraLabelBounds), textColour, backgroundColor, TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString);If this is a problem, is it possible to get the EndEllipsis version of the string based upon the graphics context, font, output rectangle bounds, and text? Many thanks! Lea Hayes
-
Hi all! I am creating a simple user control which renders text within its paint event handler. Under some circumstances (when the output rectangle is very small) the exception "The object is already in use elsewhere." occurs...Which does not make any sense because a) the program is not multithreaded and b) it isn't particuarly complex. This crashing began when I started using the
TextFormatFlags.ModifyString
flag, and the problem is likewise immediately cured by removing this flag. Am I using the flag in an incorrect fashion? TheitemLabel
string is actually updated correctly (end ellipsis is added when displayed).// Force duplication of string, the original value is changed otherwise.
string itemLabel = new string(item.Label.ToCharArray());// Use text renderer to output required text.
TextRenderer.DrawText(ctx.Graphics, itemLabel, activeFont, Rectangle.Round(extraLabelBounds), textColour, backgroundColor, TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString);If this is a problem, is it possible to get the EndEllipsis version of the string based upon the graphics context, font, output rectangle bounds, and text? Many thanks! Lea Hayes
-
What is the class of the exception that you are getting? That might help to determine what it is that is used elsewhere... Where do you get the Graphics and Font objects from?
Despite everything, the person most likely to be fooling you next is yourself.
Hi, The exception class is
System.InvalidOperationException
. TheGraphics
class is as provided by the paint event handler (this is the overriden methodprotected override void OnPaint(PaintEventArgs e)
). The font object is generated by:Font activeFont = SystemFonts.DefaultFont;
if(series of conditions)
activeFont = new Font(activeFont, FontStyle.Bold);Here is the exception information: System.InvalidOperationException was unhandled Message="Object is currently in use elsewhere." Source="System.Drawing" StackTrace: at System.Drawing.Graphics.CheckErrorStatus(Int32 status) at System.Drawing.Graphics.DrawLine(Pen pen, Single x1, Single y1, Single x2, Single y2) Whilst the above suggests that the problem is related to the 'DrawLine' method, just simply removing the 'TextFormatFlags.ModifyString' flag prevents the crash from occurring. For my particular application all I needed was a boolean value which indicates whether the output text was truncated or not. Whilst I have found a workaround for this (listed below), I am still interested to find out why this exception is being thrown...I have double-checked my code and I cannot understand how the objects are being used elsewhere because they are pretty much created each time the paint event is handled. The only things which are in common are the data item and the user control itself.
// Use text renderer to output required text.
if (extraLabelBounds.Width > 0)
TextRenderer.DrawText(ctx.Graphics, itemLabel, activeFont, Rectangle.Round(extraLabelBounds), textColour, backgroundColor, TextFormatFlags.EndEllipsis);// NOTE: Unfortunately the following is probably less efficient than with the alternative flag...
// Measure string both with and without end ellipsis to determine if string has overflown or not.
Size measuredA = TextRenderer.MeasureText(ctx.Graphics, itemLabel, activeFont);
Size measuredB = TextRenderer.MeasureText(ctx.Graphics, itemLabel, activeFont, Size.Round(extraLabelBounds.Size), TextFormatFlags.EndEllipsis);// If label rendered label length is different to the actual item label then a
// tooltip will be made available.
bool hasOverflown = !measuredA.Equals(measuredB);Thanks, Lea Hayes