5

メッセージを使用してEM_FORMATRANGE、リッチ テキスト コントロールの出力を任意のデバイス コンテキストにレンダリングしています。ただし、ビットマップにレンダリングする場合、ビットマップのデバイス コンテキストの 1 インチあたりのドット数は、ディスプレイ デバイスの DPI (1 インチあたり 96 ドット) と同じです。これは、私がレンダリングしたいものよりもはるかに低いです。ユーザーがズームインできるように、はるかに高い DPI でレンダリングし、後で高 DPI プリンターで印刷することをお勧めします。

RTF コントロールがとを呼び出しGetDeviceCapsて、デバイスの 1 インチあたりのピクセル数を取得していると思われます。次に、この DPI 値を 100% のズーム レベルで使用してドキュメントをレンダリングします。Windows ディスプレイ デバイスは、(コントロール パネルで設定されているように) システムで大きなフォントが使用されていて、アプリケーションが DPI 対応でない限り、常に 96 DPI の値を返します。LOGPIXELSXLOGPIXELSY

インターネット上の多くの例では、 の出力をスケーリングすることを提案していますEM_FORMATRANGE。これは、任意の DPI 解像度を実現できるようにするためです。ほとんどの例では、一般にSetMapModeSetWindowExtEx、およびを使用し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) に配置したほうがよいでしょう。最悪の部分は、場合によってはエラーが累積することです。

これが、単純なテキストをスケーリングするときにこの非常に目立つエラーの根本的な原因であると思います。

EM_FORMATRANGE<code>を使用してレンダリングし、</code>SetMapMode でスケーリングします

上記の例は、96 DPI ディスプレイ デバイス コンテキストを使用EM_FORMATRANGEして 400% にスケーリングされた 8 ポイントの Segoe UI です。SetMapModeテキストは 32 ポイントのサイズになりましたが、各文字間のスペースが大きすぎて不自然に見えます。

ワードパッドで 400% にズーム

上記の例は、テキストを 8 ポイントの Segoe UI として入力し、ズーム コントロールを使用して 400% のズーム レベルに設定することによって、ワードパッドで作成されました。各文字間のスペースは正常に見えます。32 ポイントのフォントと 100% のズーム レベルでまったく同じ結果が得られます。

この問題を回避するために、次のことを試しました。試行したそれぞれの結果は、400% にスケーリングすると、同じように満足のいくものではありませんでした。

  • などSetWorldTransformで行われるスケーリングの代わりに使用するスケーリング トランスフォーム セットを使用します。SetMapModeSetWindowExtEx
  • メタファイルのデバイス コンテキストを に渡し、EM_FORMATRANGE後でメタファイルをスケーリングします。
  • メタファイルへのレンダリングと組み合わせてスケーリングを使用SetMapModeし、後でスケーリングせずにメタファイルを表示します。

問題は、リッチ エディット コントロールが最も近い整数に丸められ、96 DPI デバイスであると見なされるものにレンダリングされ、その場での変換を無視するという事実に帰着するため、結果は常に満足のいくものではないと思います。メタファイル形式を調べたところ、個々の文字位置が実際にはピクセルレベルの解像度でメタファイルに格納されていることがわかりました。これが、その時点までに丸めが既に行われているため、メタファイルのスケーリングが明らかに機能しなかった理由です。

この問題を回避する 2 つの実際の解決策を考えることができます。

  • GetDeviceCaps異なる値を返すように、ユーザー指定の 1 インチあたりのドット数が大きいデバイス コンテキストを使用します。(注:一般的にDPIが高いため、プリンターデバイスの使用を提案する例もありますが、プリンターを持たず、オフスクリーンバッファーにレンダリングできるシステムでコードを動作させたいと考えています)。
  • リッチ エディット コントロールに、デバイス コンテキストの 1 インチあたりのドット数が によって報告されるドット数と異なると想定するように指示する方法GetDeviceCaps

それ以外は、これらの丸め誤差の影響を受けやすいようです。

(1) 私が提案したソリューションのいずれかを実装する方法を知っている人、または (2) 正確な高 DPI 出力をバッファに入れるという私の目標を達成する方法について別の考えを持っている人はいますか?

4

4 に答える 4

0

EM_SETZOOMこのメッセージを使用して、リッチ エディット コントロールが出力自体をスケーリングできるようにしてください。

于 2012-10-10T20:21:13.060 に答える
0

私はまったく同じ問題を抱えています。

簡単な解決策は、テキストを 100% スケールのビットマップに描画してから、ビットマップを拡大縮小することです。それは最善の解決策ではありませんが、あなたにとってはうまくいくかもしれません。

より良い解決策は見つかりましたか?もしそうなら、ここでそれらを共有してください。

また、この問題は、テキストを 100% メタファイルに描画してから、メタファイルを画面に合わせて拡大縮小するときにも発生することに注意してください。スケーリング。

ローイ

于 2012-07-24T12:59:07.857 に答える
0

コントロール内のすべてのテキストのポイント サイズを 4 倍にして、コントロールを 4 倍の大きさのビットマップにレンダリングできます。

自分でコントロールを設定する場合、これは非常に簡単です。ユーザーが入力した任意のコンテンツをサポートする場合、より多くの作業が必要になり、テキスト以外のもの (埋め込みビットマップなど) を処理するために余分な労力が必要になります。

于 2012-09-28T20:30:34.853 に答える
0

同様の問題に2週間費やしました。WYSISWG 編集用にスケーラブルなリッチ エディットが必要でした。Windows のリッチ エディット コントロールは EM_FORMATRANGE によるスケーリングを正しくサポートしておらず、文字間隔はズーム レベル間で変化せず、フォント サイズは個別のフォント サイズ ステップでのみスケーリングされることがわかっています。

スケールの大きな違いは必要なかったので、ITextServices のウィンドウレス テキスト編集インターフェイスを使用して、固定解像度で内部ビットマップにレンダリングするという解決策に落ち着きました。次に、GDI+ を使用して、内部ビットマップを必要な画面サイズにリサンプリングし、トリリニア フィルタリングを行いました。結果は、スケールの違いが大きすぎない限り、スケーラブルなリッチ エディットを十分にエミュレートしており、私のニーズには十分でした。

さまざまなオプションを試した結果、Windows のリッチ エディット コントロールでは正確なスケーリングができないと確信しました。テキストをレンダリングする独自のコントロールを作成できます。ただし、異なるスタイルのテキストごとに個別の描画呼び出しが必要になります。また、テキストの強調表示、カーソルの配置、マウスとキーボード入力の処理、rtf テキストの解析など、すべての機能の豊富な編集ハンドルを処理する必要があります。この場合、おそらくサードパーティのコンポーネントを購入するのが最善でしょう (適切な無料のオープン ソース コンポーネントが見つかりませんでした)。誰かがそれを試してみたい場合に備えて、さまざまな API のテキスト レンダリングに関連する出発点を指摘します。

  • GDI - TextOut が文字間隔を正しく設定しない。GetCharacterPlacement と ExTextOut が必要です。また、スケーリングを自分で計算する必要があります。おそらくGDIを使いたくないでしょう
  • GDI+ - DrawString はスケーリングを正しく処理します。GDI+ は妥当なオプションです
  • DirectWrite - Vista プラットフォーム アップデート以降に限定したい場合、DirectWrite は Microsoft の最新のテキスト API です。

また、GDI と GDI+ の間でテキストのレンダリングがどのように異なるかを説明するリンクもここにあります。

http://windowsclient.net/articles/gdiptext.aspx

于 2012-10-10T19:42:46.757 に答える