GDI+ and ClearType : inconsistent behavior
-
Wednesday, February 11, 2009 1:38 PM
Hi,
I've got a strange bug with the property Graphics.TextRenderingHint, in a case where I use DrawString() with TextRenderingHint.SystemDefault and TextRenderingHint.ClearTypeGridEdit.
Depending on the order of my instructions, the strings are not drawn in the same way.
Compare the different cases below :
http://www.imageno.com/w2y59tsml9g0pic.html
The code used to obtain this result :namespace GdiBug { using System; using System.Drawing; using System.Drawing.Text; using System.Windows.Forms; public partial class Form1 : Form { [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); bool withBug = args == null || args.Length == 0 || args[0] != "false"; Form1 form = new Form1(); form.WithBug = withBug; form.Text = withBug ? "With Bug" : "Without Bug"; Application.Run(form); } public Form1() { this.Font = new Font("Tahoma", 12f, FontStyle.Bold); this.ClientSize = new Size(200, 60); } public bool WithBug { get; set; } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); using (SolidBrush b = new SolidBrush(ForeColor)) { if (WithBug) { // Draws ClearType first e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; e.Graphics.DrawString("ClearTypeGridFit", Font, b, 10, 0); // Then SystemDefault = aliased e.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault; e.Graphics.DrawString("SystemDefault", Font, b, 10, 24); } else { // Draws SystemDefault first (with antialias) e.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault; e.Graphics.DrawString("SystemDefault", Font, b, 10, 0); // Then ClearTypeGridFit = same result as SystemDefault e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; e.Graphics.DrawString("ClearTypeGridFit", Font, b, 10, 24); } } } } }
Use the application by giving execution argument "true" or "false" (assuming "true" if missing).
The only difference between the 2 columns is the order of instructions. In left column (expected behavior), SystemDefault enum is equal to ClearTypeGridFit when the system has ClearType enabled. In right column, despite the ClearType setting turned on, If you set TextRenderingHint to ClearTypeGridFit, then if you switch back to SystemDefault, the string will be drawn without ClearType turned on...
The incorrect cases highlighten : http://www.imageno.com/b6fs6i89ge83pic.html
By Design or not ?? Any workaround ?? (Note this problem is encountered for different controls using different render mode explicitely, so a "just use the good case" is irrevelant).
Thanks !
All Replies
-
Wednesday, February 11, 2009 2:06 PMModeratorGraphics.DrawString() is too broken to be usable. It got replaced by TextRenderer.DrawText().
Hans Passant. -
Wednesday, February 11, 2009 2:14 PMnobugz said:You suggest to go back to the old GDI instead of using GDI+ ?
Graphics.DrawString() is too broken to be usable. It got replaced by TextRenderer.DrawText().
Hans Passant.
Moreover, the msdn doc for the GDI+ method DrawString() and TextRenderingHint enum don't speak about switching rendering hint... Could not accept it's a bug since... ever ?
I have now to convince the creator of the components we use...
Thanks for the alternative anyway, but I would prefer having an alternative based on GDI+. -
Wednesday, February 11, 2009 2:48 PMModerator
They couldn't fix the bugz in Graphics.DrawString() because way too much .NET 1.x code depended on its quirks. That's what Application.SetCompatibleTextRenderingDefault() is all about too. If you really want to use GDI+, you'll have to find the workarounds for the bugs yourself. Right now, using Graphics.DrawString() in a Paint event is a bug.
Hans Passant.- Marked As Answer by Steven.Yu Monday, February 16, 2009 2:19 AM
-
Wednesday, February 11, 2009 3:36 PMOkay,
For now I'm trying to find a workaround for our app (ie. by creating a fake control which render itself using SystemDefault, to force the correct initialization of these "context").


