プロパティシート

ウィンドウ内にモードレス&チャイルドなプロパティシートを埋め込むたくらみ。そもそもCPropertySheetはモーダルか、モードレス(といっても非チャイルドのダイアログ)としての使い方しかしないようなので、MSDNではよくわかりませんでした。で、手探りでごにょごにょ。ちなみに、想定してるアプリケーションはダイアログベースのやつです。なので、この処理はOnInitDialogに書きます。

001 // プロパティシートにプロパティページを追加する。
002 m_cPropSheet.AddPage( &m_cPropSE );
003 m_cPropSheet.AddPage( &m_cPropThread );
004 
005 // プロパティシートを作る。
006 m_cPropSheet.Create( this, WS_CHILD | WS_VISIBLE );
007 
008 // プロパティシートの位置あわせ。
009 CRect rc;
010 // 現在のウィンドウサイズを得る。
011 m_cPropSheet.GetWindowRect( &rc );
012 // (420,0)の位置に持ってくる。
013 rc.OffsetRect( 420 - rc.left, -rc.top );
014 // あと、幅も縮める。
015 rc.right -= 200;
016 TRACE2( "%d,%d,", rc.left, rc.top );
017 TRACE2( "%d,%d\n", rc.right, rc.bottom );
018 // 動かす。
019 m_cPropSheet.MoveWindow( &rc );
020 
021 // プロパティシートの中のタブコントロールの位置合わせ。
022 CTabCtrl* pTabCtrl = m_cPropSheet.GetTabControl();
023 // 現在のサイズを得る。
024 pTabCtrl->GetWindowRect( &rc );
025 TRACE2( "Before: %d,%d,", rc.left, rc.top );
026 TRACE2( "%d,%d\n", rc.right, rc.bottom );
027 // クライアント座標に変換。多分ちょっとずれてる
028 pTabCtrl->ScreenToClient( &rc );
029 //rc.OffsetRect( -rc.left, -rc.top ); // こっちでも大丈夫っぽい
030 // プロパティシートと同じサイズ縮める。
031 rc.right -= 200;
032 // 動かす。
033 pTabCtrl->MoveWindow( &rc );
034 pTabCtrl->GetWindowRect( &rc );
035 TRACE2( "After: %d,%d,", rc.left, rc.top );
036 TRACE2( "%d,%d\n", rc.right, rc.bottom );
037 CPoint ptTabCtrl = rc.TopLeft();
038 
039 if( false ){ // じつはこんな面倒なことしなくてよかった
040     // この関数でプロパティページを置くべき位置が求まるらしい。
041     pTabCtrl->AdjustRect( FALSE, &rc );
042     rc.OffsetRect( -ptTabCtrl );
043     for( int i = 0; i < m_cPropSheet.GetPageCount(); ++i ){
044         CPropertyPage* pPropPage = m_cPropSheet.GetPage( i );
045         if( pPropPage->GetSafeHwnd() == NULL ){
046             // なぜかNULLになることがある。
047             continue;
048         }
049         pPropPage->MoveWindow( &rc );
050     }
051 }
052 

今ひとつ不正確な点は、タブコントロールの位置です。ClientToScreenでそれっぽい位置には来るのですが、本来はもう少し右下に来るようです。