Jump to content
  • Advertisement
Sign in to follow this  
Zipster

[.net] [C#] Drawing a string in different colors?

This topic is 3259 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been trying to draw a string in multiple colors for the past couple of hours now and I haven't had much luck. Basically, I want to take the existing functionality I have with Graphics.DrawString and add the ability to change the color sub-strings to be different than the brush color, i.e. change all instances of "foo" to red and "blah" to blue. That's pretty much it. I thought this would be simple enough. First render the string using the base color. Then use Graphics.MeasureCharacterRanges to find all the sub-string regions. Iterate the regions, and re-render all the sub-strings in their special colors. Since I'm not changing any font sizes, styles, layouts, etc., they would align perfectly with the full string and I'd be done. Well hours later and I'm still fiddling with all the parameters for DrawString and MeasureCharacterRanges (mainly string formats) trying to get the damn sub-strings to align. I've messed with every setting I could find, in all manner of combinations. Either the regions are off horizontally by a few pixels, or they're too small and clip/wrap the text, or they're completely off the bitmap altogether. And that's assuming that the sub-strings don't wrap! I haven't even attempted to code that case yet since I get even get the basics working. Has anyone ever attempted this before? Hours on Google and nothing I've seen has either been relevant or worked. For now I've hacked in some offsetting code because it's always off by 7 pixels to the right, but that's a horrible solution.

Share this post


Link to post
Share on other sites
Advertisement
I played around with some code and ran into the same issue and then found this article.

My guess is that the stringformat and textformatflag incompatibility is messing things up.

I haven't got the time to test it but de example code (download at the top of the article) might be of use to you.

Share this post


Link to post
Share on other sites
Oi, try using System.Windows.Forms.TextRenderer. It has DrawText and MeasureText functions that have been accurate for my purposes. IIRC, you may have to fiddle with the TextFormatFlags a wee bit, but TextFormatFlags.TextBoxControl should work nicely.

I'm thinking I've read somewhere that the reason MeasureString and DrawString don't match up is 'cause it uses GDI+, whereas TextRenderer uses GDI. Something about how GDI+ handles pixel/sub-pixel I'm guessing?

Hope this helps!

[Edit: Blergh. Didn't bother to read the article linked in the post above. [disturbed]]

[Edited by - nerd_boy on August 16, 2009 1:06:00 PM]

Share this post


Link to post
Share on other sites
Thanks for the replies, I wasn't even aware that the Forms namespace had text rendering. The problem with MeasureText though is that it measures text in "local space", so to speak. MeasureCharacterRanges allows me to pass in a full string with bounding rectangle, and then ask for a sub-rectangle bounding a particular range of characters (i.e. characters 23-29 in "global space"). I can then (ideally) just render that range of characters in a different color, using the returned sub-rectangle.

If I were to use MeasureText, I would need to split the string using the colored keywords as delimiters, and then render it in pieces. It could work, but it would take a lot more effort than what I have now. I would also have to implement word wrap functionality myself, for instance, but all things considered I believe the extra work is worth finding a robust solution.

Thanks again! I'll let you know how it goes [smile]

Share this post


Link to post
Share on other sites
Using anything other than MeasureCharacterRanges gave me hideously wrong results when I did this. You might try looking at the owner draw code in this code to see how I handle it. The results look like this:

Cleaned up version of dotTrace style visualizer

[Edited by - Promit on August 17, 2009 12:56:54 PM]

Share this post


Link to post
Share on other sites
Quote:
Since I'm not changing any font sizes, styles, layouts, etc., they would align perfectly with the full string and I'd be done.
You'd need to clear underneath the subranges first, as the antialiasing will cause problems otherwise.

Share this post


Link to post
Share on other sites
MeasureCharacterRanges and DrawString will not return the same results for substrings as for the whole string. Let me repeat: what you are trying to do will *not* work.

It's a known limitation of GDI+ text rendering. One potential solution is to use TextRenderer.MeasureText and TextRenderer.DrawText which rely on GDI instead. However, you will have to turn off text antialiasing for this to work, which is not advisable (edit: or clear the subranges, as benryves suggested - not always possible).

Solution: split your text into text runs (one run per [font, style, size, color] combination) and draw the runs sequentially.

Better solution: use a RichTextControl which offers this functionality out of the box.

Another solution: use a WebBrowser Control and format your text using HTML.

Share this post


Link to post
Share on other sites
Quote:
Original post by ernow
Promit, the link to your code is broken. DotTracestyle.cs with a capital 'S' ;)
o_O

I can't fix the link. Every time I change it, the S snaps back to lowercase. It happens without the link too:
http://slimtune.googlecode.com/svn/trunk/SlimTuneUI/DotTracestyle.cs
style.

Share this post


Link to post
Share on other sites
Quote:
Original post by Promit
Quote:
Original post by ernow
Promit, the link to your code is broken. DotTracestyle.cs with a capital 'S' ;)
o_O

I can't fix the link. Every time I change it, the S snaps back to lowercase. It happens without the link too:
http://slimtune.googlecode.com/svn/trunk/SlimTuneUI/DotTracestyle.cs
style.

You can get around it using HTML entities.

http://slimtune.googlecode.com/svn/trunk/SlimTuneUI/DotTraceStyle.cs =>
http://slimtune.googlecode.com/svn/trunk/SlimTuneUI/DotTraceStyle.cs

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!