4

I have implemented a CellPainting event handler that uses TextRenderer.DrawText and it has worked great up until a cell had an ampersand in it. The cell shows the ampersand correctly while editing the cell, but when editing is done and it is drawn, it shows up as a small line (not an underscore).

Editing cell Not Editing cell

using System;
using System.Drawing;
using System.Windows.Forms;

namespace StackOverFlowFormExample {
    public partial class DataGridViewImplementation : DataGridView {
        public DataGridViewImplementation() {
            InitializeComponent();
            this.ColumnCount = 1;
            this.CellPainting += DGV_CellPainting;
        }

        private void DGV_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) {         
            if (!e.Handled && e.RowIndex > -1 && e.Value != null) {
                e.PaintBackground(e.CellBounds, false);
                TextRenderer.DrawText(e.Graphics, e.Value.ToString(), 
                                      e.CellStyle.Font, e.CellBounds,
                                      e.CellStyle.ForeColor, TextFormatFlags.VerticalCenter);
                e.Handled = true;
            }
        }
    }
}

//creating the datagridview
public partial class MainForm : Form {
    public MainForm() {
        InitializeComponent();  
        DataGridViewImplementation dgvi = new DataGridViewImplementation();
        this.Controls.Add(dgvi);
        dgvi.Rows.Add("this is a & value");
    }
}

replacing

TextRenderer.DrawText(e.Graphics, e.Value.ToString(), 
                      e.CellStyle.Font, e.CellBounds, 
                      e.CellStyle.ForeColor, TextFormatFlags.VerticalCenter);

with

e.PaintContent(e.ClipBounds);

shows it correctly, of course I want to be able to customize the painting of the content though. I've also tried using

e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font, Brushes.Black, e.CellBounds);

e.PaintContent Image

but it doesn't draw it the same as

e.Paint(e.ClipBounds, e.PaintParts);

I use e.Paint in my actual code when a cell is being painted that doesn't need my customized painting.

How can I get e.Graphics.DrawString to look the same as e.Paint or get TextRenderer.DrawText to display the ampersand correctly?

Blake Thingstad
  • 1,639
  • 2
  • 12
  • 19

1 Answers1

8

You want to use the TextRenderer version since DrawString should really only be used for printing:

TextRenderer.DrawText(e.Graphics, e.Value.ToString(), 
                  e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor, 
                  TextFormatFlags.NoPrefix | TextFormatFlags.VerticalCenter);

The NoPrefix flag will show the ampersand correctly.

LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • Amazing! That fixed it! Do you have any explanation as to why NoPrefix has to be used? I would never have guessed that I'd have to use that without having found this "bug" first. Also, can you be more clear by what you mean by "printing"? – Blake Thingstad Nov 22 '16 at 23:25
  • 2
    @BlakeThingstad It's not a bug. An ampersand is used to signify the the hot letter in a button to activate it, so if you create a button and gave it a text property of "&Hello", the H would be underlined. Two ampersands would be used to only show one. – LarsTech Nov 22 '16 at 23:33
  • 3
    @BlakeThingstad DrawString had a a lot of issues drawing text on a monitor, so it go replaced with the TextRenderer class. But DrawString is still relevant for printing to paper because of the DPI differences. All of the Microsoft controls use the TextRenderer class. See this answer [Graphics.DrawString vs TextRenderer.DrawText?Which can Deliver Better Quality](http://stackoverflow.com/a/23230570/719186) for a better detailed explanation. – LarsTech Nov 22 '16 at 23:42