18

I find the way the DrawString function cuts off entire characters or words to be counterintuitive. Showing parts of the text clearly conveys that something is missing.

Here are some examples:

StringTrimming.None: enter image description here

StringTrimming.Character: enter image description here

What I want: enter image description here (GIMP mockup)

Is StringTrimming.None the same as StringTrimming.Character? They seem to behave exactly alike in my case. Is there something I could have overlooked or is this a known "feature"?

According to the docs StringTrimming.None "Specifies no trimming."

This site with examples created with Java even show "None" to trim more characters than "Character".

Are there other tricks to get this effect?

Note: I do not want to display "…" or similar. I find this to be a waste of space but that is probably a discussion for UX.

Community
  • 1
  • 1
Sarien
  • 6,647
  • 6
  • 35
  • 55
  • sorry .. just want to know .. what would you apply this to ? – matzone Jun 04 '13 at 14:31
  • @Rotem Good idea but that will mess up wrapping in the case where there is plenty of vertical space. Still, you should add that as an answer. It works great for single lines! – Sarien Jun 04 '13 at 14:36
  • @matzone A DataGridView (a table for the less Windows Forms savvy). – Sarien Jun 04 '13 at 14:37
  • @Sarien I did :) Could you give an example about the vertical space? I didn't understand the case you're referring to. – Rotem Jun 04 '13 at 14:37
  • @Rotem If the cell is very high but too narrow for the text, DrawString will normally wrap the text. Naturally, it doesn't get that right anymore if you lie about the size of your rectangle. :) – Sarien Jun 04 '13 at 14:45
  • @Sarien I'm assuming you don't like the default ellipse and that is why you are doing this? – Justin Jun 04 '13 at 14:51

2 Answers2

14

It's possible that the text appears to be trimmed because it's actually wrapping invisibly onto the next line. In the call to Graphics.DrawString, disable wrapping by passing a StringFormat object whose FormatFlags property is set to NoWrap:

StringFormat format =
    new StringFormat
    {
        FormatFlags = StringFormatFlags.NoWrap,
        Trimming = StringTrimming.None
    };
g.DrawString(s, font, brush, rect, format);
Michael Liu
  • 52,147
  • 13
  • 117
  • 150
  • 1
    Is it possible to retain the wrapping and only disable it when there is not enough space for another line anyway? (I could measure everything to do that but would like to avoid that.) – Sarien Jun 04 '13 at 14:47
  • 1
    @Sarien: There doesn't seem to be a flag for that. You would have to use an `if` statement or `?` operator, and pass the `NoWrap` flag only if the height of your drawing rectangle is less than twice the line height. – Michael Liu Jun 04 '13 at 14:52
4

As a workaround, you can give the DrawString method a bigger RectangleF than you really want, and set the clipping region of your Graphics object to the actual RectangleF you want to draw the string in.

RectangleF rect = new RectangleF(10, 10, 30, 15);
e.Graphics.DrawRectangle(Pens.Red, Rectangle.Truncate(rect));

RectangleF fakeRect = new RectangleF(rect.Location, new SizeF(short.MaxValue, short.MaxValue));

Region r = e.Graphics.Clip;
e.Graphics.SetClip(rect);            
e.Graphics.DrawString("1 Default", this.Font, SystemBrushes.ControlText, fakeRect);
e.Graphics.Clip = r;

Note that this code assumes you wish to anchor your text to the top left corner of the rectangle. Otherwise you should generate the fake rectangle in a method that maintains the same anchor point as your intended layout rectangle.

Rotem
  • 21,452
  • 6
  • 62
  • 109
  • This is likely the best approach. The `DrawString()` trim options are about manipulating the string prior to display. What you want, however, is to display it all and clip. – DonBoitnott Jun 04 '13 at 14:22