CStaticの幅調整

[戻る]
Pocket 2005/06/15(水) 02:47:38
下記環境で開発している者ですが、宜しくお願いいたします。

環境:
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になって
しまっています。

文字列の表示ピクセル数を取得するのに、正しい方法をどなたかご教授頂けないでしょ
うか。

すみませんが、宜しくお願いいたします。

Pocket 2005/06/15(水) 03:01:49
すみません、一点自己修正で、

> GetTextExtentPoint32()のszにも、DrawTextのrcにも同じ値が入るのですが

この部分は、sz にも rcのright/leftの差分も同じ値になります、の間違いです。
どこぞで、GetTextExtentPoint32()ではカーニング処理がされない値が返ると漏れ伝え
聞いて、DrawTextも試してみたのですが、結果は一緒だった、という感じです。

dairygoods 2005/06/15(水) 09:17:04
>  HGDIOBJ hFont_ = SelectObject(hDC, &font);

CFont* と HGDIOBJ はまったく別物ですので、
CFont* の値を指定しても、SelectObject 側では、
「無効なフォントが指定されたぞ」と思っていることでしょう。

そして、デフォルトのフォントで計算されているのだと思います。

sugar 2005/06/15(水) 09:47:31
>  font.CreatePointFont( 8, "MS UI Gothic" );

8ptのフォントを作る時は、第1引数は 80 にしないといけないんじゃなかったかな。

Pocket 2005/06/15(水) 10:36:15
dairygoodsさん、sugarさん有難うございます。

ちなみに、フォントに変更をかけてない場合は、SelectObjectのくだりはやはり必要無
いでしょうか?

というのも、最初は何もせずデフォルトでやっていたのですが、ダイアログデフォルト
のフォント値とCStaticのデフォルトフォントは別物でしょうか?

何も指定せず、デフォルトでやった場合はdairygoodsさんのおっしゃる様に、今と値が
変わらないのですが、そもそも今回のケースでフォント指定の必要性が有るのかも良く
分かりません (^-^;;

ちなみに、フォント系とSelectObjectのあたりをカットしても、GetTextExtentPoint32
()で帰ってくる値は同じで、DrawTextも同様です。また、フォントを指定するにして
も、何をして良いやら、良く分からない、、、という感じです。(指定の仕方が間違っ
ていたのもありますが)

ダイアログに設定されているデフォルトフォント(MS UI Gothic,8ポイント)とそのダ
イアログの中のコントロールのデフォルトフォントは別なのでしょうか?

dairygoods 2005/06/15(水) 11:01:12
デバイスコンテキストのデフォルトと
ダイアログリソースで設定するダイアログのフォントは無関係です。

フォントを指定せずTextOut()等で出力してみれば、
どんなフォントか分かると思います。

Pocket 2005/06/15(水) 11:12:48
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 );
}

Pocket 2005/06/15(水) 11:13:27
[[解決]]
あぁ、、

すみません、解決チェックを押し忘れました。

R-Cradle 2005/06/15(水) 11:55:11
もう解決しているようですが...
わざわざフォントを作成しなくても、スタティックコントロールのフォントを取得
して、それをDCに選択してから、GetTextExtent()すればいいのでは。
こんな感じ。(試してないです)

    CClientDC dc(&m_StcError);
    CFont* pPrevFont = dc.SelectObject(m_StcError.GetFont());
    CSize size = dc.GetTextExtent(message);
    dc.SelectObject(pPrevFont);

これで、正しいsizeが手に入ると思われます。

Pocket 2005/06/15(水) 13:06:50
こんにちわ。
R-Cradleさん、有難う御座います。

今思えば、この方法で大丈夫でしたね。実験しましたが、同様に上手く行きました。
結果的にハマったポイントは、フォントをきちんと設定しないと駄目だ、という事を抜か
していた為に、あれやこれやの方法で、うにうにしてました。

冷静に考えれば、そうなのですが、お恥ずかしい・・・(^-^;;

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