1. 程式人生 > 實用技巧 >MFC中視窗靜態分割&檢視切換

MFC中視窗靜態分割&檢視切換

目錄

視窗靜態分割

單個分割器

宣告

首先在MainFrm.h中宣告分割物件

CSplitterWnd m_wndSplitter;

準備檢視

CView

或其派生類中派生四個類:CMyView1CMyView2CMyView3CMyView4

靜態分割視窗&新增檢視

MainFrm.cpp中新增虛擬函式OnCreateClient,新增如下程式碼

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此新增專用程式碼和/或呼叫基類
CRect rectClient;
GetClientRect(&rectClient); if (!m_wndSplitter.CreateStatic(this, 2, 2) ||
!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter.CreateView(1, 1, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext))
return FALSE; // return CFrameWnd::OnCreateClient(lpcs, pContext);
return TRUE;
}

使檢視大小隨視窗大小改變

MainFrm.h中宣告變數

BOOL m_bSplitter;

MainFrm.cpp建構函式中初始化m_bSplitter

CMainFrame::CMainFrame() noexcept :
m_bSplitter(FALSE)
{
}

MainFrm.cpp虛擬函式OnCreateClient視窗分割之後新增對m_bSplitter的賦值

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此新增專用程式碼和/或呼叫基類
CRect rectClient;
GetClientRect(&rectClient); if (!m_wndSplitter.CreateStatic(this, 2, 2) ||
!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter.CreateView(1, 1, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext))
return FALSE; m_bSplitter = TRUE; // 視窗已完成分割,檢視已經動態建立 // return CFrameWnd::OnCreateClient(lpcs, pContext);
return TRUE;
}

MainFrm.cpp中新增WM_SIZE訊息對映,新增如下程式碼

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy); // TODO: 在此處新增訊息處理程式程式碼
if (m_bSplitter == TRUE)
{
m_wndSplitter.SetColumnInfo(0, cx / 2, 0);
// 另外一列將自適應寬度
m_wndSplitter.SetRowInfo(0, cy / 2, 0);
// 另外一行將自適應高度 // 重新計算
m_wndSplitter.RecalcLayout();
}
}

效果圖

多個分割器

宣告

宣告兩個分割器

CSplitterWnd m_wndSplitter1; // 主分割器
CSplitterWnd m_wndSplitter2; // 子分割器

靜態分割視窗&新增檢視

MainFrm.cpp中修改虛擬函式OnCreateClient

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此新增專用程式碼和/或呼叫基類
CRect rectClient;
GetClientRect(&rectClient); if (!m_wndSplitter1.CreateStatic(this, 2, 1) ||
!m_wndSplitter1.CreateView(0, 0, RUNTIME_CLASS(CListView), CSize(rectClient.Width(), rectClient.Height() / 2), pContext))
return FALSE; if (!m_wndSplitter2.CreateStatic(&m_wndSplitter1, 1, 2, WS_CHILD | WS_VISIBLE, m_wndSplitter1.IdFromRowCol(1, 0)) ||
!m_wndSplitter2.CreateView(0, 0, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter2.CreateView(0, 1, RUNTIME_CLASS(CListView), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext))
return FALSE; m_bSplitter = TRUE; // 視窗已完成分割,檢視已經動態建立 // return CFrameWnd::OnCreateClient(lpcs, pContext);
return TRUE;
}

使檢視大小隨視窗大小改變

相應地修改OnSize函式

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy); // TODO: 在此處新增訊息處理程式程式碼
if (m_bSplitter == TRUE)
{
m_wndSplitter1.SetRowInfo(0, cy / 2, 0);
m_wndSplitter2.SetColumnInfo(0, cx / 2, 0); // 重新計算
m_wndSplitter1.RecalcLayout();
m_wndSplitter2.RecalcLayout();
}
}

效果圖

檢視切換

CMainFrame新增切換檢視的函式BOOL CMainFrame::Switch(int nIndex),新增如下程式碼建立框架

BOOL CMainFrame::Switch(int nIndex)
{
switch (nIndex)
{
case 0:
break;
case 1:
break;
default:
return FALSE;
}
return TRUE;
}

檢視之間的切換

宣告

CSplitterWnd m_wndSplitter;

修改相應函式

新增CMyView2和CMyView3的繪圖程式碼

CMyView2

void CMyView2::OnDraw(CDC* pDC)
{
CRect rectClient;
GetClientRect(rectClient); pDC->FillSolidRect(rectClient, RGB(255, 255, 255));
}

