zoukankan      html  css  js  c++  java
  • MFC 静态拆分视图窗口

    今天学习了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;
    }

    效果:

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

    签名:GreenLeaf1976
  • 相关阅读:
    Mac安装Homebrew的那些事儿
    SpringBoot:如何优雅地处理全局异常?
    JDK8日常开发系列:Consumer详解
    Docker 快速安装Jenkins完美教程 (亲测采坑后详细步骤)
    Linux安装Git-两种方式详细教程)
    Linux安装maven(详细教程)
    Linux安装jdk(详细教程)
    Docker基础概念与安装
    JVM参数及调优
    JDK内置工具命令
  • 原文地址:https://www.cnblogs.com/greenleaf1976/p/14851446.html
Copyright © 2011-2022 走看看