私の質問は、Windows 7 で正しく動作するためにフォント処理をどのように変更する必要があるかということです。以前は有効だったが、もはや有効ではないという仮定を立てたことは確かです。しかし、私はどこから探し始めればいいのかさえわかりません! 誰かが助けてくれることを祈っています!私が理解している詳細は次のとおりです (Microsoft Windows Developers フォーラムにもこの質問を投稿しましたが、回答はありません)。
はい、私は時代遅れです (まあ、私はまだプレーン C で WIN32 コードを書いています!) ウィンドウのクライアント領域内でさらに古い DOS 画面 I/O ライブラリを模倣する 10 年前の DLL を作成しました。言うまでもなく、固定幅フォントしか使用できません。DLL を使用する一部のプログラムを Windows 7 に移行すると、固定幅の TRUE TYPE フォントを使用すると奇妙なちらつきが発生します (ビットマップ フォントは引き続き完全に動作します)。で書かれた単一の文字ExtTextOut
が本来よりも幅が広いことに注意してください。3 つの異なる方法で測定値を確認しました ( GetTextExtentPoint32
132 文字の文字列を使用して 132 で除算する方法、呼び出して 256 文字すべてGetTextMetrics
を使用する方法GetCharABCWidths
)、フォントが同じ幅であることにすべて同意しました。しかしExtTextOut
フォント幅よりも 1 ピクセルまたは 2 ピクセル広い背景の四角形をレンダリングしています。パラメータで指定された位置の 1 ピクセルか 2 ピクセル左からバックグラウンド レンダリングを開始するか [次のように呼びます ExtTextOut( hdc, r.left, r.top, ETO_OPAQUE, &r, &ch, 1, NULL )
。 Windows 7 のビットマップ フォント -- しかし、Windows 7 では固定幅の True Type フォントでは正しく動作しなくなりました。
私が何をする必要があるのか 理解していない人のために、方眼紙に正方形ごとに1文字を書くことを想像してみてください. すべての正方形は同じフォントを使用していますが、前景色や背景色が異なる場合があります。テキストの配置を使用しTA_TOP|TA_LEFT
ます。これは最も単純で、一貫して適用される配置は固定幅フォントでも機能するはずだからです。
私が見ているのは、ExtTextOut が、RECT *
パラメーターで指定したよりも大きな背景の四角形を放出していることです。私が提供している四角形は、報告されたフォントのサイズから作成されているため、これは決して起こらないはずです。また、Windows XP 以前では発生せず、Windows 7 のビットマップ (つまり .FON) フォントでは発生しません。また。しかし、これは Windows 7 の固定幅 TrueType フォントで常に発生します。これは、Windows 2000、Windows XP、および Windows 7 (32 & 64) で実行されているまったく同じ EXECUTABLE で発生します。Windows 7 にはバグがあると簡単に言いたいのですが、私は、Windows でのフォント処理について私が立てたいくつかの基本的な仮定が、もはや真実ではないと信じる傾向があります (Windows 用のソフトウェアを 20 年間作成した後)。
しかし、それが何であるかを発見する方法や場所がわかりません! 助けてください!
--- 修正 ---
興味のある人のために、私はバグと考えているものを回避することができました-反対のドキュメントを見つけるまで。私の回避策は、ライブラリに 2 つの変更を加えることです。
GetTextExtentPoint32()
からのデータではなく、「X」から返されたサイズを使用しTEXTMETRICS
ます。- すべての呼び出しに
ETO_CLIPPING
フラグを含めます。ExtTextOut()
以前は、tmHeight+tmExternalLeading
文書化されているように、連続するテキスト行の上部の間のピクセル数に使用していました。)から返される size.cy の値GetTextExtentPoint32(
は同じではなく、より正確に見えることがわかりました。私が見つけた最悪の例は、OCRB True Type フォントでした。作成した OCRB フォントのデバッガーで見たものを次に示します (システム フォント選択ダイアログを使用)。
ocrbtm.tmHeight = 11
ocrbtm.tmExternalLeading = 7
ocrbsize.cy = 11
そのため、まだ発見していない何らかの理由で、Windows は OCRB フォントに定義された外部先行値を無視しています。TM の代わりにサイズの値を使用すると、きれいできちんとした密集したテキストが得られます。これはまさに私が望んでいたことです。
四角形を 1 文字の寸法に正確に設定し、背景を塗りつぶす (そして前のセルの内容を上書きする) ために使用しているため、このETO_CLIPPING
フラグは必要ありません。ETO_OPAQUE
サイズ、テキスト メトリック、または ABC 幅のいずれかが示します。少なくとも、これまでに見つけたすべてのドキュメントに基づいて、これは真実です。
HEIGHTの問題は長い間存在していたと思いますが、Windows 7でソフトウェアを実行するまで残りは不要でした.これを私の質問に追加して、私が明らかに理解していないことを誰かが説明できるかどうかを確認します.
-- 修正 2 --
1: 私が見つけることができるすべてのドキュメントはtmHeight+tmExternalLeading
、単一行のテキストを生成する必要があると述べています。限目。しかし、それは常に正しいとは限らず、Windows が によって返されることがあるさまざまな値をどのように決定するかを示すドキュメントを見つけることができませんGetTextExtentPoint32()
。
2: Win7 (Vista の可能性あり) では、本来ExtTextOut
よりも少し多くの背景を塗りつぶし始めました (右側にいくつかの余分なピクセルを追加することにより)。ただし、True Type フォントが選択されている場合のみです。四角形が文字の予想サイズの2 倍(両方の寸法) であってもこれを行います。 :1 の倍率であり、これはバグのようです。ビットマップ (.FON) フォントではなく真のタイプにのみ影響するという事実も、スケーリングを除外しているようです (存在しない限り) 。Windows はテキストの一部だけでなく、すべてのテキストをスケーリングしようとするためです。また、[カスタム DPI 設定] ダイアログに [Windows XP スタイルの DPI スケーリングを使用する] という灰色の (チェックされている) 設定があります。最後に、この問題全体は、Aero またはその他の Win7 ネイティブ テーマではなく、Windows クラシック テーマで実行した結果である可能性があります。
-- 修正 3 --
SetProcessDPIAware() を呼び出すだけでは、私が抱えている問題には影響しません。私の問題は 100% DPI 設定 (スケール 1:1) で発生するため、問題がDPI 関連である場合、DPI 仮想化のバグを発見したに違いありません。これは、Microsoft がこの機能を次のように説明しているためです。
この機能は、あたかも 96 DPI で実行されているかのように、"仮想化された" システム メトリックと UI 要素をアプリケーションに提供することによって機能します。その後、アプリケーションは 96 DPI のオフスクリーン サーフェスにレンダリングされ、Desktop Windows Manager は結果のアプリケーション ウィンドウを DPI 設定に一致するようにスケーリングします。
私の設定はすべて 100% のスケーリングであることを示しており、カスタム設定ボックスを見ると、それが 96 DPI であることを明確に示しています。つまり、96 DPI から 96 DPI への DPI 仮想化が固定幅 True Type フォントで機能しない場合、Windows に問題がありますよね? または、DPI バーチャライザーを正しく動作させるために呼び出す (または呼び出しを停止する) 必要がある関数はありますか?
想定されるスケーリングの問題が、当初考えていたほど実際にフォントのサイズと関係があるかどうかはまだ確信が持てません。これは、テキスト文字が出力されるのではなく、背景の四角形が塗りつぶされるという問題が発生しているためです。ExtTextOut()
フォントが True Type の場合、背景の四角形が少し拡大されます。また、Windows クラシック テーマまたは標準の Windows Aero テーマのどちらを使用しても、この問題が発生することも確認しました。次に、他の人が実験できるように、単純化された例を作成します。
-- 修正 4 --
私が見ているもの (および私が行っていること) を示す最小限のデモ プログラムを作成しました。Visual Studio 2010 プロジェクト/ソースは、http: //www.svalli.com/files/fwtt.7z からダウンロードできます。 -- マルウェアを拡散する危険を冒したくないので、意図的に実行可能ファイルを含めませんでした。プログラムは、固定幅フォントを選択し、2 つの 5x5 文字グリッドをクライアント領域に書き込みます。1 つはサイズを使用して作成され、もう 1 つはGetTextExtentPoint32
サイズを使用して作成されます。TEXTMETRIC
Microsoft によって文書化されたサイズ。グリッドは黒と白の市松模様で、赤地に黄色の文字が最後に中央に書かれ、オーバーラップ効果を示しています (はっきりと表示するには、ズーム ユーティリティが必要な場合があります)。プログラムは、すぐ下の 5 つの X で始まる文字列も描画します。同じ左オフセットから始まるグリッドは、個々の文字を配置する方法の比較として使用されます (文字列を一致させます)。メニューでは、クリッピングのオン/オフを切り替えたりExtTextOut
、他のフォントを選択したりできます。また、起動時にdpiaware
プログラムを呼び出すコマンド ライン オプション (大文字と小文字を区別)SetProcessDPIAware()
もあり、その呼び出しの効果も評価できます。
これを作成してから、正しい背景の四角形を塗りつぶしていることを学びましたExtTextOut
が、不透明な背景でレンダリングされているキャラクターは、本来よりも幅が広く、描画を開始するように指示された場所から開始することさえできない可能性がありますExtTextOut
! ExtTextOut
最終的に文字間隔が文字列全体をレンダリングしたときに得られるものと一致するため、「あるべき」と言いました。オーバーラップは、指定された長方形の片側または両側にあるようです。たとえば、OCRB は文字セルの左側と右側の両方に余分なピクセルを追加しますが、私が確認した他の True Type フォントは右側に 2 ピクセルを追加します。縁。
私は本当にこれを「正しい」方法でやりたいと思っていますが、私が間違っていることや欠けていることを示すドキュメントが見つかりません。おそらく、100% 以外の縮尺での DPI Aware の何かが欠けていると思いますが、それ以外の場合は困惑しています。
-- 修正 5 --
少し困惑が少ない... 問題は ClearType が原因です。ClearType をオフにすると、すべてのフォントが再び機能するようになりました。XP で ClearType をオンにすると、同じ問題が発生します。どうやら ClearType は (誰かがそれを検出する方法を教えてくれるまで) 静かに (誰かがそれを検出する方法を教えてくれるまで) 文字を水平方向に数ピクセル引き延ばすことができるようです。
この問題を回避する唯一の方法はクリッピングですか?
-- 修正 6 --
上記のクリッピングの質問に対する部分的な回答: 新しいフォントを作成するとき、次のことを行います (疑似コードで):
CreateFontIndirect
SelectFont
GetTextMetrics
if( (tmPitchAndFamily & TMPF_TRUETYPE) && Win6.x or above )
if( SystemParametersInfo( SPI_GETCLEARTYPE ) )
lfQuality = NONANTIALIASED_QUALITY
DeleteObject( font )
CreateFontIndirect
クリッピングを有効にしなくても、これはほとんどの場合、使用しているフォント サイズで機能しますが、文字セルの右 (または左) に余分なピクセルをレンダリングするものをいくつか見つけました。幸いなことに、これらはインターネット上で見つかったフリー フォントのように見えるため、全体的な品質はプロのフォント ファウンドリの基準を下回っている可能性があります。
誰かがより良い答えを見つけることができれば、私は本当に、本当にそれを聞くのが大好きです! それまでは、これでいいと思います。ここまで読んでくれてありがとう!