DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DrawStringメソッドによる文字描画

環境/言語:[VB2010 Express]
分類:[.NET]

VisualBasic2010Expressにて、文字描画についての質問です。
Graphics.DrawString メソッドを用いてPictureboxへの文字描画をしています。
ですが、Textboxでの表示と様子が異なっています。
・少し文字が粗い
・少し強調文字っぽくなっている
添付した画像は上がDrawStringメソッドで描画した文字で、下がTextboxの文字です。どちらもFontはArial、sizeは22ptです。
DrawStringメソッドでTextboxのようにキレイに描画する方法はないのでしょうか?よろしくお願いします。
添付ファイル: 1377406216.jpg (10 KB)
■No31762に返信(伊藤さんの記事)
すみません。ソースを記載するのを忘れました。
下記の通りです。
-------
Dim canvas As Bitmap
Dim g As Graphics
Dim fnt As Font
Dim layout As Rectangle
Dim stFormat As New StringFormat()

fnt = New Font("Arial", 22, FontStyle.Regular)
canvas = New Bitmap(PictureBox1.Width, PictureBox1.Height)
g = Graphics.FromImage(canvas)
layout = New Rectangle(0, 0, PictureBox1.Width, PictureBox1.Height)

stFormat.Alignment = StringAlignment.Near
stFormat.LineAlignment = StringAlignment.Center

g.DrawString("Measure", fnt, Brushes.Black, layout, stFormat)

PictureBox1.Image = canvas
fnt.Dispose()
g.Dispose()
-------
2013/08/26(Mon) 13:02:31 編集(投稿者)

■No31762に返信(伊藤さんの記事)
> Graphics.DrawString メソッドを用いてPictureboxへの文字描画をしています。
TextRenderer.DrawText や TextBoxRenderer.DrawTextBox ではなく、
Graphics.DrawString による描画ですね。


> ですが、Textboxでの表示と様子が異なっています。
透過色の上に ClearType を施そうとすると、ClearType で処理された領域が
黒く塗りつぶされてしまいます。今回は Black での描画ゆえに滲んだように
見えていますが、Brushes.Red などで描画して、違いを確認してみてください。

今回の場合については、事前に
 'g.Clear(PictureBox1.BackColor)
 g.Clear(Me.BackColor)
などを使って、背景色を不透過色で塗りつぶしておきましょう。
透過色描画が不要な場合には、これでうまくいくかと思います。

透過色描画(半透明ブラシ、あるいは半透過/全透過背景への描画)が必要な
場合は、ClearType の利用を諦めて、かわりにアンチエイリアシングでの
描画に切り替えてみてください。具体的には、g.TextRenderingHint を
アンチエイリアス系のモードに切り替えて描画するということです。
(併せて、g.PixelOffsetMode も高品質モードにしておくとよいでしょう)
この場合、元のテキストと完全同一の内容とは行きませんが、それに近い
結果を得ることができるはずです。
いくつかの事情が存在しています。

まず、Graphics::DrawStringメソッドは、事前に設定されたGraphics::TextRenderingHintの設定によってアンチエイリアスの方法が決められます。
http://dobon.net/vb/dotnet/graphics/antialias.html
Graphics::FromImageによって作成されたGraphicsのTextRenderingHintは、多分SystemDefaultですが、これはアンチエイリアスの品質がよろしくありません(あるいは全く行いません)。

次に、そもそもGraphics::DrawStringと、テキストボックス等で使用される描画ライブラリが異なっているという問題があります。
System.Drawingは全てGDI+という描画ライブラリを使って描画を行いますが、テキストボックス等ではGDIという描画ライブラリを使用しています。
(Label::Textなどの描画は、Mainメソッド冒頭のApplication.SetCompatibleTextRenderingDefaultの呼び出しによってどちらを行うかが決められています)
当然、描画ライブラリによって描画結果は異なります。
GraphicsからGDIで描画する方法も提供されており、Graphics::DrawStringの代わりにTextRenderer::DrawTextメソッドを使用できます。
なおこのメソッドではGraphics::TextRenderingHintは使用されませんが、ある程度のアンチエイリアスは行われるようです(OSのバージョンや設定にも依ると思いますが)。

それから、ディスプレイの設定で、「テキストやその他の項目の大きさの変更」(Win7以外では違う項目名かもしれません)が小-100%以外になっていた場合というのも考えられます。
System.Drawing.Bitmapは確か常に96bppとして作成されます。そこに書き込んだ文字列画像を96bpp以外のデバイスに描画した場合、好ましくないレンダリング結果になる可能性があります。
こちらは、Bitmap::SetResolutionで、e.Graphics.DpiX/DpiYを設定すれば回避できそうな気がします。
// DPIの問題については一切検証してません。
描画されている幅が違うので
Hongliangさんが指摘してされているDpiの違いと
思われます。
2013/08/26(Mon) 16:33:23 編集(投稿者)

