窗口分割

CSplitterWnd

| 名称 | 描述 |
|---|---|
| CSplitterWnd::OnDraw | 由框架调用以绘制拆分器窗口。 |
| CSplitterWnd::OnDrawSplitter | 呈现拆分窗口的图像。 |
| CSplitterWnd::OnInvertTracker | 呈现拆分窗口的图像,使其与框架窗口的大小和形状相同。 |
Create-动态创建分割窗口

CreateStatic-创建静态风格窗口

CreateView-创建窗格

SetRowInfo和SetColumnInfo-设置窗格信息

OnDrawSplitter-绘制分割窗口特征

OnInvertTracker-绘制风格条

视图切换

范例


添加资源


CSplitterWndEx1
CSplitterWndEx与Afx 定义的 CSplitterWndEx重名了,故以下CSplitterWndEx全部改为CSplitterWndEx1




OnDrawSplitter

cpp
//呈现拆分窗口的图像。
void CSplitterWndEx::OnDrawSplitter(CDC* pDC, ESplitType nType, const CRect& rect)
{
// TODO: 在此添加专用代码和/或调用基类
if (pDC == NULL)
{
RedrawWindow(rect, NULL, RDW_INVALIDATE | RDW_NOCHILDREN);//更新工作区中的指定矩形或区域。
return;
}
ASSERT_VALID(pDC);
CRect rc = rect;
//ESplitType:拆分窗口中不同图形元素的绘制类型
switch (nType)
{
//splitBorder:表示拆分窗口的边框
case splitBorder:
//重画分割窗口边界,使左上为绿色 右下为红色
pDC->Draw3dRect(rc, RGB(0, 200, 0), RGB(255, 0, 0));//绘制三维矩形。
rc.InflateRect(-1, -1);//增大 CRect 的宽度和高度。
pDC->Draw3dRect(rc, RGB(0, 200, 0), RGB(255, 0, 0));
return;
//splitBox:表示拆分窗口中的分隔框(split box),通常是一个可拖动的方块,用于创建新的窗格。
case splitBox:
pDC->Draw3dRect(rc, RGB(0, 0, 0), RGB(0, 0, 0));
rc.InflateRect(-1, -1);
pDC->Draw3dRect(rc, RGB(0, 0, 0), RGB(0, 0, 0));
rc.InflateRect(-1, -1);
pDC->FillSolidRect(rc, RGB(0, 0, 0));//使用指定的纯色填充给定的矩形。
pDC->Draw3dRect(rc, RGB(0, 0, 0), RGB(0, 0, 0));
return;
//splitBar:表示分隔条(split bar),出现在两个窗格之间,用于调整相邻窗格的大小。
case splitBar:
//重画分割条,使之为绿色
pDC->FillSolidRect(rc, RGB(100, 200, 255));
rc.InflateRect(-1, -1);
pDC->Draw3dRect(rc, RGB(0, 0, 200), RGB(0, 0, 200));
return;
default:
ASSERT(FALSE);
}
// fill the middle
pDC->FillSolidRect(rc, RGB(0, 200, 0));
//return CSplitterWnd::OnDrawSplitter(pDC, nType, & rect);
}
OnInvertTracker

cpp
//拆分器窗口跟踪器(拖动时的高亮区域)
void CSplitterWndEx::OnInvertTracker(const CRect& rect)
{
// TODO: 在此添加专用代码和/或调用基类
ASSERT_VALID(this);
ASSERT(!rect.IsRectEmpty());
ASSERT((GetStyle() & WS_CLIPCHILDREN) == 0);//WS_CLIPCHILDREN:在父窗口内进行绘图时,不包括子窗口所占用的区域。
CDC* pDC = GetDC();
CBrush* pBrush = CDC::GetHalftoneBrush();//检索半色调画笔。
HBRUSH hOldBrush = NULL;
if (pBrush != NULL)
hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);// 创建位模式,绘制图案背景.(PATINVERT 使用布尔 XOR (^) 运算符将目标位图与图案相结合)
if (hOldBrush != NULL)
SelectObject(pDC->m_hDC, hOldBrush);
ReleaseDC(pDC);
//CSplitterWnd::OnInvertTracker(rect);
}
OnLButtonDown

cpp
void CSplitterWndEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CSplitterWnd::OnLButtonDown(nFlags, point);
}
修改构造函数
cpp
CSplitterWndEx::CSplitterWndEx()
{
//更改分割条和窗格间距大小
m_cxSplitter = m_cySplitter = 10;
m_cxSplitterGap = m_cySplitterGap = 10;
}
CLeftPaneView

编辑头文件
cpp
#include <afxcview.h>

OnInitialUpdate

cpp
//视图初始化
void CLeftPaneView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
::SetWindowLong(m_hWnd, GWL_STYLE, WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_BORDER | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES);//更改指定窗口的属性
CTreeCtrl& treeCtrl = GetTreeCtrl();//返回对与视图关联的树控件的引用。
m_ImageList.Create(IDB_IMAGES, 16, 1, RGB(255, 0, 255));//创建图像列表
treeCtrl.SetImageList(&m_ImageList, LVSIL_NORMAL);//设置与树视图控件关联的图像列表的句柄。
//插入树项
treeCtrl.InsertItem(L"编辑视", 0, 0); //在树视图控件中插入新项。
treeCtrl.InsertItem(L"列表视", 1, 1);//在树视图控件中插入新项。
}
OnTvnSelchanged

