ダイアログ単位って何?

[戻る]
シャノン 2003/12/28(日) 14:33:12
長文失礼します。

VC++ のダイアログエディタを表示すると、ウィンドウ右下にダイアログやコントロール
のサイズが表示されます。
が、このサイズを見ながら縦と横の数字を同じにすると、コントロールは正方形になら
ず、やや縦長にやってしまいます。
試しに 200 * 200 のビットマップを貼り付けた PictureBox のサイズを見ると、117 * 
136 と表示されました。なお、この PictureBox に対して GetClientRect を実行する
と、ちゃんと 200 * 200 という値を取得できます。

この 117 * 136 と 200 * 200 を相互変換するにはどうしたらよいのでしょうか?

調べてみた結果、これはダイアログ単位というものだとわかりました。
MapDialogRect で変換できるそうなので、こんなコードを書いてみると

RECT rect = { 0, 0, 117, 136 };
MapDialogRect( &rect );

CString str;
str.Format( "%d, %d", ( LONG )rect.right, ( LONG )rect.bottom );
AfxMessageBox( str );

結果は 205 * 238。これは計算誤差の範囲なのでしょうか?
ちなみにフォントは MS Shell Dlg(9)、UseSystemFont は TRUE です。

ついでに、GetDialogBaseUnits のページに載っている変換方法を使って

LONG l = GetDialogBaseUnits();
LONG baseX = LOWORD( l );
LONG baseY = HIWORD( l );

RECT rect;
m_ctlPict.GetClientRect( &rect );

double X = ( double )rect.bottom * 4.0 / ( double )baseX;
double Y = ( double )rect.right * 8.0 / ( double )baseY;

// 以下表示部分省略

こんなこともやってみました。結果は 100 * 88 。全然違う数字になりました。

さらに、「GetDialogBaseUnits はポイント単位ではあるまいか?」という疑惑を抱い
て、ピクセル‐ポイント変換を考慮したこんな式も

    LONG l = GetDialogBaseUnits();
    LONG baseX = LOWORD( l );
    LONG baseY = HIWORD( l );

    RECT rect;
    m_ctlPict.GetClientRect( &rect );

    CWindowDC cdc( this );
    double X = ( double )rect.right * ( double )cdc.GetDeviceCaps( 
LOGPIXELSX ) / 18.0 / baseX;
    double Y = ( double )rect.bottom * ( double )cdc.GetDeviceCaps( 
LOGPIXELSY ) / 9.0 / baseY;

// 表示部分省略

結果は 133 * 118 。数字は 117 * 136 にかなり近くなりましたが、幅と高さが逆で
す。
ちなみに 18.0 ってのは 72 / 4、9.0 は 72 / 8 です。

一体どうすれば、ピクセル‐ダイアログ単位の相互変換が可能なのでしょうか?

ネテロ 2003/12/28(日) 15:26:19
>RECT rect = { 0, 0, 117, 136 };
この値って間違ってませんか?
MapDialogRectを使えば正常に変換されるはず。
1ポイントくらいの誤差はあるようだけど。

シャノン 2003/12/28(日) 16:14:26
一応、手順を確認しておきますと
1.MFC AppWizard でダイアログベースアプリを作りました。
2.リソースエディタでメインダイアログを開き、ピクチャボックスを貼り付けました。
  サイズを調整し、200 * 200 ピクセルにしました。
  これについては、GetClientRect で 200 * 200 と取得できるのを確認済みです。
3.このピクチャボックスを選択すると、VC++ のウィンドウの右下に 117 * 136 と表示
されます。これが、MapDialogRect の解説で言うところのダイアログボックス単位なん
ですよね?
4.で、

  RECT rect = { 0, 0, 117, 136 };
  MapDialogRect( &rect );

  というわけなんですが、間違えてますでしょうか?
  ちなみにこの結果は、上にも書いたとおり 205 * 238 で、期待する結果である 200 
* 200 とはかけ離れた値になってしまっている、というわけです。

ネテロ 2003/12/28(日) 16:16:46
追記:
ダイアログボックステンプレートで DS_SETFONT スタイルが指定されているときは、
指定されたフォントの平均文字幅と高さがベース単位になります。

>ちなみにフォントは MS Shell Dlg(9)、UseSystemFont は TRUE です。
これってどういう意味でしょう?
ダイアログのプロパティでフォントを設定してるのですよね。
プログラムでフォントを変えてる?

シャノン 2003/12/28(日) 16:17:10
連続投稿失礼します。
要するに何がしたいのかといいますと
「(例えば)200 * 200 ピクセルのピクチャボックスをダイアログ上に配置する場合、
ウィンドウ右下に表示される寸法をいくつにあわせればいいの?」
ということなんです。

