none
GetTextExtentPoint32関数で取得できるサイズはフォントの回転に依存するのでしょうか? RRS feed

  • 質問

  • GetTextExtentPoint32関数で、TrueTypeのプロポーショナルフォント(たとえばMS Pゴシック)で指定された文字列(半角カナを含む)のサイズを取得したいのですが、指定したデバイスコンテキストに対して、CreateFont関数の第3パラメータ(nEscapement)と第4パラメータ(nOrientation)ともに1800(180度回転)を指定した後では、0を指定した時とは異なるサイズが取得できてしまいます。

    900もしくは2700でも1800と同じサイズで取得されてしまいます。0のみ、他より少し小さいサイズになるようです。

    GetTextExtentPoint32関数は、文字送り方向の角度が0度であることを前提にしているとありますが、90度、180度、270度では正確なサイズは計算できないのでしょうか?それとも、回転を行うと実際の文字サイズも変わってしまうのでしょうか?
    • 編集済み ぽか。 2009年6月29日 10:05
    2009年6月29日 7:27

回答

  • Microsoftに以下のような内容で問い合わせてみました。(本当はもっとたくさん記述してあり、かなり省略しています)

      GetTextExtentPoint32関数は、文字送り方向の角度が0度であることを前提にしている
      とありますが、フォント回転と同期した90度、180度、270度では正確なサイズは計算で
      きないのでしょうか?それとも、回転を行うと(プロポーショナルの)文字間ピッチが
      変わってしまうものなのでしょうか?

    その結果、第1次として

      GetTextExtentPoint32関数は、文字送り方向 (Escapement) の角度が 0 度の場合のみ、正しい文字列のサイズが取得され、
      文字のベースラインの角度 (Orientation) については、任意の角度を設定することができます。

      従いまして、文字のベースラインの角度 (Orientation)の値にかかわらず、文字送り方向 (Escapement) の角度として
      0 度以外を指定した場合には、正しいサイズを返しません。
      本動作は、想定された動作となります。

    との回答を得ましたが、なんとなく的を外されているような感が否めません。

    次の問い合わせを行っており、次週明けには次の回答があると思いますが、まずは報告まで。

    • 回答としてマーク ぽか。 2009年7月15日 1:21
    2009年7月10日 8:43
  • 先程、マイクロソフトより正式な回答がありました。(部分的な抜粋です)

      GetTextExtentPoint32関数は、文字送り方向 (Escapement) の角度が 0 度の場合のみ、
      正しい文字列のサイズが計算されます。
      但し、0 度以外の角度につきましては、結果的にサイズ計算は行われ、
      なんらかの値を取得することが可能ではございますが、サポート対象外の動作となります。
      
      この点につきましては、以下の MSDN ライブラリにて公開されております技術情報にも記述
      がございます。
      0 度以外の場合に取得できる値は API として未定義であり、期待する値とならない可能性
      がございますので、この値をご使用いただくことは、推奨いたしかねます。
      
         GetTextExtentPoint32 Function
         http://msdn.microsoft.com/en-us/library/dd144938.aspx

    ということで、私の行っている方法すなわち、画面描画用のフォントと、実際の印字における
    回転にあわせた自動改行位置の計算用フォントを2つ用意して、それぞれで計算・描画を行う
    方法では、サポート対象外の動作ということになってしまいました。
    #ま、この方法で今のところは正常に動作しているので、このままでいこうと思っていますが。

    将来的には、テンポラリなBitmapオブジェクトを仲介したBitmapの回転で対応することにして、
    フォントの回転は0度のみで対応する方法に移行しようかとは思っています。
    #コスト対効果の面で、実現の可能性は低いですが・・・

    ミッヒーさんには、いろいろと相談に乗って頂き、本当に感謝しております。
    ありがとうございました。

    • 回答の候補に設定 ミッヒー 2009年7月14日 11:00
    • 回答としてマーク ぽか。 2009年7月15日 1:08
    2009年7月14日 7:32

