« 時間のかかる処理のタイムアウト | トップページ | Unicodeと双方向テキスト »

2007年6月 1日 (金)

GetCharacterPlacementとカーソル配置

うーん。ブログの更新が随分とあいてしまった。そういえば、GYAOで無料配信をしているスターゲートシリーズがおもしろい。続きをみたいところだけど、GYAOで続きが配信されるか疑わしい。なんか、最初のエピソードだけ流して興味あったら、レンタルするなりしなさいってスタンスのような気がする。

気を取り直して今回は、カーソル(キャレット)の配置。Windowsの標準コントロールであるEditコントロールみたいな機能を自前で実装するとなると、テキストの表示にはExtTextOutなどを使うとして、カーソルの位置をどうやって決めるかちょっと考えさせられる。以前、取り上げた、GetTextExtentExPoint、GetTextExtentPoint32やGetCharWidth32でできないことはないかもしれない。ちなみに、MSDNのドキュメントにも書いてあるように、文字列の幅を求めるのに、GetCharWidth32で個々の文字の幅を求めて、その和をとるのは、正確ではない。なぜなら、デバイスによってはカーニング等が行われるからだ。

で、こんな時に便利そうなのがGetCharacterPlacementである。GetCharacterPlacementのGCP_RESULTS構造体のCaretPosフィールドにカーソル位置の情報が返される。この情報の示す位置にカーソルを配置すればよいのだ。

で、さっそく、CaretPosフィールドに返された位置に線を引いてみたのが下の図である。

Caretpos1_3

フォントはMS ゴシックである。上の図のように、CaretPosフィールドに返される位置にカーソルを配置すれば、問題なさそうである。

ちなみに、上の図は、テキストをExtTextOutのETO_GLYPH_INDEXなしで表示したものである。GetCharacterPlacementのドキュメントを見れば分かるように、このAPIで、グリフインデックスも取得できるので、グリフインデックスを取得し、ExtTextOutでETO_GLYPH_INDEX付きで表示しても問題なさそうである。下がETO_GLYPH_INDEX付きで表示したときの図である。

Caretpos2_1

問題なさそうである。しかし、ここでフォントをTahomaに変えてみよう。結果は下のようになる。

Caretpos3_1

カーソル位置がおもいっきりずれているのが分かるであろう。まず、文字化けを起こしているが、これは、Tahomaは欧文フォントなので、日本語で使用するグリフが含まれていない。また、ETO_GLYPH_INDEX付きでグリフインデックスを直接処理しているので、フォントリンクが働かないので文字化けが起きているのである。(つまり、ETO_GLYPH_INDEXなしの時にExtTextOutで自動で行われるフォントリンクのような機能は自前で実装する必要がある)。この文字化けは、ある程度想定?できた結果なのでスルーして次の問題に進んでみる。

次の問題とはカーソル位置がずれていることである。ううーん。このカーソル位置はいったい何の位置なのだろうか・・これは、ETO_GLYPH_INDEXなしでExtTextOutを呼び出した結果を重ねてみれば一目瞭然である。

Caretpos4_1

上の図をみれば、わかるようにCaretPosで返されるカーソル位置は常にフォントリンクの影響を受けるということらしい。まぁ、これはそういう仕様と割り切るしかない。

追記:どうやら、上の現象はWindowsXP上では、異なる結果になる模様です。汗汗。ちなみに、上の現象はWindows2000上。

« 時間のかかる処理のタイムアウト | トップページ | Unicodeと双方向テキスト »

Windows」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1497665/39651885

この記事へのトラックバック一覧です: GetCharacterPlacementとカーソル配置:

« 時間のかかる処理のタイムアウト | トップページ | Unicodeと双方向テキスト »

自作ソフトウェア

無料ブログはココログ

メモ