シャノン 2003/12/28(日) 16:19:28
ダイアログのプロパティで、Use System Font を TRUE にすると、Font は自動的に MS 
Shell Dlg(8) に固定されます。
プロパティからフォントを変えると、Use System Font は FALSE になります。
プログラム的には一切フォントをいじっていません。

ネテロ 2003/12/28(日) 16:28:11
>「(例えば)200 * 200 ピクセルのピクチャボックスをダイアログ上に配置する場合、
>ウィンドウ右下に表示される寸法をいくつにあわせればいいの?」
リソースエディタで200 * 200のビットマップを作成して、
それを貼り付けたピクチャボックスで選択すればいいと思う。
その場合に表示される右下の値でMapDialogRectすれば
ちゃんと200 * 200になるはず。
一度やってしまえは変換値がわかるので次からは計算で出せばよいと思う。

シャノン 2003/12/28(日) 16:37:22
> リソースエディタで200 * 200のビットマップを作成して、
> それを貼り付けたピクチャボックスで選択すればいいと思う。
まさにそうやりましたとも。

> ちゃんと200 * 200になるはず。
なってないから困ってるんですってば。
205 * 238 が返って来ちゃうんです。
205 はともかく、238 は計算誤差では済ませられないと思います。

ネテロ 2003/12/28(日) 16:42:54
>なってないから困ってるんですってば。
環境は?
我が輩はVC++6sp5のWinNT4だけど。

シャノン 2003/12/28(日) 16:59:37
すいません、それを一番最初に書くべきでしたね
VC++.NET 2003 の XP Pro SP1 です

シャノン 2003/12/28(日) 17:20:55
すいません、こちらのミスだったようです。
原因はさっぱりわかりませんが、プロジェクトを一から作り直したらどういうわけか 
MapDialogRect が正常に機能するようになりました。

以前は、右下の値も何度確認しても 117, 136 だったのですが、作り直したら 114, 
133 になっていて、MapDialogRect を通すと 200, 200 になります。

が、未だに本題である
>「(例えば)200 * 200 ピクセルのピクチャボックスをダイアログ上に配置する場合、
>ウィンドウ右下に表示される寸法をいくつにあわせればいいの?」
はわからないため、未解決とさせていただきます。
以前ですが、学校の課題でビットマップを動的に表示するものがあり、それには
> リソースエディタで200 * 200のビットマップを作成して、
> それを貼り付けたピクチャボックスで選択すればいいと思う。
これは適用できませんので。
どうにかピクセルから DLU を算出したいところです。

ネテロ 2003/12/28(日) 17:43:04
ダイアログフォントを変えないなら変換係数が固定だと思うので、
dialogunitX = (pixelX * 4) / baseunitX 
dialogunitY = (pixelY * 8) / baseunitY 
で算出できると思います。
ベースの値は計算で出ますからね。

フォントを変えるなら
指定されたフォントの平均文字幅と高さがベース単位になります。

渋木宏明(ひどり) [E-Mail] [HomePage] 2003/12/28(日) 21:20:43
>>「(例えば)200 * 200 ピクセルのピクチャボックスをダイアログ上に配置する場
合、
>>ウィンドウ右下に表示される寸法をいくつにあわせればいいの?」
>はわからないため、未解決とさせていただきます。

確実に 200x200 ピクセルにしたいなら、OnInitDialog() とかで SetWindowPos() する
とか。

ダイアログリソース上で頑張っても、画面のプロパティで「大きいフォント」とかやら
れたりするとNGかも。

シャノン 2003/12/29(月) 14:31:27
[[解決]]
> ダイアログフォントを変えないなら変換係数が固定だと思うので、
> dialogunitX = (pixelX * 4) / baseunitX 
> dialogunitY = (pixelY * 8) / baseunitY 
> で算出できると思います。
> ベースの値は計算で出ますからね。

この計算式、というか GetDialogBaseUnits はフォントが「System」の時にしか効かな
いんですね。
ダイアログのプロパティで「Use System Font」を TRUE にするとフォントは System で
はなく MS UI Gothic になってしまうようで…

> フォントを変えるなら
> 指定されたフォントの平均文字幅と高さがベース単位になります。

これをどうにか計算してやればいいんでしょうが…面倒ですな。
MapDialogRect の逆、フォントを考慮してピクセル→ダイアログ単位変換をしてくれる
関数があればいいんですが…。

> 確実に 200x200 ピクセルにしたいなら、OnInitDialog() とかで SetWindowPos() す
るとか。
> ダイアログリソース上で頑張っても、画面のプロパティで「大きいフォント」とかや
られたりするとNGかも。

デザイン時にはムリってことですかね。
とりあえずこの話題は一旦解決にしておいて、フォントを変えた場合でもベース単位を
正常に取得する方法を模索してみようと思います。

ありがとうございました。

古いスレッドには追加発言できません。