すべての返信

  • 回答にはなっていませんが、参考までに。

    私は NONCLIENTMETRICS.lfSmCaptionFont を lfClipPrecision |= CLIP_LH_ANGLES 指定で 900 回転させて表示していますが、フォントのサイズは画面上では同一に見えます。また、LOGFONT として指定されるフォントのサイズも変更していません。ただ、lfEscapement と lfOrientation メンバを 900 にしただけです。

    ただし、GetTextExtentPoint32 関数は呼び出していませんので、内部のサイズが変わっているかは確認していませんが。

    唯一確認したのは、ExtTextOut 呼び出し時に回転無しのフォントに比べて、lfEscapement = 900、lfOrientation = 900 のフォント開始位置がずれる (この場合でいうと左側にずれる) という現象のみです。この部分に対しては本来、y であるべき数値を x として使用して望む位置に表示出来ています。

    また、回転させたフォントに対しては、DrawText、DrawTextEx も機能しないようです。

    おそらく、回転させたフォントに関しては、回転前の値を用いる事になるかと思います。

    なお、指定されたフォントのフェイスネーム、および lfHeight、lfWidth 値はどのような値になっているのでしょうか?
    • 編集済み ミッヒー 2009年6月29日 17:31 またしても誤記訂正
    2009年6月29日 17:08
  • ミッヒーさん、書き込みありがとうございます。

    あれからこちらでもいろいろと条件を変えてみて、発生する条件が少しわかってきましたので、ここに記載してみます。

    1)HeightとWidthはそれぞれ21で発生していましたが、22以上にすると再現しなくなりました。(フォントは「MS Pゴシック」)
    2)フォントを「MS P明朝」に変えると、回転による(0度と180度の)差分が多くなり、HeightとWidthを25にしても再現しました。
      (フォントにより、境界値がかわるようです)

    #フォントが極端に小さいからだとつっこまれそうですが。
    2009年6月30日 1:32
  • ぽか。 さん、すいません。環境に慣れる意味合いも込めて、VC++ 2005 で試してみたのですが、再現出来ません。

    おそらく私が、「プロポーショナルフォント」を理解していないせいだと思います。

    ので、CreateFont の第 9 引数 ( fdwCharSet ) 以降の引数をお教え下さい。

    差支えがなければ、GetTextExtentPoint32 に渡している文字列もお教え頂けると助かります。

    • 編集済み ミッヒー 2009年6月30日 6:08 回答者名誤記 (大変失礼を致しました)
    2009年6月30日 6:07
  • ミッヒーさん、書き込みありがとうございます。


    プログラムソースの抜粋から、必要な部分のみを抽出したコードを記載しておきます。
    (DCの接続やオブジェクトの廃棄処理などは割愛しております)


    #define FONTNAME_PMINCHO "MS P明朝"
    #define FONTNAME_PKAKU_GOTHIC "MS Pゴシック"

    CString szDispFontName;
    int nOrientation = 1800;
    int nEscapement  = 1800;
    int nWeight      = FW_EXTRABOLD;
    int nHeight      = 21;
    int nWidth       = 21;
    szDispFontName = FONTNAME_PKAKU_GOTHIC;

    CreateFont(nHeight, nWidth,
     nEscapement, nOrientation, nWeight, 0, 0, 0,
     SHIFTJIS_CHARSET,
     OUT_DEVICE_PRECIS,
     CLIP_DEFAULT_PRECIS | CLIP_LH_ANGLES,
     PROOF_QUALITY,
     FF_ROMAN | VARIABLE_PITCH,
     szDispFontName);


    ちなみに、GetTextExtentPoint32に引き渡している文字列は、以下です。

    成分:変性アルコール、水、香料、メトキシケイヒ酸エチルヘキシル、オキシベンゾン-3


    nOrientationとnEscapementの値によって、GetTextExtentPoint32で得られる文字列幅が、
    0000→593
    0900→600
    1800→598
    2700→600
    になります。(MS Pゴシックの場合)

    これが、MS P明朝の場合は、
    0000→605
    0900→614
    1800→611
    2700→614
    になります。


    わかりにくい説明で申し訳ありません。

    2009年6月30日 11:24
  • ぽか。さん、再びすいません。まだ再現出来ません。

    私の環境下で、MS Pゴシックを使った場合、

    0000 → 1414 × 21
    1800 → 1414 × 21

    になります。

    最初の回答に

    #フォントが極端に小さいからだとつっこまれそうですが。
    と書いておられますが、高さ 21 のフォントはそこそこ大きいフォントだと思います。

    ::GetStockObject(SYSTEM_FONT)

    としてシステムフォントを引っ張ってきましたが、高さは 18 でしたし。

    MBCS と UNICODE に起因する問題かと思って確認してみましたが、結果は同じでした。

    ただ、::GetTextExtentPoint32 関数を呼び出す前に、フォントを設定しなかった場合、幅が 435 になりました。

    なかなか解決に結び付かず、たびたび申し訳ありませんが、DC はどのように取得しているのか、DC のマップ モードは何になっているのか、そして使用している OS と開発ツールをお教え下さい。

    追記
    (DCの接続やオブジェクトの廃棄処理などは割愛しております)
    ひょっとして、印刷用の DC ですか?
    2009年6月30日 12:49
  • ミッヒーさん、書き込みありがとうございます。

    こちらこそ、お忙しいところお手数をお掛けして申し訳ありません。
    こちらの開発環境に依存するとは思ってもみなかったので、記載が漏れてしまいました。

    Windows2000の元で、VB6.0とVC++6.0で開発しております。
    VBでPictureオブジェクトを配し、描画部分のみをVC++で設計したDLLで賄っております。

    VBからはPictureBoxのプロパティのうち、hdc,ScaleWidth,ScaleHeightをDLLに渡しており、
    それぞれ
    HDC h;
    CSize winSize;
    としてDLL内部に取り込んでおります。

    エラー処理等は割愛してますが、ほぼ以下のコードで作成したmemDCを使用しております。

    CDC hdc;
    CDC memDC;
    CBitmap memBitmap;
    CBitmap* oldBitmap;
    hdc.Attach(h);
    memDC.CreateCompatibleDC(&hdc);
    memBitmap.CreateCompatibleBitmap(&hdc,winSize.cx, winSize.cy);
    oldBitmap = (CBitmap*)memDC.SelectObject(&memBitmap);


    ミッヒーさんが
         #高さ 21 のフォントはそこそこ大きいフォントだと思います。
    と書いておられますが、単位が違うのでしょうか、ドット単位なので、TrueTypeフォントの21ドットは、かなり小さいと思います。
    これ以上小さくすると、文字がつぶれそうです。

    2009年7月1日 1:23
  • ぽか。さん、VC++ 6.0 SP 5 (わけあって SP 6 は入れていません) で確認してみましたが、やはり VC++ 2005 と同じ値になってしまいました。

    私の環境は WinXP SP 3 なので、Win2000 での確認が取れません。
    Windows2000の元で、VB6.0とVC++6.0で開発しております。
    VBでPictureオブジェクトを配し、描画部分のみをVC++で設計したDLLで賄っております。
    なるほど。そういう環境下なのですね。VB は 5.0 時代に使っていましたが、今は全く使っていません。インストールもしていないので、確認の為にインストール・・・。すいません、今は VS 6.0、2005、2008 をインストールしているので、VS の基本として古いものからインストールしていく、という観点から行くと、VB 2008 のインストールになるかと思いますが、環境が変わって不具合が出る可能性を考えると躊躇してしまいます。

    ので、ここからは想像で回答させて頂きます。

    通常、VC++ でマッピングモードの指定をしない限り、MM_TEXT モードになります。これは 1 ピクセルが 1 論理値と同じ値になります。よって、高さ 21 のフォントはピクセル上でも 21 の高さになります。

    ただ、その描画部分は VB から呼び出されていますよね。VB は基本的にダイアログベースなので、VC++ 側の描画も通常のウィンドウベースではなく、ダイアログへの描画になるかと思います。通常の VC++ アプリケーションではダイアログへの描画であっても、OnPaint ハンドラでフォント指定、描画の手順を踏めば、ウィンドウに描画した場合と同様のものが描画され、また ::GetTextExtentPoint32 関数の戻り値も同じです。(VC++ 2005 で確認しました。)

    私は VB から呼び出される VC++ DLL を書いた経験がなく、また使った経験もないのですが、VB から渡された HDC ってダイアログユニット値を使う前提になっているのではないでしょうか?

    この想像があっていると仮定して、の話ですが、VB 側から HDC ではなく、HWND を渡して、::GetDC(HWND) とするとどうなるでしょうか?
    (当然、DC を使い終えたら、ReleaseDC を呼び出す必要があります。)

    ところで、実行中の VB アプリを (VC++ DLL での描画込み) を Alt + Print Scrn でアクティブアプリケーションの画面キャプチャをして、ペイントソフトで見るか、実行中の VB アプリを VC++ 6.0 付属の ZoomIn.exe で見るとフォントの高さは幾つになっていますか?

    なお、聞きそびれていましたが、、::GetTextExtentPoint32 で取得した値をどうするのでしょうか?
    (質問ばかりになってしまいました。すいません。)
    2009年7月1日 2:40
  • ミッヒーさん、書き込みありがとうございます。

    本当にいろいろとありがとうございます。

    開発環境はWin2000ですが、WinXPでも同様の現象は発生しています。

       #ただ、その描画部分は VB から呼び出されていますよね。

    描画部分は全てVC++にて行っております。VBはコントロールの提供とイベントのハンドリングしか行っておりません。

       #VB から渡された HDC ってダイアログユニット値を使う前提になっているのではないでしょうか?

    この意味がよくわからないです。不勉強で申し訳ありません。

       #HDC ではなく、HWND を渡して、::GetDC(HWND) とするとどうなるでしょうか?

    便宜上簡単なコードを記載しましたが、実際はもっと複雑なので、インターフェース部分を変更すると、他の部分への影響が大きすぎて、動作しなくなると思います。申し訳ありません。

       #画面キャプチャをして、ペイントソフトで見るとフォントの高さは幾つになっていますか?

    キャプチャしてペイントでみました。
    フォントの幅、高さは同じですが、文字間ピッチが数箇所、ほぼ1ドットずれている箇所があり、
    そのために文字列全体としての幅がかわっているようです。

       #::GetTextExtentPoint32 で取得した値をどうするのでしょうか?

    領域を指定して、長い文字列を自動改行させるのですが、その改行位置の検出に使っています。

    そろそろMicrosoftのプレミアサポート行きですかね。何かわかりましたら、ここで報告させていただきます。

    2009年7月1日 4:29
  • ぽか。さん、力不足ですいません。

    いや、それより説明力不足の方が大きいかもしれません。

    VC++ では DC の使用する値がマップ モードによってピクセル値へと変換されます。例えば、マップ モードが MM_HIMETRIC だった場合、原点は左下となり、各数値は 0.01 mm 単位の値として計算され、最終的にピクセル値となって画面上での値になります。

    VB は基本的にダイアログベースなので、ウィンドウに設定されたダイアログユニット値を使用する DC になっているのではないか、と想像しました。その想像下での話で、フォントの高さ 21 もダイアログユニット値に変換され、画面上では小さくなっているのではないか、と考えました。

    ぽか。さんが教えて下さったフォント、表示文字列から私が VC++ 上で試した ::GetTextExtentPoint32 が返した値と、ぽか。さんが示して下さった値とがあまりにも違いすぎたので、DC のマッピングモード、というより値をピクセル値に変換する部分が何か違う値になっているのでは、と思いました。

    ただ、画面上でフォントの高さが 21 となっているようですので、違ったみたいですね・・・。

    そうなると、ぽか。さんの示して下さった値、

    0000→593 
    が気になる所ですが、これは改行した後の値、という認識で良かったのでしょうか?

    何はともあれ、上手く行くようお祈り致します。
    2009年7月1日 4:54
  • ミッヒーさん、書き込みありがとうございます。

    いえいえ、こちらこそお手数をお掛けしてしまい、恐縮です。
    マイクロソフトのプレミアサポートに問い合わせようと思います。


    さすがに文章だけではイメージがつかめないかと思い、jpgですがWebフォトにUPしました。(BMPはだめみたいだったので)
    アプリケーションの画面コピーからの抜粋です。回転すると改行位置が異なる現象がわかりやすいように、同じ条件のユニットのコピーを180度回転させています。

    http://photos.yahoo.co.jp/ph/poka2000/vwp2?.tok=bcrAXXKBmJOfL52j&.dir=/c9a5&.dnm=b545.jpg&.src=ph
    (ここは2週間で自動削除されます)

    雰囲気だけでも伝われば。


    補足:
    1)593というのは改行後の値ではありません。参考として書いた文字列をGetTextExtentPoint32関数に通して得られたサイズ情報そのものです。
    2)21を指定しているにもかかわらず、画面上の実際の文字サイズ(高さ)は18でした。これは余白部分という意味と、奇数サイズを指定しても勝手に偶数サイズになってしまう制限からきているのかと思いますが。

    2009年7月1日 6:10
  • ぽか。さん、画像確認しました。

    確かに 0 度と 180 度の改行位置がずれてますね。

    ただ、どう見ても高さ 21、幅 21 のフォントではありませんね・・・。

    有償のプレミアサポートに問い合わせる前に後 2 点だけ確認をお願いできますか?

    593というのは改行後の値ではありません。参考として書いた文字列をGetTextExtentPoint32関数に通して得られたサイズ情報そのものです。
    との事ですが、DLL 内でフォントを作成後、フォントの LOGFONT を取得した場合、幅と高さ、そしてフェイスネームはどうなっていますか?

    後、インターフェースとして使われている VB 側のフォントを DLL 側で使われている 0 度のフォントと同じものに出来ますか?
    2009年7月1日 6:31
  • ミッヒーさん、書き込みありがとうございます。

       #ただ、どう見ても高さ 21、幅 21 のフォントではありませんね・・・。

    いえ、ビットマップファイルを拡大してグリッド表示させ、全角文字を見た限りでは、ちゃんと18x18ドット文字になっていました。

    あと、お断りしておかないといけないのですが、CreateFont関数では、指定したサイズを超えない最大サイズが採用されるため、弊社アプリで奇数ドットの場合は+1していました。

       #DLL 内でフォントを作成後、フォントの LOGFONT を取得した場合、幅と高さ、そしてフェイスネームはどうなっていますか?

    フォント作成後にLOGFONTを取得してみました。結果は、
    幅:0(プロポーショナルなので0を指定)
    高さ:22(指定も22)
    フェイスネーム:MS Pゴシック
    です。想定通りであり、特に問題があるとは思えませんでした。

    2009年7月1日 11:03
  • ぽか。さん、返信遅れ、申し訳ありませんでした。
    幅:0(プロポーショナルなので0を指定)
    高さ:22(指定も22)
    フェイスネーム:MS Pゴシック
    プロポーショナルフォントとは幅が 0 のフォントを指すのですか。私の知識不足でご迷惑をお掛けしました。

    という事は以前の
    int nHeight      = 21;
    int nWidth       = 21;
    はコピペの際に起こった間違いだった、という事ですか・・・。

    ともかく、教えて頂いたフォントのパラメーターと文字列を使って、::GetTextExtentPoint32 関数を呼び出した所、
    0000 → 636
    1800 → 641
    となりました。ようやくスタートラインに立てた、という所ですね。

    長々と申し訳ありませんでした。

    それで、本題の ::GetTextExtentPoint32 関数の戻り値を揃えるには、という話ですが・・・。

    MSDN の CreateFont 関数のドキュメントに気になる記述がありました。
    Windows NT/2000:GM_ADVANCED グラフィックモードでは、文字列の文字送りの方向(nEscapement パラメータ)を、文字列内の各文字の向き(nOrientation パラメータ)とは独立して指定できます。
    http://msdn.microsoft.com/ja-jp/library/cc428368.aspx より引用。

    試していませんが、SetGraphicsMode 関数を使って GM_ADVANCED モードにしてみる、というのはどうでしょうか?

    ただ、MATRIX が関連しそうな感じのドキュメントですが・・・。

    結局、プロポーショナルフォントって何?と私が質問しただけのやりとりになってしまい、申し訳ありませんでした。
    • 編集済み ミッヒー 2009年7月1日 15:50 ドキュメント不備?という勘違い部分の修正 本当にすいませんでした。
    2009年7月1日 14:38
  • ミッヒーさん、書き込みありがとうございます。

       #コピペの際に起こった間違いだった、という事ですか・・・。

    本当に申し訳ありません。関数レベルの引数にてWidthに値がセットされていた(アプリケーションからはポイント数で指定しています)ので、簡略化した時にそのまま書いてしまいましたが、関数の途中で、Proportionalの場合はWidth=0にしているのを見過ごしてしまいました。

       #ようやくスタートラインに立てた、という所ですね。

    回り道をさせてしまい、非常に恐縮です。
    でも、再現できたんですね。とても嬉しいです。
    ここの情報をもってMicrosoftに問い合わせると、再現性が高いという証拠になりそうです。

       #SetGraphicsMode 関数を使って GM_ADVANCED モードにしてみる、というのはどうでしょうか?

    はい、明日にでもTryしてみます。(ただし、他にも影響が出そうで少し怖いですが)

    2009年7月1日 15:51
  • ぽか。さん、こちらこそ勘違いをしている事に気付かず、長々と失礼致しました。

    書き込みの後で思ったのですが、90 度毎の回転しか行わない、というのであれば、回転無しのフォントと、DIB を使って、ビットマップの画像を回転させる、という荒業もあるかな、等と思ったりもしました。

    ビットマップのビットを直接触った経験があるなら、上手く行くか判らない SetGraphicsMode 関数よりも確実だと思います。

    繰り返しになりますが、私の勘違いで、お手間を取らせてすいませんでした。今後はもっと慎重に書き込むよう心掛けます。

    2009年7月1日 16:18
  • ミッヒーさん、書き込みありがとうございます。

    早速、SetGraphicsMode関数を使ってGM_ADVANCEDモードにしてみました。

    http://photos.yahoo.co.jp/ph/poka2000/vwp2?.tok=bc1pnXKB5cWV.5IN&.dir=/c9a5&.dnm=3c2e.jpg&.src=ph
    (ここは2週間で自動削除されます)

    暴走したりはしませんでしたが、フォントの回転が無視され、描画方向のみが有効になってしまい、開始位置もめちゃくちゃになってしまいました。(使えませんね)

    GetTextExtentPoint32関数で得られる幅サイズも、(前回と同じ文字列で)
    0000→593(←これはGM_COMPATIBLEモードの時と同じ)
    1800→489
    となってしまいました。

       #回転無しのフォントと、DIB を使って、ビットマップの画像を回転させる、という荒業もあるかな、等と

    今更ですが、弊社アプリケーションはプリンタ出力とプレビュー表示を行っております。プリンタ出力は90度単位で回転がありますが、プレビュー表示はできる限りの正立表示を行っておりますので、印字と表示で回転方向が異なるといった特徴があります。

    問題点はプリンタ出力とプレビュー表示で改行位置が異なるということですので、実際のプレビュー描画のフォントサイズは問われておりません。

    本来でしたら、印字も表示も、同じ正立方向でビットマップ展開し、生成されたBMPを回転させる方法が一番いいのでしょうが、従来との互換性を考えると、印字結果が変わるような変更はできません。

    現時点での対処方法としては、画面描画用のフォントと、実際の印字における回転にあわせた自動改行位置の計算用フォントを2つ用意して、それぞれで計算・描画を行うといった方法で解決しております。

    回転を行うと改行位置が変わる理由が知りたくて、ここに投稿させて頂きました。


       #私の勘違いで、お手間を取らせてすいませんでした。今後はもっと慎重に書き込むよう心掛けます。

    いえいえ、とても参考になっております。本当にいろいろとありがとうございました。

    2009年7月2日 0:58
  • ぽか。さん、画像を確認させて頂きました。

    確かに SetGraphicsMode 関数は目的に沿うものではなかったようですね。
    回転を行うと改行位置が変わる理由が知りたくて、ここに投稿させて頂きました。
    長々と 2 日に渡り、逆に質問させて頂きましたが、お力になれず、残念です・・・。

    プレミアサポートに問い合わせても、「そういう仕様だから」という結論になりそうですし・・・。
    いえいえ、とても参考になっております。本当にいろいろとありがとうございました。
    こちらこそ、色々勉強させて頂きました。ありがとうございました。
    2009年7月2日 1:18
  • Microsoftに以下のような内容で問い合わせてみました。(本当はもっとたくさん記述してあり、かなり省略しています)

      GetTextExtentPoint32関数は、文字送り方向の角度が0度であることを前提にしている
      とありますが、フォント回転と同期した90度、180度、270度では正確なサイズは計算で
      きないのでしょうか?それとも、回転を行うと(プロポーショナルの)文字間ピッチが
      変わってしまうものなのでしょうか?

    その結果、第1次として

      GetTextExtentPoint32関数は、文字送り方向 (Escapement) の角度が 0 度の場合のみ、正しい文字列のサイズが取得され、
      文字のベースラインの角度 (Orientation) については、任意の角度を設定することができます。

      従いまして、文字のベースラインの角度 (Orientation)の値にかかわらず、文字送り方向 (Escapement) の角度として
      0 度以外を指定した場合には、正しいサイズを返しません。
      本動作は、想定された動作となります。

    との回答を得ましたが、なんとなく的を外されているような感が否めません。

    次の問い合わせを行っており、次週明けには次の回答があると思いますが、まずは報告まで。

    • 回答としてマーク ぽか。 2009年7月15日 1:21
    2009年7月10日 8:43
  • ぽか。さん、やっぱり、そういう仕様だから、という回答でしたか・・・。

    GetTextExtentPoint32 関数とは別の関数で代用できないか、調べて見ましたが、やはり、同じように 0 度と 180 度の文字列サイズは異なるようです。( DrawTextEx と GetTextExtentExPoint 関数で確認しました )

    そこで思ったのですが、180 度の回転の場合、文字列幅の計算が文字列の先頭ではなく、画面上で先頭になる左側から (文字列の後ろから) 計算が行われるのではないでしょうか?

    あくまで予想で何の根拠もありませんが、お役に立てば幸いです・・・。


    追記

    GetCharWindth32 関数と CharNext 関数を使って、文字列の先頭から調べてみましたが、結果は同じでした・・・。
    後、使えそうなのは GetCharacterPlacement 関数ぐらいでしょうか・・・。
    (もっとも、この関数は下位互換の為に残されているようですが)

    私には GetCharacterPlacement 関数の使い方がよく判らず、エラーになってしまいましたが・・・。

    参考になる書き込みを出来ず、非常に申し訳なく思っています・・・。
    • 編集済み ミッヒー 2009年7月10日 18:49 追記部分追加
    2009年7月10日 13:05
  • 先程、マイクロソフトより正式な回答がありました。(部分的な抜粋です)

      GetTextExtentPoint32関数は、文字送り方向 (Escapement) の角度が 0 度の場合のみ、
      正しい文字列のサイズが計算されます。
      但し、0 度以外の角度につきましては、結果的にサイズ計算は行われ、
      なんらかの値を取得することが可能ではございますが、サポート対象外の動作となります。
      
      この点につきましては、以下の MSDN ライブラリにて公開されております技術情報にも記述
      がございます。
      0 度以外の場合に取得できる値は API として未定義であり、期待する値とならない可能性
      がございますので、この値をご使用いただくことは、推奨いたしかねます。
      
         GetTextExtentPoint32 Function
         http://msdn.microsoft.com/en-us/library/dd144938.aspx

    ということで、私の行っている方法すなわち、画面描画用のフォントと、実際の印字における
    回転にあわせた自動改行位置の計算用フォントを2つ用意して、それぞれで計算・描画を行う
    方法では、サポート対象外の動作ということになってしまいました。
    #ま、この方法で今のところは正常に動作しているので、このままでいこうと思っていますが。

    将来的には、テンポラリなBitmapオブジェクトを仲介したBitmapの回転で対応することにして、
    フォントの回転は0度のみで対応する方法に移行しようかとは思っています。
    #コスト対効果の面で、実現の可能性は低いですが・・・

    ミッヒーさんには、いろいろと相談に乗って頂き、本当に感謝しております。
    ありがとうございました。

    • 回答の候補に設定 ミッヒー 2009年7月14日 11:00
    • 回答としてマーク ぽか。 2009年7月15日 1:08
    2009年7月14日 7:32