none
NONCLIENTMETRICS と同じフォントをダイアログに設定するには? RRS feed

  • 質問

  • お世話になります。

    VC++ 6.0 MFC に関する質問です。

    タイトルの通り、NONCLIENTMETRICS の lfMenuFont をダイアログのフォントに設定したいのですが、上手く行きません。

    ダイアログは CDialog::InitModalIndirect で作成しています。

    今の環境では、NONCLIENTMETRICS の lfMenuFont.lfHeight は -11 となっています。

    この値を素直に WORD へ変換すると、ダイアログのフォントは lfHeight = 14 となってしまいます。
    lfMenuFont.lfHeight に - を付けて、11 を設定すると、今度は -15 になってしまいます。

    ダイアログユニットに関する問題だとは思うのですが、解決方法が判りません。

    ご存知の方、よろしくお願いします。
    2009年6月14日 10:24

回答

  • このあたりに誤解はないでしょうか?

    http://support.microsoft.com/kb/32667/en-us
    Em=dpiY*point_size/72;  // where dpiY is dots per inch in Y direction

    • 回答としてマーク ミッヒー 2009年7月9日 13:41
    2009年6月15日 6:15
  • (NONCLIENTMETRIC.lfMenuFont.Height + TEXTMETRIC.tmInternalLeading) * dc.GetDeviceCaps(LOGPIXELSY) / 72

    とした所、画面上では同じサイズの様なフォントが表示される様になりました。
    CDialog::InitModalIndirect()ではDLGTEMPLATEに対してフォントサイズをポイントサイズで指定する必要があります。

    Em=dpiY*point_size/72; // where dpiY is dots per inch in Y direction

    この式からポイントサイズは、point_size=Em*72/dpiY です。

    lf.lfHeightが負の場合はEmですから、NONCLIENTMETRICS.lfMenuFont.lfHeightが -11 ならば、Em = 11 です。
    したがって、point_size=11*72/dc.GetDeciceCaps(LOGPIXELSY) となるのではないでしょうか?

    lfHeightは正の場合と負の場合で意味が異なるというあたりもまだ誤解があったりするのではないでしょうか?
    もう少し落ち着いて、http://support.microsoft.com/kb/32667/en-us をお読みになることをお勧めします。
    • 回答としてマーク ミッヒー 2009年6月16日 15:25
    2009年6月16日 13:47

