今天学习了MFC中拆分窗口,现将方法记录下.

想要在窗口视图中拆分成左右两个视图窗口,首先要注意的是拆分后要加载到左右的视图要符合动态创建的类,

也就是要在自己创建的视图类中添加动态创建机制宏.

类内声明宏:

  DECLARE_DYNCREATE(CSelectView)     //CSelectView为自己创建的视图类

类外实现宏:

  IMPLEMENT_DYNCREATE(CSelectView,CTreeView)  //CTreeView为父类

1.创建两个自己的视图类,

  CSelectView继承于CTreeView

  CMyDialg继承于CFromView

CSelectView用于树形控件显示,没啥可说的.着重说下,对话框的视图类,要注意是子窗口,无边框.所以在窗口属性中要把.Border设置为None,Style设置为Child

下面是两个类的声明:

#pragma once
#include <afxcview.h>  //树形视图类头文件
class CSelectView :
public CTreeView
{
DECLARE_DYNCREATE(CSelectView)
CSelectView();
protected:
//virtual void OnDraw(CDC* pDC) override;
private:
CTreeCtrl *m_pTreeCtrl;
public:
virtual void OnInitialUpdate();
DECLARE_MESSAGE_MAP()
afx_msg void OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult);
}; #include <afxext.h>  //窗口视图类头文件
// CMyDialog 窗体视图 class CMyDialog : public CFormView
{
DECLARE_DYNCREATE(CMyDialog) protected:
CMyDialog(); // 动态创建所使用的受保护的构造函数
virtual ~CMyDialog(); virtual void OnDraw(CDC* pDC) override; public:
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG1 };
#endif
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif virtual void OnDragLeave() override; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP()
};

在类外分别加上实现宏

//CSelectView类

#include "CSelectView.h"
#include "MyApp.h" IMPLEMENT_DYNCREATE(CSelectView,CTreeView) //窗口类
#include "resource.h"
#include "CMyDialog.h" // CMyDialog IMPLEMENT_DYNCREATE(CMyDialog, CFormView)

注意,如果父类中有纯虚函数要在自己创建的类中实现,不然无法动态创建类对象

2.在主框架类中重写OnCreateClient()函数

//m_splitter:为类的成员变量:

CSplitterWnd m_splitter;

BOOL MyWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
//拆分窗口(一行两列)
m_splitter.CreateStatic(this, 1, 2);
//创建视图类对象
  //第一列创建树形视图类,第二列创建对话框视图类
m_splitter.CreateView(0, 0, RUNTIME_CLASS(CSelectView),
CSize(200, 200), pContext);
m_splitter.CreateView(0, 1, RUNTIME_CLASS(CMyDialog),
CSize(200, 200), pContext); return TRUE;
}

这样就把主窗口拆分成左右两个视图窗口了,中间的分隔栏可以用鼠标左右拖动

3.加载数据到树形视图中

树形视图类要加载数据就要在初始化函数OnInitialUpdate()中

首先要定义一个CTreeCtrl类型的控件,用来操作数据

在树形视图类中添加

CTreeCtrl*  m_treeCtrl;

在OnInitialUpdate()中添加数据加载

void CSelectView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate(); // TODO: 在此添加专用代码和/或调用基类
m_pTreeCtrl = &GetTreeCtrl();//获取树形视图中的树形控件对象

//添加数据和样式,也可以添加图标,不过我没弄,
m_pTreeCtrl->ModifyStyle(0, TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS| TVS_SHOWSELALWAYS); m_pTreeCtrl->InsertItem(TEXT("显示数据"), 0,0,TVI_ROOT);
m_pTreeCtrl->InsertItem(TEXT("添加数据"), 0, 0, TVI_ROOT);
m_pTreeCtrl->InsertItem(TEXT("修改数据"), 0, 0, TVI_ROOT);
m_pTreeCtrl->InsertItem(TEXT("删除数据"), 0, 0, TVI_ROOT); }

4.更改右边的视图类

根据左边树形视图中的选择,右边更改相应的窗口视图类

在树视图的OnTvnSelchanged函数中处理选择项改变的事件

在主框架类中定义自定义消息用

//自定义消息
#define NM_A   (WM_USER+100)
#define NM_B   (WM_USER+101)
#define NM_C   (WM_USER+102)

void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
HTREEITEM hSel = pNMTreeView->itemNew.hItem;  //获取树控件选中的项
CString str = m_pTreeCtrl->GetItemText(hSel);  //获取选中项的字符串数据
//根据选择的项发送自定义消息(NM_A,NM_B)来更改右边的视图窗口类
  //我就随便定义了两个消息NM_A,NM_B,都响应OnMyChange函数
  