■No31771に返信(shuさんの記事)
> 描画されている幅が違うので
> Hongliangさんが指摘してされているDpiの違いと
> 思われます。

それはまた別の問題だと予想しています。

提示のコードには、TextBox の Font を設定している箇所が無いことから、
デザイン時に設定しているであろうと想像できますが、提示頂いた画像では、
TextBox の方の文字は、Arial の字形であるようには見えないためです。

それに、自分の PC はデフォルトで125%設定(120.0 dpi)になっているのですが、
GDI モード/GDI+ モードを切り替えたとしても、最初の画像にあるような
「e」の文字 1 文字分もの幅の変化は見られませんでした。


字形比較すると、下段 TextBox の方は、MS UI Gothic か MS Pゴシック など、
上段の描画は、Arial (または Microsoft Sans Serif) のものに類似していました。

下記は、「ワードパッド」で 描いた 22pt の赤文字を重ねた文字です。
(当方環境は120dpi 設定なので、ワードパッドの縮尺を 80% にしています)
上段は Arial ですが、下段は MS UI Gothic です。字形を比べてみてください。


特に、Windows 7 や 8.x では、Arial が非表示設定になっています。
http://technet.microsoft.com/ja-jp/windows/dd901393.aspx

このままの状態で、デザイン時に TextBox 等のフォントを
フォントダイアログから選択しようとしても、Arialは一覧に現れません。
フォント名の欄に Arial と入力することはできますが、この場合、
直前に選択されていたフォントが割り当てられることになるでしょう。


なお、仮にフォントの非表示設定を解除した状態で、フォントダイアログから
22pt を選択したとして、それがピッタリ 22.0 になる保証はありません。
(たとえば、22.2 ぐらいになってしまう可能性もあります)
添付ファイル: Font.png (44 KB)
みなさま、いろいろとコメントいただきありがとうございます。

魔界の仮面弁士さんのコメントに

>提示のコードには、TextBox の Font を設定している箇所が無いことから、
>デザイン時に設定しているであろうと想像できますが、提示頂いた画像では、
>TextBox の方の文字は、Arial の字形であるようには見えないためです。

とあります。TetBoxのFontは推察通り、デザイン時に設定しました。フォントはArial 22ptです。Arialの字体に見えませんか?
魔界の仮面弁士さん、Hongliangさん、shuさん

いろいろとありがとうございます。私の用途的には、最初に魔界の仮面弁士さんから教えていただいた方法で間に合いそうです。

みなさんの議論は理解できない部分がありますが、何度か読んでいるうちにもう少し理解が深まると思います。

私は下記の様なソースコードで対応することとしました。
また、Hongliangさん投稿にあった、TextRenderer::DrawTextも試してみたいと思います。


ありがとうございました。

-------------
Dim canvas As Bitmap
Dim g As Graphics
Dim fnt As Font
fnt = New Font("Arial", 22, FontStyle.Regular)
canvas = New Bitmap(PictureBox1.Width, PictureBox1.Height)
g = Graphics.FromImage(canvas)
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
g.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
g.DrawString("Measure", fnt, Brushes.Black, 0, 0)
PictureBox1.Image = canvas
fnt.Dispose()
g.Dispose()
-------
添付ファイル: 1377519759.jpg (17 KB)
解決済み!
魔界の仮面弁士の仰るとおり、テキストボックスのフォントはArilになっていませんでした。デザイン時にはArialの22ptに設定してあるのですが、fontが反映されていなかったようでした。
コード内に

Dim fnt As Font
fnt = New Font("Arial", 22, FontStyle.Regular)
TextBox1.Font = fnt

を追加したところ字体が変化しました。
添付ファイル: 1377521242.jpg (19 KB)
■No31776に返信(伊藤さんの記事)
> フォントはArilになっていませんでした。
実際には何になっていましたか?


> デザイン時にはArialの22ptに設定してあるのですが、
Form1.Designer.vb 内のコード(InitializeComponent 内のコード)を
確認してみてください。


■No31777に返信(魔界の仮面弁士さんの記事)
> ■No31776に返信(伊藤さんの記事)
>>フォントはArilになっていませんでした。
> 実際には何になっていましたか?

MS UI Gothicになっていたようです。



>>デザイン時にはArialの22ptに設定してあるのですが、
> Form1.Designer.vb 内のコード(InitializeComponent 内のコード)を
> 確認してみてください。

確認してみましたが、Arial,22ptとなっています。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板