メッセージを使用してEM_FORMATRANGE
、リッチ テキスト コントロールの出力を任意のデバイス コンテキストにレンダリングしています。ただし、ビットマップにレンダリングする場合、ビットマップのデバイス コンテキストの 1 インチあたりのドット数は、ディスプレイ デバイスの DPI (1 インチあたり 96 ドット) と同じです。これは、私がレンダリングしたいものよりもはるかに低いです。ユーザーがズームインできるように、はるかに高い DPI でレンダリングし、後で高 DPI プリンターで印刷することをお勧めします。
RTF コントロールがとを呼び出しGetDeviceCaps
て、デバイスの 1 インチあたりのピクセル数を取得していると思われます。次に、この DPI 値を 100% のズーム レベルで使用してドキュメントをレンダリングします。Windows ディスプレイ デバイスは、(コントロール パネルで設定されているように) システムで大きなフォントが使用されていて、アプリケーションが DPI 対応でない限り、常に 96 DPI の値を返します。LOGPIXELSX
LOGPIXELSY
インターネット上の多くの例では、 の出力をスケーリングすることを提案していますEM_FORMATRANGE
。これは、任意の DPI 解像度を実現できるようにするためです。ほとんどの例では、一般にSetMapMode
、SetWindowExtEx
、およびを使用しSetViewportExtEx
ます (例: http://social.msdn.microsoft.com/Forums/en-us/netfxbcl/thread/37fd1bfb-f07b-421d-9b5e-5f4492ffbbc3を参照)。これらの関数を使用して、リッチ テキスト コントロールのレンダリング出力をスケーリングできます。たとえば、400% のスケーリングを指定すると、リッチ テキスト コントロールが 5 ピクセル幅のものをレンダリングすると、実際には 20 ピクセル幅になります。
残念ながら、古い GDI 関数は浮動小数点数ではなく整数を使用します。たとえば、RTF コントロールが要素を (12.7, 15.3) ピクセルで描画する必要があると判断したとします。これは (13, 15) の位置に丸められます。これらの丸められた座標は GDI に渡され、GDI は で指定されたスケーリングを使用して画像を拡大しますSetMapMode
: 400% の例では、(13*4, 15*4) または (52, 60) になります。しかし、これは正確ではありません。要素は (12.7*4, 15.3*4) または (51, 61) に配置したほうがよいでしょう。最悪の部分は、場合によってはエラーが累積することです。
これが、単純なテキストをスケーリングするときにこの非常に目立つエラーの根本的な原因であると思います。
上記の例は、96 DPI ディスプレイ デバイス コンテキストを使用EM_FORMATRANGE
して 400% にスケーリングされた 8 ポイントの Segoe UI です。SetMapMode
テキストは 32 ポイントのサイズになりましたが、各文字間のスペースが大きすぎて不自然に見えます。
上記の例は、テキストを 8 ポイントの Segoe UI として入力し、ズーム コントロールを使用して 400% のズーム レベルに設定することによって、ワードパッドで作成されました。各文字間のスペースは正常に見えます。32 ポイントのフォントと 100% のズーム レベルでまったく同じ結果が得られます。
この問題を回避するために、次のことを試しました。試行したそれぞれの結果は、400% にスケーリングすると、同じように満足のいくものではありませんでした。
- など
SetWorldTransform
で行われるスケーリングの代わりに使用するスケーリング トランスフォーム セットを使用します。SetMapMode
SetWindowExtEx
- メタファイルのデバイス コンテキストを に渡し、
EM_FORMATRANGE
後でメタファイルをスケーリングします。 - メタファイルへのレンダリングと組み合わせてスケーリングを使用
SetMapMode
し、後でスケーリングせずにメタファイルを表示します。
問題は、リッチ エディット コントロールが最も近い整数に丸められ、96 DPI デバイスであると見なされるものにレンダリングされ、その場での変換を無視するという事実に帰着するため、結果は常に満足のいくものではないと思います。メタファイル形式を調べたところ、個々の文字位置が実際にはピクセルレベルの解像度でメタファイルに格納されていることがわかりました。これが、その時点までに丸めが既に行われているため、メタファイルのスケーリングが明らかに機能しなかった理由です。
この問題を回避する 2 つの実際の解決策を考えることができます。
GetDeviceCaps
異なる値を返すように、ユーザー指定の 1 インチあたりのドット数が大きいデバイス コンテキストを使用します。(注:一般的にDPIが高いため、プリンターデバイスの使用を提案する例もありますが、プリンターを持たず、オフスクリーンバッファーにレンダリングできるシステムでコードを動作させたいと考えています)。- リッチ エディット コントロールに、デバイス コンテキストの 1 インチあたりのドット数が によって報告されるドット数と異なると想定するように指示する方法
GetDeviceCaps
。
それ以外は、これらの丸め誤差の影響を受けやすいようです。
(1) 私が提案したソリューションのいずれかを実装する方法を知っている人、または (2) 正確な高 DPI 出力をバッファに入れるという私の目標を達成する方法について別の考えを持っている人はいますか?