if (str == TEXT("添加数据"))
{
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(),NM_A, (WPARAM)NM_A, 0);
}
else if (str == TEXT("修改数据"))
{
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_B, (WPARAM)NM_B, 0);
} }

在主框架中捕获消息

BEGIN_MESSAGE_MAP(MyWnd,CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(ID_BTN_NEW,&MyWnd::OnBtnNew)
ON_COMMAND(ID_BTN_EDIT,&MyWnd::OnBtnEdit)
ON_COMMAND(ID_BTN_DELETE,&MyWnd::OnBtnDelete)
ON_COMMAND(ID_BTN_QUIT,&MyWnd::OnBtnQuit)
ON_COMMAND(ID_BTN_MIN,&MyWnd::OnBtnMin)
ON_COMMAND(ID_BTN_FIND,&MyWnd::OnBtnFind)
ON_WM_PAINT()
ON_MESSAGE(NM_A,&MyWnd::OnMyChange)//自定义消息函数
ON_MESSAGE(NM_B,&MyWnd::OnMyChange)//自定义消息函数
ON_WM_SIZE()
END_MESSAGE_MAP()

在OnMyChange中实现窗口视图类的切换

LRESULT MyWnd::OnMyChange(WPARAM wParam, LPARAM lParam)
{
CCreateContext context;//动态创建机制结构体
switch (wParam)
{
case NM_A://创建IDD_DIALOG1对话框视图类CMyDialog
{
context.m_pNewViewClass = RUNTIME_CLASS(CMyDialog);//要创建的视图类
context.m_pCurrentFrame = this;    //当前窗口类
context.m_pLastView = (CFormView*)m_splitter.GetPane(0, 1); //要在哪列创建新的视图类,(我这是要在右边,也就是第0行1列)
m_splitter.DeleteView(0, 1);  //删除原来的视图类
m_splitter.CreateView(0, 1, RUNTIME_CLASS(CMyDialog), CSize(200, 200), &context);  //动态创建新的视图类(大小无所谓,最后都是平铺分隔的左右窗口)
CMyDialog *pNewView = (CMyDialog*)m_splitter.GetPane(0, 1); //获取新创建的视图类对象
m_splitter.RecalcLayout();  
pNewView->OnInitialUpdate();  //初始化新视图类
m_splitter.SetActivePane(0, 1);  //激活新的视图类 }
break;
case NM_B: //创建IDD_DIALGO2对话框视图类MyAddDlg
{
context.m_pNewViewClass = RUNTIME_CLASS(MyAddDlg);
context.m_pCurrentFrame = this;
context.m_pLastView = (CFormView*)m_splitter.GetPane(0, 1);
m_splitter.DeleteView(0, 1);
m_splitter.CreateView(0, 1, RUNTIME_CLASS(MyAddDlg), CSize(200, 200), &context);
MyAddDlg *pNewView = (MyAddDlg*)m_splitter.GetPane(0, 1);
m_splitter.RecalcLayout();
pNewView->OnInitialUpdate();
m_splitter.SetActivePane(0, 1); }
break;
case NM_C:
break;
}
/*if (wParam == NM_A)
{
MessageBox(TEXT("添加数据"));
}
else if(wParam==NM_B){
MessageBox(TEXT("修改数据"));
}*/ return 0;
}

效果:

这样就方便用对话框来拖拽控件来布局界面

MFC 静态拆分视图窗口的更多相关文章

  1. MFC之拆分窗口

    7.3.1 多视图 许多文档只要求单个视图,但每个文档可支持一个以上的视图.为了帮助编程人员实现多个视图,文档对象保留它的视图列表.为添加和移去视图提供成员函数,例如,提供的UpdateAllView ...

  2. MFC 静态文本的自绘 空心字的实现

    想在对话框里,显示几个字是很简单的,只要用静态文本的输出就可以了.然而有时候我们需要显示特效的字,我们希望显示的文字就像Word里的艺术字一样,看起来美观.这时我们可以重写CStatic类.用Draw ...

  3. vs mfc 静态文本 改变字体大小

    VC的对话框字体设置对所有控件都有效,你不能单独地改变某个静态文本的字体.对于你的问题,需要首先用CreateFont来建立一个字体对象,然后调用控件的SetFont,就可以了. 例子: 1.改静态文 ...

  4. MFC 静态文本框

    窗体上操作控件内容,需要句柄,在控件处使用鼠标右键——添加变量. DoDataExchange()函数会自动生成代码,把ID与变量绑定(即DDX_Control(pDX, IDC_TEXT, objT ...

  5. MFC如何使用静态MFC库

    大部分MFC程序都是使用 在共享DLL中使用MFC ,但是VS每一个版本都需要一个 MFC运行库,实在是有点烦人. 所以我选择了使用静态MFC库,虽然文件会大一些,但是至少不麻烦了. VS这个做的不够 ...

  6. VS2010 MFC中 静态编译设置方法

    问题:VS2010 c++编写的程序在别人的机子运行不了,缺少mfc100u.dll xxx100d.dll等 解决方法:1.将这些dll打包,和应用程序一起发布;2.采用MFC静态编译; 静态编译: ...

  7. VC++ 窗口拆分CSplitterWnd

    前言         当前许多优秀的软件都采用“多视”技术. 所谓“多视”,是指在同一个框架窗口里同时显示多个视图. 通过运用这种技术,可以在框架的有限控件内同时提供用户更大的信息量,并且使得用户界面 ...

  8. C++ MFC学习 (六)

    由于微软在VS2013 及之后不建议再使用 C/C++ 的传统库函数 scanf,strcpy,sprintf 等,所以直接使用这些库函数会提示 C4996 错误 VS建议采用带 _S的函数,如: s ...

  9. [MFC] MFC编译程序,缺少MFC动态链接库的解决

    问题:VS2010 c++编写的程序在别人的机子运行不了,缺少mfc100u.dll xxx100d.dll等的解决方法   解决方法: 1.将这些dll打包,和应用程序一起发布; 2.采用MFC静态 ...

  10. MFC编译程序,缺少MFC动态链接库的解决

    MFC编译程序,缺少MFC动态链接库的解决 问题:VS2010 c++编写的程序在别人的机子运行不了,缺少mfc100u.dll xxx100d.dll等的解决方法 解决方法: 1.将这些dll打包, ...

随机推荐

  1. Linux内核:通知链 机制

    Linux内核:通知链 机制 背景 在驱动分析中经常看到fb_notifier_callback,现在趁有空学习一下. 参考: https://www.cnblogs.com/armlinux/arc ...

  2. Android Camx 架构介绍

    Android Camx 架构介绍 原文链接:深入理解高通Camx Hal 概览 高通平台的Camera架构从以前用的mm-camera转向camx-chi,完全是两样不同的东西:软件架构不同.代码位 ...

  3. 解决keil5仿真错误:Encountered an improper argument

    --- title: 解决keil5仿真错误:Encountered an improper argument date: 2020-06-18 03:13:18 categories: tags: ...

  4. arm linux 移植 SQLite 3

    背景 SQLite 是 一个 常用于 嵌入式平台的 轻量级数据库. host平台 :Ubuntu 16.04 arm平台 : S5P6818 SQLite :3.31.1 arm-gcc :4.8.1 ...

  5. 全国产RK3568J + FPGA的PCIe、FSPI通信实测数据分享!

    测试数据汇总 案例 时钟频率 理论速率 测试结果 FSPI通信案例 150MHz 71.53MB/s 读速率:67.452MB/s 写速率:52.638MB/s PCIe通信案例 100MHz 803 ...

  6. [UG 二次开发 python] 导出BOM表(包含图片)

    只导出最底层的零件,零件的属性已经设置好,零件的截图生成后,放在零件的同一个文件夹下 用到了 xlsxwriter # nx: threaded # 导出BOM表 __version__ = &quo ...

  7. el-date-picker的value-forma在Element UI (Vue 2)和Element Plus (Vue 3)中的不同

    Element UI (Vue 2): <template> <el-form-item prop="register_date" label="成立日 ...

  8. [oeasy]python0089_大型机的衰落_Dec小型机崛起_PDP_VAX网络

    编码进化 回忆上次内容 上次 回顾了 计算机存储单位的演变 最小的读写单位 是 bit 8-bit 固定下来 成为了字节(Byte) 位数 容量 8-bit 1Byte 1024Byte 1 KB 1 ...

  9. AT_agc019_b 题解

    洛谷链接&Atcoder 链接. 题目简述 给定一个字符串 \(A\),可以选择区间 \([i,j]\) 翻转一次,求能得到多少本质不同的字符串.(\(A\) 的长度不超过 \(2 \time ...

  10. 计算机网络中的检验和(checksum)(包括计算文件的检验和附有c++代码)

    介绍: 检验和(checksum),在数据处理和数据通信领域中,用于校验目的地一组数据项的和.它通常是以十六进制为数制表示的形式.如果校验和的数值超过十六进制的FF,也就是255. 就要求其补码作为校 ...