GDI と GDI+
GDI というのは、ウィンドウズで画面やプリンタへの描画に使われている技術です。
また、GDI+ は Windows XP で登場した技術で、GDI を完全に置き換える後継となるものです。.NET Framework では、System.Drawing
名前空間の中に GDI+ を使用するためのクラスが収められています。
この二種類の技術を使ってテキストを描画してみました。
同じフォントで描画しているはずなのに、結構品質が違いますね。下はギザギザが目立ってあまりにもひどすぎます。また、同じフォントのはずなのに大きさが違ってきています。さて、どちらが GDI でどちらが GDI+ でしょうか?
「まさか……」と思われた方、正解です。下のひどい方が GDI+ による描画なのです。しかも、スムージングモードには最高性能を指定しています。
protected override void OnPaint(PaintEventArgs e)
{
var text = "Hello World! こんにちは世界!";
var graphics = e.Graphics;
TextRenderer.DrawText(graphics, text, Font, new Point(50, 50), ForeColor);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawString(text, Font, new SolidBrush(ForeColor), new PointF(50, 100));
}
このコードの TextRenderer.DrawText()
が GDI を使うメソッド、Graphics.DrawString()
が GDI+ を使うメソッドです。
Visual Studio で Windows Forms アプリケーションを作成すると、Program.cs の Main()
に昔はなかったメソッド呼び出しが一つあります。
Application.SetCompatibleTextRenderingDefault(false);
これは何をするものかというと、「コントロールの描画には GDI+ ではなく GDI を使いなさい」という命令です。「GDI+ のテキスト描画は使い物にならない」と MS 自身が認めているわけですね。
なぜリリース前にわからなかったのでしょう?
また、リリース後何年も経っているのに改善されないところを見ると、どうやらこのまま GDI+ は放っておくつもりなのでしょう。
2017 年 4 月 10 日追記
@snowbug さんの指摘を受けて、TextRenderingHint = TextRenderingHint.AntiAlias
に設定したものを追加しました。前回のフォントの大きさを覚えていなかったので少し字が小さくなったようですが、原寸大です。
一番下が TextRenderingHint.AntiAlias
なのですが、どうでしょうか?
protected override void OnPaint(PaintEventArgs e)
{
var text = "Hello World! こんにちは世界!";
var graphics = e.Graphics;
TextRenderer.DrawText(graphics, text, Font, new Point(50, 50), ForeColor);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawString(text, Font, new SolidBrush(ForeColor), new PointF(50, 100));
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
graphics.DrawString(text, Font, new SolidBrush(ForeColor), new PointF(50, 150));
}
2017 年 4 月 10 日追記
@takabosoft さんの指摘を受けて、次のようにしてみました。フォントは「游ゴシック, 20.25pt」です。メイリオでもやってみましたが、似たような結果になりました。また、ほかの部分をコメントアウトして、メソッド内部の最初二行と最後二行だけにしても同じでした。Application.SetCompatibleTextRenderingDefault(true);
としても同じでした。
当方 Windows10 です。他の方の環境では違いが出るのでしょうか?
protected override void OnPaint(PaintEventArgs e)
{
var text = "Hello World! こんにちは世界!";
var graphics = e.Graphics;
TextRenderer.DrawText(graphics, text, Font, new Point(50, 50), ForeColor);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawString(text, Font, new SolidBrush(ForeColor), new PointF(50, 100));
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
graphics.DrawString(text, Font, new SolidBrush(ForeColor), new PointF(50, 150));
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
graphics.DrawString(text, Font, new SolidBrush(ForeColor), new PointF(50, 200));
}
執筆日: 2017/04/10
Discussion