Graphics.MeasureString() が予想よりも高い数値を返すのはなぜですか? 質問する

Graphics.MeasureString() が予想よりも高い数値を返すのはなぜですか? 質問する

領収書を生成しており、Graphics オブジェクトを使用して DrawString メソッドを呼び出して必要なテキストを印刷しています。

graphics.DrawString(string, font, brush, widthOfPage / 2F, yPoint, stringformat);

これは、私が必要としていた機能としては問題なく機能します。私は常に何を印刷するかを知っていたので、80mm のレシート用紙に適切に収まるように文字列を手動で切り取ることができました。次に、これをより柔軟にするために、さらに少し機能を追加する必要がありました。ユーザーは、下部に追加される文字列を渡すことができます。

何を入力しようとしているのかわからなかったので、折り返す文字数と文字列自体を受け取る独自のワードラップ関数を作成しました。文字数を調べるために、次のような操作を実行しました。

float width = document.DefaultPageSettings.PrintableArea.Width;
int max = (int)(width / graphics.MeasureString("a", font).Width);

幅は 283 を返します。これは mm に換算すると約 72 で、80 mm の用紙の余白を考慮すると妥当です。

しかし、MeasureString メソッドは、Courier New 8pt フォントで 10.5 を返します。そのため、36 ~ 40 になるはずだった値が 26 になり、2 行のテキストが 3 ~ 4 行になってしまいます。

PrintableArea.Width の単位は 1/100 インチで、グラフィックス オブジェクトの PageUnit は Display (プリンターの場合は通常 1/100 インチ) です。では、なぜ 26 しか返されないのでしょうか?

ベストアンサー1

WindowsClient.net より:

GDI+は、表示されるすべての文字列の両端に小さな量(1/6 em)を追加します。この1/6 emにより、端がはみ出したグリフ(斜体の「') をサポートし、グリッドフィッティングの拡張を支援するために GDI+ にわずかな余裕も与えます。

のデフォルトのアクションは、DrawString隣接する実行を表示するときに不利に働きます。

  • まず、デフォルトの StringFormat は各出力の両端に 1/6 em を追加します。
  • 次に、グリッドに適合した幅が設計より狭い場合、弦は最大 1 em まで収縮することが許可されます。

これらの問題を回避するには:

  • 常に、タイポグラフィ文字列形式 ( )に基づく StringFormatMeasureStringとを渡します。Graphicsを に設定します。このレンダリング方法では、アンチエイリアシングとサブピクセルのグリフ配置を使用してグリッドフィッティングの必要性を回避するため、本質的に解像度に依存しません。DrawStringStringFormat.GenericTypographic
    TextRenderingHintTextRenderingHintAntiAlias

.NET でテキストを描画する方法は 2 つあります。

  • GDI+ (graphics.MeasureStringおよびgraphics.DrawString)
  • GDI (TextRenderer.MeasureTextおよびTextRenderer.DrawText)

マイケル・カプランの(残念な)素晴らしいブログよりすべてを整理する.NET 1.1では、GDI+テキストレンダリング用です。しかし、いくつか問題がありました。

  • GDI+ のややステートレスな性質により、デバイス コンテキストが設定され、各呼び出しの後に元のコンテキストが復元されるため、パフォーマンスの問題が発生します。
  • 国際テキストのシェーピング エンジンは、Windows/Uniscribe および Avalon (Windows Presentation Foundation) では何度も更新されていますが、GDI+ では更新されていないため、新しい言語の国際レンダリング サポートは同じレベルの品質を実現できません。

そこで彼らは、.NETフレームワークを変更して、GDI+のテキストレンダリングシステムを使用し、ジーディーアイ当初、彼らは単に変更できればよいと考えていました。

graphics.DrawString

GDI+ の代わりに古いDrawTextAPI を呼び出すようにしました。しかし、テキストの折り返しと間隔を GDI+ と完全に一致させることはできませんでした。そのため、graphics.DrawStringGDI+ を呼び出し続けるしかありませんでした (互換性の理由。呼び出していたユーザーは、graphics.DrawString突然、テキストが以前のように折り返されなくなることに気付くでしょう)。

GDI テキスト レンダリングをラップするための新しい静的TextRendererクラスが作成されました。このクラスには 2 つのメソッドがあります。

TextRenderer.MeasureText
TextRenderer.DrawText

注記: TextRendererは GDI のラッパーですが、 はgraphics.DrawString依然として GDI+ のラッパーです。


次に、既存のすべての .NET コントロールをどうするかという問題がありました。例:

  • Label
  • Button
  • TextBox

彼らは、それらを切り替えて使用したいと考えていましたTextRenderer(つまり、GDI) が、注意する必要がありました。.NET 1.1 のときのように、コントロールの描画に依存している人がいるかもしれないからです。

そして誕生した」互換性のあるテキストレンダリング

デフォルトでは、アプリケーション内のコントロールは.NET 1.1と同じように動作します(「互換性がある()。

あなた消す互換モードを呼び出すには、次の操作を実行します。

Application.SetCompatibleTextRenderingDefault(false);

これにより、アプリケーションの品質が向上し、速度が速くなり、国際的なサポートも向上します。要約:

SetCompatibleTextRenderingDefault(true)  SetCompatibleTextRenderingDefault(false)
=======================================  ========================================
 default                                  opt-in
 bad                                      good
 the one we don't want to use             the one we want to use
 uses GDI+ for text rendering             uses GDI for text rendering
 graphics.MeasureString                   TextRenderer.MeasureText
 graphics.DrawString                      TextRenderer.DrawText
 Behaves same as 1.1                      Behaves *similar* to 1.1
                                          Looks better
                                          Localizes better
                                          Faster

GDI+TextRenderingHintと対応するLOGFONT品質GDIフォント描画に使用されます:

TextRenderingHint           mapped by TextRenderer to LOGFONT quality
========================    =========================================================
ClearTypeGridFit            CLEARTYPE_QUALITY (5) (Windows XP: CLEARTYPE_NATURAL (6))
AntiAliasGridFit            ANTIALIASED_QUALITY (4)
AntiAlias                   ANTIALIASED_QUALITY (4)
SingleBitPerPixelGridFit    PROOF_QUALITY (2)
SingleBitPerPixel           DRAFT_QUALITY (1)
else (e.g.SystemDefault)    DEFAULT_QUALITY (0)

サンプル

GDI+ (graphics.DrawString) と GDI (TextRenderer.DrawText) のテキスト レンダリングの比較を以下に示します。

GDI+: TextRenderingHintClearTypeGridFitジーディーアイ: CLEARTYPE_QUALITY:

ここに画像の説明を入力してください

GDI+: TextRenderingHintAntiAliasジーディーアイ: ANTIALIASED_QUALITY:

ここに画像の説明を入力してください

GDI+: TextRenderingHintAntiAliasGridFitジーディーアイ:サポートされていません。ANTIALIASED_QUALITY を使用します。:

ここに画像の説明を入力してください

GDI+: TextRenderingHintSingleBitPerPixelGridFitジーディーアイ: PROOF_QUALITY:

ここに画像の説明を入力してください

GDI+: TextRenderingHintSingleBitPerPixelジーディーアイ: DRAFT_QUALITY:

ここに画像の説明を入力してください

DRAFT_QUALITYが と同一でありPROOF_QUALITY、 が と同一であるのは奇妙だと思いますCLEARTYPE_QUALITY

参照

おすすめ記事