cpp
void CLeftPaneView::OnTvnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();//获取活动主窗口的指针
CTreeCtrl& treeCtrl = GetTreeCtrl();//返回与视图关联的树控件。
CString str;
HTREEITEM hSelectedItem = treeCtrl.GetSelectedItem();//获取当前选中的树项
str = treeCtrl.GetItemText(hSelectedItem);//获取当前选中的树项文本
if (str.Find(L"编辑") != -1)
{
pFrame->SwitchToView(EDITVIEW);//切换到编辑视图
}
else if (str.Find(L"列表") != -1)
{
pFrame->SwitchToView(LISTVIEW);//切换到列表视图
}
*pResult = 0;
}
CEditPaneView

OnInitialUpdate

cpp
void CEditPaneView::OnInitialUpdate()
{
CEditView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
SetWindowText(L"请选择左侧树视图选项以便查看切换视图效果视图");//更改指定窗口标题栏的文本(如果有)。 如果指定的窗口是控件,则控件的文本将更改。
}
CListPaneView

编辑头文件
cpp
#include <afxcview.h>

cpp
void CListPaneView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
CListCtrl& ctl = GetListCtrl();
//设置列表控件风格
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);//检索有关指定窗口的信息。
dwStyle |= LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS;//报表、即使控件没有焦点,也会始终显示所选内容、就地编辑项目文本
::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);//更改指定窗口的属性。
//设置扩展风格
dwStyle = ctl.GetExtendedStyle();//检索列表视图控件当前的扩展样式。
dwStyle |= LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT; //显示项和子项周围的网格线、选中某个项后,将突出显示该项及其所有子项
ctl.SetExtendedStyle(dwStyle);//设置列表视图控件当前的扩展样式
//列表控件头内容
TCHAR tittle[3][10] = { _T("姓名"),_T("单位"),_T("地址") };
LV_COLUMN lvcolumn;//包含有关报表视图中的列的信息
CRect rect;
GetWindowRect(&rect);//获取指定窗口的边界矩形。
//填充列表控件头
for (int i = 0; i < 3; i++)
{
lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT| LVCF_WIDTH | LVCF_ORDER;
lvcolumn.fmt = LVCFMT_LEFT;
lvcolumn.pszText = tittle[i];
lvcolumn.iSubItem = i;
lvcolumn.iOrder = i;
lvcolumn.cx = rect.Height() / 3;
GetListCtrl().InsertColumn(i, &lvcolumn);//插入列
}
}
CMainFrame
修改头文件

cpp
#pragma once
#include "SplitterWndEx1.h"
#include "LeftPaneView.h"
#include "ListPaneView.h"
#include "EditPaneView.h"
//定义右边视的类型
#define EDITVIEW 0
#define LISTVIEW 1
class CMainFrame : public CFrameWnd
{
public:
CSplitterWndEx m_wndSplitter;
CEditPaneView* m_pEditView;
CListPaneView* m_pListView;
...
};
OnCreateClient

cpp
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此添加专用代码和/或调用基类
if (!m_wndSplitter.CreateStatic(this, 1, 2))//创建静态拆分器窗口
return FALSE;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftPaneView), CSize(100, 100), pContext))//为静态拆分器窗口创建窗格。
return FALSE;
if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CEditPaneView), CSize(100, 100), pContext))//为静态拆分器窗口创建窗格。
return FALSE;
m_pEditView = (CEditPaneView*)m_wndSplitter.GetPane(0, 1);//返回指定行和列的窗格。
return TRUE;
//return CFrameWnd::OnCreateClient(lpcs, pContext);
}
SwitchToView

cpp
void CMainFrame::SwitchToView(int nViewType)
{
// TODO: 在此处添加实现代码.
CView* pView = (CView*)m_wndSplitter.GetPane(0, 1);//获取视图
CRect rcRight, rcFrame;
pView->GetClientRect(&rcRight);//获取视图的边界
GetClientRect(&rcFrame); //获取主窗口的边界
switch (nViewType)
{
case EDITVIEW: //CEditPaneView
{
if (!pView->IsKindOf(RUNTIME_CLASS(CEditPaneView)))
{
m_wndSplitter.DeleteView(0, 1);//删除旧的视图
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CEditPaneView),CSize(rcRight.Width(), rcRight.Height()), NULL);//创建新的视图
m_wndSplitter.RecalcLayout();//重新显示拆分器窗口
m_pEditView = (CEditPaneView*)m_wndSplitter.GetPane(0, 1); // 返回指定行和列的窗格。
}
break;
}
case LISTVIEW: //CListPaneView
{
if (!pView->IsKindOf(RUNTIME_CLASS(CListPaneView)))
{
m_wndSplitter.DeleteView(0, 1);//删除旧的视图
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CListPaneView),CSize(rcRight.Width(), rcRight.Height()), NULL);//创建新的视图
m_wndSplitter.RecalcLayout();//重新显示拆分器窗口
m_pListView = (CListPaneView*)m_wndSplitter.GetPane(0, 1);// 返回指定行和列的窗格。
}
break;
}
default:
break;
}
}