CMyView3

void CMyView3::OnDraw(CDC* pDC)
{
CRect rectClient;
GetClientRect(rectClient); pDC->FillSolidRect(rectClient, RGB(0, 0, 0));
}

修改OnCreateClient函式

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此新增專用程式碼和/或呼叫基類
CRect rectClient;
GetClientRect(&rectClient); if (!m_wndSplitter.CreateStatic(this, 1, 2) ||
!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CMyView1), CSize(rectClient.Width() / 2, rectClient.Height()), pContext) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMyView2), CSize(rectClient.Width() / 2, rectClient.Height()), pContext))
return FALSE; m_bSplitter = TRUE; // 視窗已完成分割,檢視已經動態建立 Switch(0); // 更改數值以獲得切換效果 // return CFrameWnd::OnCreateClient(lpcs, pContext);
return TRUE;
}

修改檢視切換函式

BOOL CMainFrame::Switch(int nIndex)
{
CRect rectClient;
GetClientRect(rectClient); switch (nIndex)
{
case 0:
m_wndSplitter.DeleteView(0, 1);
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMyView2), CSize(rectClient.Width() / 2, rectClient.Height()), NULL);
m_wndSplitter.RecalcLayout();
break;
case 1:
m_wndSplitter.DeleteView(0, 1);
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMyView3), CSize(rectClient.Width() / 2, rectClient.Height()), NULL);
m_wndSplitter.RecalcLayout();
break;
default:
return FALSE;
}
return TRUE;
}

子分割器之間的切換

宣告

CSplitterWnd m_wndSplitter; // 主分割器
CSplitterWnd m_wndSplitter1; // 子分割器1
CSplitterWnd m_wndSplitter2; // 子分割器2

準備檢視

CView或其派生類中派生第五個類:CMyView5

修改相應函式

修改OnCreateClient函式

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此新增專用程式碼和/或呼叫基類
CRect rectClient;
GetClientRect(&rectClient); if (!m_wndSplitter.CreateStatic(this, 1, 2) ||
!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyView1),CSize(rectClient.Width() / 2, rectClient.Height()),pContext))
return FALSE; if (!m_wndSplitter1.CreateStatic(&m_wndSplitter, 2, 1, WS_CHILD) ||
!m_wndSplitter1.CreateView(0, 0, RUNTIME_CLASS(CMyView2), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter1.CreateView(1, 0, RUNTIME_CLASS(CMyView3), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext))
return FALSE; if (!m_wndSplitter2.CreateStatic(&m_wndSplitter, 2, 1, WS_CHILD) ||
!m_wndSplitter2.CreateView(0, 0, RUNTIME_CLASS(CMyView4), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext) ||
!m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(CMyView5), CSize(rectClient.Width() / 2, rectClient.Height() / 2), pContext))
return FALSE; m_bSplitter = TRUE; // 視窗已完成分割,檢視已經動態建立 Switch(0); // 更改數值以獲得切換效果 // return CFrameWnd::OnCreateClient(lpcs, pContext);
return TRUE;
}

修改檢視切換函式

BOOL CMainFrame::Switch(int nIndex)
{
CRect rectClient;
GetClientRect(rectClient); switch (nIndex)
{
case 0:
::SetWindowLong(m_wndSplitter1, GWL_ID, m_wndSplitter.IdFromRowCol(0, 1));
m_wndSplitter1.ShowWindow(SW_SHOW);
::SetWindowLong(m_wndSplitter2, GWL_ID, AFX_IDW_PANE_FIRST);
m_wndSplitter2.ShowWindow(SW_HIDE);
break;
case 1:
::SetWindowLong(m_wndSplitter1, GWL_ID, AFX_IDW_PANE_FIRST);
m_wndSplitter1.ShowWindow(SW_HIDE);
::SetWindowLong(m_wndSplitter2, GWL_ID, m_wndSplitter.IdFromRowCol(0, 1));
m_wndSplitter2.ShowWindow(SW_SHOW);
break;
default:
return FALSE;
}
return TRUE;
}

篇尾宣告

單個分割器 參閱資料:https://blog.csdn.net/bao_bei/article/details/60136336

多個分割器 參閱資料:https://blog.csdn.net/bao_bei/article/details/60136336

檢視之間的切換 參閱資料:https://www.cnblogs.com/chenzuoyou/p/3342003.html

子分割器之間的切換 原創