SDI で,MDI の「新しいウィンドウを開く」で 4 つのビューを表示した様な動作が欲しかったので,調べてみた.
動的な分割ウィンドウである程度の所まではできそう.
1. MainFrm.h の CMainFrame に以下を追加. CSplitterWnd m_wndSplitter; virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); 2. CMainFrame::OnCreateClient の追加. BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { { if (!m_wndSplitter.Create(this,2, 2,CSize(10, 10), pContext, WS_CHILD | WS_VISIBLE /* | WS_HSCROLL | WS_VSCROLL */ | SPLS_DYNAMIC_SPLIT)) { TRACE0("Failed to create split bar "); return FALSE; } return TRUE; } } スクロールバーを付加したくなかったので,6 つ目のウィンドウスタイルを変更している. テスト用に分割動作をコマンドとして実装. void CMainFrame::OnSplit() { if (IsSplit) { if (m_wndSplitter.GetColumnCount() > 1) { m_wndSplitter.DeleteColumn(1) ; } if (m_wndSplitter.GetRowCount() > 1) { m_wndSplitter.DeleteRow (1) ; } IsSplit = !IsSplit ; } else { CRect rect ; m_wndSplitter.GetClientRect(&rect) ; if (m_wndSplitter.GetColumnCount() == 1) { m_wndSplitter.SplitColumn(rect.Width ()/2) ; } if (m_wndSplitter.GetRowCount() == 1) { m_wndSplitter.SplitRow (rect.Height()/2) ; } IsSplit = !IsSplit ; } }
2 x 2 の分割ウィンドウのコントロールの ID (Spy++ で確認)
左上(0,0) E900 AFX_IDW_PANE_FIRST
右上(0,1) E901
左下(1,0) E910
右下(1,1) E911
ビューの OnDraw を以下の様に書き換えると
void CSpltWView::OnDraw(CDC* pDC) { int row = -1 ; int clm = -1 ; CMainFrame* mw = (CMainFrame*)AfxGetMainWnd() ; CSplitterWnd* sw = &mw->m_wndSplitter ; CString str ; if (sw->IsChildPane(this,&row,&clm)) { int id = sw->IdFromRowCol(row,clm) ; CString tmp1 ; tmp1.Format(_T("row = %d , clm = %d"),row,clm) ; CString tmp2 ; tmp2.Format(_T("IdFromRowCol = %04X"), id) ; str += tmp1 + _T("\r\n") ; str += tmp2 + _T("\r\n") ; } { UINT nID = GetDlgCtrlID() ; CString tmp ; tmp.Format(_T("GetDlgCtrlID = %04X"),nID) ; str += tmp + _T("\r\n") ; } { CWnd* pw = GetParent() ; CString tmp1 ; tmp1.Format(_T("Splitter = %08x "),sw->GetSafeHwnd()) ; CString tmp2 ; tmp2.Format(_T("Parent = %08x "),pw->GetSafeHwnd()) ; str += tmp1 + _T("\r\n") ; str += tmp2 + _T("\r\n") ; } CRect rect ; GetClientRect(rect) ; rect.top = rect.left = 10 ; pDC->DrawText(str,rect,0) ; }
MFC の ソースを眺めていると CView::GetParentSplitter があったので,間接的にはそれを使えば良さそう.
ビューでどの位置かを求めるだけなら, short texNo = 0 ; { UINT nID = GetDlgCtrlID() ; switch (nID) { case AFX_IDW_PANE_FIRST + 0x00 : texNo = 1 ; break ; case AFX_IDW_PANE_FIRST + 0x01 : texNo = 2 ; break ; case AFX_IDW_PANE_FIRST + 0x10 : texNo = 3 ; break ; case AFX_IDW_PANE_FIRST + 0x11 : texNo = 4 ; break ; } }