MFC多视图

窗口分割

CSplitterWnd

名称 描述
CSplitterWnd::ActivateNext 执行"Next Pane"或"Previous Pane"命令。
CSplitterWnd::CanActivateNext 检查当前是否可以使用"Next Pane"或"Previous Pane"命令。
CSplitterWnd::Create 调用,用于创建动态拆分器窗口并将其附加到 CSplitterWnd 对象。
CSplitterWnd::CreateScrollBarCtrl 创建共享滚动条控件。
CSplitterWnd::CreateStatic 调用,用于创建静态拆分器窗口并将其附加到 CSplitterWnd 对象。
CSplitterWnd::CreateView 调用,用于在拆分器窗口中创建窗格。
CSplitterWnd::DeleteColumn 从拆分器窗口中删除一列。
CSplitterWnd::DeleteRow 从拆分器窗口中删除一行。
CSplitterWnd::DeleteView 从拆分器窗口中删除视图。
CSplitterWnd::DoKeyboardSplit 执行键盘拆分命令,通常为"Window Split"。
CSplitterWnd::DoScroll 执行拆分窗口的同步滚动。
CSplitterWnd::DoScrollBy 根据给定数目的像素滚动拆分窗口。
CSplitterWnd::GetActivePane 根据框架中的焦点或活动视图确定活动窗格。
CSplitterWnd::GetColumnCount 返回当前窗格列数。
CSplitterWnd::GetColumnInfo 返回指定列的信息。
CSplitterWnd::GetPane 返回指定行和列的窗格。
CSplitterWnd::GetRowCount 返回当前窗格行数。
CSplitterWnd::GetRowInfo 返回指定行的信息。
CSplitterWnd::GetScrollStyle 返回共享滚动条样式。
CSplitterWnd::IdFromRowCol 返回位于指定行和列的窗格的子窗口 ID。
CSplitterWnd::IsChildPane 调用,用于确定窗口当前是否为此拆分器窗口的子窗格。
CSplitterWnd::IsTracking 确定拆分器栏当前是否正在移动。
CSplitterWnd::RecalcLayout 调整行或列大小后调用,用于重新显示拆分器窗口。
CSplitterWnd::SetActivePane 将窗格设置为框架中的活动窗格。
CSplitterWnd::SetColumnInfo 借助调用来设置指定列信息。
CSplitterWnd::SetRowInfo 借助调用来设置指定行信息。
CSplitterWnd::SetScrollStyle 为拆分器窗口的共享滚动条支持指定新的滚动条样式。
CSplitterWnd::SplitColumn 指示框架窗口垂直拆分的位置。
CSplitterWnd::SplitRow 指示框架窗口水平拆分的位置。
名称 描述
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;
	}
}
相关推荐
小丑西瓜6661 天前
CMake基础用法,cmake_minimum_required,project,add_executable
linux·服务器·c++·camke
晚风吹长发1 天前
初步了解Linux中的命名管道及简单应用和简单日志
linux·运维·服务器·开发语言·数据结构·c++·算法
fpcc1 天前
设计心得——隔离隐藏的初步实践
c++
C++ 老炮儿的技术栈1 天前
不调用C++/C的字符串库函数,编写函数strcpy
c语言·开发语言·c++·windows·git·postman·visual studio
fyzy1 天前
C++写后端实现,实现前后端分离
开发语言·c++
CSDN_RTKLIB1 天前
C++谓词
c++·stl
汉克老师1 天前
GESP2025年9月认证C++五级真题与解析(单选题9-15)
c++·算法·贪心算法·排序算法·归并排序·gesp5级·gesp五级
飞鹰511 天前
CUDA高级优化实战:Stream、特殊内存与卷积优化—Week3学习总结
c++·gpt·chatgpt·gpu算力
txinyu的博客1 天前
std::function
服务器·开发语言·c++
学嵌入式的小杨同学1 天前
【嵌入式 C 语言实战】交互式栈管理系统:从功能实现到用户交互全解析
c语言·开发语言·arm开发·数据结构·c++·算法·链表