下記環境で開発している者ですが、宜しくお願いいたします。
環境:
WinXP, Visual Studio.NET 2003
Dialogベースアプリケーション
DialogにCStaticを貼り付けて、そこにエラー内容を書いて本体プログラムからDialogを
Createをしようとしています。
この時、エラーメッセージの長さがマチマチなので、内容の長さによってCStaticの長さ
を調節し、合わせてダイアログの長さも調節したいと思っています。
尚、Dialog/CStaticのフォントに変更はありません。
ここで、このエラーのダイアログのメンバー関数で、下記の様に実装しました。
void EShellExecuteErrorDialog::ResizeStaticWindow( CString message )
{
HDC hDC = ::GetDC( m_StcError.GetSafeHwnd() );
CFont font;
font.CreatePointFont( 8, MS UI Gothic );
HGDIOBJ hFont_ = SelectObject(hDC, &font);
char szBuf[ 256 ];
strcpy( szBuf, message );
SIZE sz;
RECT rc;
rc.left = 0;
rc.right = 0;
GetTextExtentPoint32( hDC, szBuf, (int)strlen( szBuf ), &sz );
DrawText( hDC, szBuf, (int)strlen( szBuf ), &rc, DT_CALCRECT );
m_StcError.GetWindowRect( &rc );
ScreenToClient( &rc );
rc.right = rc.left + sz.cx;
m_StcError.MoveWindow( &rc );
SelectObject( hDC, hFont_ );
}
すると、GetTextExtentPoint32()のszにも、DrawTextのrcにも同じ値が入るのですが、
この値が表示されているピクセルよりも3~4割長い値が帰ってくる様で、
m_StcError.MoveWindow()でMoveすると実際の表示よりかなり長いStaticWindowになって
しまっています。
文字列の表示ピクセル数を取得するのに、正しい方法をどなたかご教授頂けないでしょ
うか。
すみませんが、宜しくお願いいたします。
すみません、一点自己修正で、
> GetTextExtentPoint32()のszにも、DrawTextのrcにも同じ値が入るのですが
この部分は、sz にも rcのright/leftの差分も同じ値になります、の間違いです。
どこぞで、GetTextExtentPoint32()ではカーニング処理がされない値が返ると漏れ伝え
聞いて、DrawTextも試してみたのですが、結果は一緒だった、という感じです。
> HGDIOBJ hFont_ = SelectObject(hDC, &font);
CFont* と HGDIOBJ はまったく別物ですので、
CFont* の値を指定しても、SelectObject 側では、
「無効なフォントが指定されたぞ」と思っていることでしょう。
そして、デフォルトのフォントで計算されているのだと思います。
> font.CreatePointFont( 8, MS UI Gothic );
8ptのフォントを作る時は、第1引数は 80 にしないといけないんじゃなかったかな。
dairygoodsさん、sugarさん有難うございます。
ちなみに、フォントに変更をかけてない場合は、SelectObjectのくだりはやはり必要無
いでしょうか?
というのも、最初は何もせずデフォルトでやっていたのですが、ダイアログデフォルト
のフォント値とCStaticのデフォルトフォントは別物でしょうか?
何も指定せず、デフォルトでやった場合はdairygoodsさんのおっしゃる様に、今と値が
変わらないのですが、そもそも今回のケースでフォント指定の必要性が有るのかも良く
分かりません (^-^;;
ちなみに、フォント系とSelectObjectのあたりをカットしても、GetTextExtentPoint32
()で帰ってくる値は同じで、DrawTextも同様です。また、フォントを指定するにして
も、何をして良いやら、良く分からない、、、という感じです。(指定の仕方が間違っ
ていたのもありますが)
ダイアログに設定されているデフォルトフォント(MS UI Gothic,8ポイント)とそのダ
イアログの中のコントロールのデフォルトフォントは別なのでしょうか?
デバイスコンテキストのデフォルトと
ダイアログリソースで設定するダイアログのフォントは無関係です。
フォントを指定せずTextOut()等で出力してみれば、
どんなフォントか分かると思います。
dairygoodsさん、有難うございます。
お二人の助言を元に以下の方法で実装して、上手く動作致しました。
有難うございました!
void EShellExecuteErrorDialog::ResizeStaticWindow( CString message )
{
HDC hDC = ::GetDC( m_StcError.GetSafeHwnd() );
LOGFONT lf;
HFONT hFont;
SIZE sz;
GetFont()->GetLogFont( &lf );
hFont = CreateFont( lf.lfHeight,
lf.lfWidth,
0, //テキストの角度
0, //ベースラインとx軸との角度
lf.lfWeight,
FALSE, //イタリック体
FALSE, //アンダーライン
FALSE, //打ち消し線
lf.lfCharSet,
lf.lfOutPrecision,
lf.lfClipPrecision,
lf.lfQuality,
lf.lfPitchAndFamily,
lf.lfFaceName
);
HGDIOBJ hFont_ = SelectObject( hDC, hFont );
GetTextExtentPoint32( hDC, message, message.GetLength(), &sz );
SelectObject( hDC, hFont_ );
m_StcError.GetWindowRect( &rc );
rc.right = rc.left + sz.cx;
ScreenToClient( &rc );
m_StcError.MoveWindow( &rc );
}
あぁ、、
すみません、解決チェックを押し忘れました。
もう解決しているようですが...
わざわざフォントを作成しなくても、スタティックコントロールのフォントを取得
して、それをDCに選択してから、GetTextExtent()すればいいのでは。
こんな感じ。(試してないです)
CClientDC dc(&m_StcError);
CFont* pPrevFont = dc.SelectObject(m_StcError.GetFont());
CSize size = dc.GetTextExtent(message);
dc.SelectObject(pPrevFont);
これで、正しいsizeが手に入ると思われます。
こんにちわ。
R-Cradleさん、有難う御座います。
今思えば、この方法で大丈夫でしたね。実験しましたが、同様に上手く行きました。
結果的にハマったポイントは、フォントをきちんと設定しないと駄目だ、という事を抜か
していた為に、あれやこれやの方法で、うにうにしてました。
冷静に考えれば、そうなのですが、お恥ずかしい・・・(^-^;;