すべての返信

  • このあたりに誤解はないでしょうか?

    http://support.microsoft.com/kb/32667/en-us
    Em=dpiY*point_size/72;  // where dpiY is dots per inch in Y direction

    • 回答としてマーク ミッヒー 2009年7月9日 13:41
    2009年6月15日 6:15
  • Atsushi777 さん、回答下さり、有難う御座います。

    Em=dpiY*point_size/72;  // where dpiY is dots per inch in Y direction
    の point_size 部分を間違えていたようです。

    By definition, the Em is equal to Cell Height minus Internal Leading.
    という記述に気付いていませんでした。

    そこで、

    (NONCLIENTMETRIC.lfMenuFont.Height + TEXTMETRIC.tmInternalLeading) * dc.GetDeviceCaps(LOGPIXELSY) / 72

    とした所、画面上では同じサイズの様なフォントが表示される様になりました。

    ただ、CDialog::OnInitDialog で LOGFONT を取得すると、15 になっています。
    画面上は -11 のメニューフォントと同じ大きさのように見えるのですが・・・。

    なお、単に

    NONCLIENTMETRIC.lfMenuFont.Height + TEXTMETRIC.tmInternalLeading

    をフォントサイズとして指定した所、同じく CDialog::OnInitDialog でのフォントの高さはマイナスが外れ、11 となり、画面上はもっと小さいフォントとなっています。

    今までフォントの高さはどのウィンドウでも同じだと思っていましたが、ダイアログの場合、ダイアログユニットによって、表示されるサイズが変わるのでしょうか?
    2009年6月15日 9:36
  • (NONCLIENTMETRIC.lfMenuFont.Height + TEXTMETRIC.tmInternalLeading) * dc.GetDeviceCaps(LOGPIXELSY) / 72

    とした所、画面上では同じサイズの様なフォントが表示される様になりました。
    CDialog::InitModalIndirect()ではDLGTEMPLATEに対してフォントサイズをポイントサイズで指定する必要があります。

    Em=dpiY*point_size/72; // where dpiY is dots per inch in Y direction

    この式からポイントサイズは、point_size=Em*72/dpiY です。

    lf.lfHeightが負の場合はEmですから、NONCLIENTMETRICS.lfMenuFont.lfHeightが -11 ならば、Em = 11 です。
    したがって、point_size=11*72/dc.GetDeciceCaps(LOGPIXELSY) となるのではないでしょうか?

    lfHeightは正の場合と負の場合で意味が異なるというあたりもまだ誤解があったりするのではないでしょうか?
    もう少し落ち着いて、http://support.microsoft.com/kb/32667/en-us をお読みになることをお勧めします。
    • 回答としてマーク ミッヒー 2009年6月16日 15:25
    2009年6月16日 13:47
  • 自己レスですが・・・。

    まずは Atsushi777 さんと私の回答をご覧になった皆様にお詫びを。

    Atsushi777 さんがご指摘された通り、ダイアログに関するフォントの設定に関しての誤解が多々あったようです。
    的外れの回答をしてしまい、ご迷惑をお掛けしました。

    改めて LOGFONT のドキュメントを見た所、フォントの高さがマイナスの場合、font mapper がデバイスユニットと cell height に対して有効な値に変換する、とありました。つまり、ダイアログユニットにより表示されるサイズが変わるのではなく、ダイアログに設定したフォントにより表示サイズが変わる、という事のようです。

    詳細は GetDialogBaseUnits 関数のドキュメントにありました。

    そして Atsushi777 さんが紹介して下さったサイトには cell Height は GetTextMetrics 関数の TEXTMETRIC.tmHeight と同じ値、となっていました。

    そこで、NONCLIENTMETRIC.lfMenuFont を使いフォントを作成、GetTextMetrics 関数を呼び出してみると、TEXTMETRIC.tmHeight = 13 となっていました。

    それで前回の回答
    (NONCLIENTMETRIC.lfMenuFont.Height + TEXTMETRIC.tmInternalLeading) * dc.GetDeviceCaps(LOGPIXELSY) / 72
    は間違いだという事に気付きました。そこで

    TEXTMETRIC.tmHeight * dc.GetDeviceCaps(LOGPIXELSY) / 72
    ( TEXTMETRIC.tmHeight = 13 )

    としたのですが、CDialog::OnInitDialog で LOGFONT した所、-23 となり、元のサイズより 2 周りは大きいフォントになってしまいました。

    そもそも SetSystemParameterInfo で取得した NONCLIENTMETRICS.lfMenuFont.lfHeight が -11 なのが謎です。-13 なら納得できるのですが。そこで、再び Atsushi777 さんが紹介して下さったサイトを確認すると、Cell Height は Ascent と Descent からなっている事が判り、NONCLIENTMETRIC.lfMenuFont を使って作成したフォントの TEXTMETRIC.tmAscent が 11 となっていました。

    そこで

    (NONCLIENTMETRIC.lfMenuFont.lfHeight + TEXTMETRIC.tmDescent) * dc.GetDeviceCaps(LOGPIXELSY) / 72

    とした所、
    (NONCLIENTMETRIC.lfMenuFont.Height + TEXTMETRIC.tmInternalLeading) * dc.GetDeviceCaps(LOGPIXELSY) / 72
    と同様の結果になりました。たまたま TEXTMETRIC の tmDescent と tmInternalLeading が共に 2 だったので同じ結果になるのは当然なんでしょうが・・・。

    ダイアログと、ウィンドウではフォントサイズが異なる、という部分は GetDialogBaseUnits 関数の説明で納得出来ましたが、NONCLIENTMETRIC.lfMenuFont.lfHeight がマイナスの場合、TEXTMETRIC の tmInternalLeading か tmDescent を足す、という方法でいいのでしょうか?
    2009年6月16日 15:15
  • Atsushi777 さん、また回答有難うございます。

    返信を書いている内に書き込まれたようで、気付きませんでした。
    lf.lfHeightが負の場合はEmですから、NONCLIENTMETRICS.lfMenuFont.lfHeightが -11 ならば、Em = 11 です。
    したがって、point_size=11*72/dc.GetDeciceCaps(LOGPIXELSY) となるのではないでしょうか?
    有難うございます、その通りでした。

    おかげで NONCLIENTMETRICS.lfMenuFont と同じフォント高さ -11 をダイアログに設定する事が出来ました。

    改めて、間違った回答へのお詫びと、Atsushi777 さんへのお礼を申し上げます。

    ありがとうございました。
    2009年6月16日 15:24