论坛: 编程破解 标题: 转(VC++切分视图) 复制本贴地址    
作者: battle [battle]    论坛用户   登录
单文档视图的分割以及视图间操作

passmatlab 2001-8-2

在这里说明一下文档的内容是保持原来的样子,所以表现出开始的幼稚,同时也欢迎大家联系,共同学习提高。

passmatlab@etang.com

一.        熟悉VC++ 6.0文档与视图的关系及如何操作它们。

二.        1. 单文档视图分割成3*1形式的三个视图;

2.在其中一个视图双击能够隐藏其它两个视图,再双击一次那两个隐藏的视图显示出来,同时产生消息给其它视图;

3.在三个视图能够实现报型和树型列表。

三.        实现的框架图:下载源代码>>>


四.        步骤:

1.        MFC可执行文件向导建立单文档基类是ClistView,名为MyEdit的工程,第四步时点开Advanced…,在Window Styles里的Use split window前打√;

2.        加入两个视图类:

class CMyListView : public CListView

class CMyTreeVIew : public CtreeView

3.        实现视图的静态分割:

向CmainFrame类中加入公共的成员变量 CSplitterWnd m_wndSplitter,再使用MFC ClassWizard加入成员函数BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext),然后在此函数里加入下面一些代码:

                    if (!m_wndSplitter.CreateStatic(this,3,1))

      {

              return FALSE;// 分割成3*1不成功

      }

    else

      {//分割成3*1成功

      SIZE size;                                 

      CRect rect;   

      GetClientRect(&rect); 

      size.cx = rect.right/3 ;

      size.cy = rect.bottom/3;

      m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyListView),size, pContext);

      m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CMyTreeVIew),size, pContext);

      m_wndSplitter.CreateView(2,0,RUNTIME_CLASS(CMyEditView),size, pContext);

      m_wndSplitter.ShowWindow(SW_SHOWNORMAL);

      m_wndSplitter.UpdateWindow();

      return  TRUE;

在文件前加入下面一些头文件:

#include "MyEditView.h"

#include "MyListView.h"

#include "MyTreeVIew.h"

4.        隐藏与显示视图:

向CmyListView加成员函数void CMyListView::OnLButtonDblClk(UINT nFlags, CPoint point),这是双击的消息机制,同时再加入公共成员变量    int m_index,这个整型变量是指示当前是隐藏还是显示视图:

初始化变量m_index:

加入成员函数:void CMyListView::OnInitialUpdate()写进m_index=0;

头文件:

#include "stdafx.h"

#include "MyEdit.h"

#include "MyListView.h"

#include "MyEditDoc.h"

#include "MyEditView.h"

#include "MyTreeVIew.h"

#include "MainFrm.h"

在双击事件里加入下面一些代码:

              CMainFrame* MainFrame1=(CMainFrame*)this->GetParent()->GetParent();

//获取主窗口的指针

        CMyEditView* View4=(CMyEditView*)MainFrame1->m_wndSplitter.GetPane(2,0);

        CMyListView* View1=(CMyListView*)MainFrame1->m_wndSplitter.GetPane(0,0);

        CMyTreeVIew* View2=(CMyTreeVIew*)MainFrame1->m_wndSplitter.GetPane(1,0);

//获取指向三个视图的指针

              if (m_index==0)

              {

  View1->SetWindowPos(0, 0, 0, 1500 , 1000, SWP_SHOWWINDOW);

  View2->SetWindowPos(0, 0, 1000, 1500, 1000, SWP_SHOWWINDOW);

  View4->SetWindowPos(0, 0, 1000, 1500, 1000, SWP_SHOWWINDOW);

//把其中的两个视图移到看不到的位置,即实现隐藏功能

  m_index=1;

              }

              else

              {

  View1->SetWindowPos(0, 0, 0, 1500 , 150, SWP_SHOWWINDOW);

  View2->SetWindowPos(0, 0, 150, 1500, 150, SWP_SHOWWINDOW);

  View4->SetWindowPos(0, 0, 300, 1500, 1000, SWP_SHOWWINDOW);

//把视图移到原来的位置,即实现显示功能

MainFrame1->m_wndSplitter.DoScroll(View2,SB_LINEDOWN,TRUE);

  m_index=0;

              }

  MainFrame1->m_wndSplitter.SetScrollStyle(WS_HSCROLL);

在这里我们发现当人为改动窗口的大小是会恢复初始化的样子,为消除这种结果,还需处理一下:

在CmainFrame类里加入成员函数和成员变量:  int m_size;

void CMainFrame::OnSize(UINT nType, int cx, int cy),

m_size是为了防止初始化时窗口大小改变出现程序中断,同时它可以指向当前是隐藏还是显示视图;首先在

CMainFrame::OnCreateClient里初始化为    m_size=0;

CMyListView::OnLButtonDblClk里加入MainFrame1->m_size=1;

再者在CMainFrame::OnSize加入代码:

    if (m_size==1)

      {

      CMainFrame* MainFrame1=(CMainFrame*)this

    CMyEditView* View4=(CMyEditView*)MainFrame1->m_wndSplitter.GetPane(2,0);

    CMyListView* View1=(CMyListView*)MainFrame1->m_wndSplitter.GetPane(0,0);

    CMyTreeVIew* View2=(CMyTreeVIew*)MainFrame1->m_wndSplitter.GetPane(1,0);

      int num=View1->m_index;

      if (num==0)

      {

  View1->SetWindowPos(0, 0, 0, 1500 , 150, SWP_SHOWWINDOW);

  View2->SetWindowPos(0, 0, 150, 1500, 150, SWP_SHOWWINDOW);

  View4->SetWindowPos(0, 0, 300, 1500, 1000, SWP_SHOWWINDOW);

      }

      else if (num==1)

      {

  View1->SetWindowPos(0, 0, 0, 1500 , 1000, SWP_SHOWWINDOW);

  View2->SetWindowPos(0, 0, 1000, 1500, 1000, SWP_SHOWWINDOW);

  View4->SetWindowPos(0, 0, 1000, 1500, 1000, SWP_SHOWWINDOW);

      }  MainFrame1->m_wndSplitter.SetScrollStyle(WS_HSCROLL);}

上面的功能就消除了那种情况。

5.        报型列表的实现:

在CmyEditView类中加入成员函数进行报型列表视图的初始化

void CMyEditView::OnInitialUpdate()

在函数里加入代码:

      CListView::OnInitialUpdate();

      ListView_SetExtendedListViewStyle(GetListCtrl(), LVS_EX_FULLROWSELECT);

//当点击时这一行都变成选中状态

      CListCtrl & m_listView = GetListCtrl();

      m_listView.ModifyStyle(NULL, LVS_REPORT);

//修改属性参数

      LV_COLUMN lvColumn; //列表的结构类型  lvColumn.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|WS_CHILD|WS_BORDER|WS_GROUP|LVS_REPORT|LVS_EDITLABELS;

    lvColumn.fmt=LVCFMT_CENTER;

    lvColumn.cx=75;



    lvColumn.iSubItem=0;

    lvColumn.pszText="Column 0";

    m_listView.InsertColumn(0,&lvColumn);



    lvColumn.iSubItem=1;

    lvColumn.pszText="Column 1";

    m_listView.InsertColumn(1,&lvColumn);



    lvColumn.iSubItem=2;

    lvColumn.pszText="Column 2";

    m_listView.InsertColumn(2,&lvColumn);



    lvColumn.iSubItem=3;

    lvColumn.pszText="Column 3";

m_listView.InsertColumn(3,&lvColumn);

//报型列表行列的实现

头文件:

#include "stdafx.h"

#include "MyEdit.h"

#include "MyListView.h"

#include "MyEditDoc.h"

#include "MyEditView.h"

#include "MyTreeVIew.h"

#include "MainFrm.h"

6.        树型列表的实现:

在CMyTreeVIew类中加入成员函数进行树型列表视图的初始化

void CMyTreeVIew::OnInitialUpdate()

在函数里加入代码:

      CTreeView::OnInitialUpdate();

        CTreeCtrl & MytreeView = GetTreeCtrl();

  MytreeView.ModifyStyle(NULL, WS_VISIBLE|WS_CHILD|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_EDITLABELS);

//设置一些属性参数

  TVITEM tvItem; //树型的结构类型  tvItem.mask=WS_VISIBLE|WS_CHILD|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_HASBUTTONS;

  tvItem.pszText="Root";

  tvItem.cchTextMax=4;

  tvItem.iImage=0;

  tvItem.iSelectedImage=0;

  TVINSERTSTRUCT tvInsert;

  tvInsert.hParent=TVI_ROOT;

  tvInsert.hInsertAfter=TVI_FIRST;

  tvInsert.item=tvItem;

  HTREEITEM hRoot=MytreeView.InsertItem(&tvInsert);

//根目录

  tvItem.pszText="child Item 1";

  tvItem.cchTextMax=12;

  tvItem.iImage=1;

  tvItem.iSelectedImage=1;

  tvInsert.hParent=hRoot;

  tvInsert.hInsertAfter=TVI_FIRST;

  tvInsert.item=tvItem;

  HTREEITEM hChildItem=MytreeView.InsertItem(&tvInsert);



  tvItem.pszText="child Item 2";

  tvItem.cchTextMax=12;

  tvItem.iImage=2;

  tvItem.iSelectedImage=2;

  tvInsert.hParent=hChildItem;

  tvInsert.hInsertAfter=TVI_FIRST;

  tvInsert.item=tvItem;

  MytreeView.InsertItem(&tvInsert);



  tvItem.pszText="child Item 3";

  tvItem.cchTextMax=12;

  tvItem.iImage=1;

  tvItem.iSelectedImage=1;

  tvInsert.hParent=hRoot;

  tvInsert.hInsertAfter=TVI_LAST;

  tvInsert.item=tvItem;

  MytreeView.InsertItem(&tvInsert);



  tvItem.pszText="child Item 4";

  tvItem.cchTextMax=12;

  tvItem.iImage=1;

  tvItem.iSelectedImage=1;

  tvInsert.hParent=hRoot;

  tvInsert.hInsertAfter=TVI_LAST;

  tvInsert.item=tvItem;

  MytreeView.InsertItem(&tvInsert);

头文件:

#include "stdafx.h"

#include "MyEdit.h"

#include "MyTreeVIew.h"

#include "MyEditDoc.h"

#include "MainFrm.h"

#include "MyEditView.h"

7.        在类为CmyListView的视图里双击时把所在的这一行的信息传给类为CmyEditView的视图,在这里我们首先把CmyEditView类视图进行初始化,代码为:

void CMyEditView::OnInitialUpdate()

{

      CListView::OnInitialUpdate();

      ListView_SetExtendedListViewStyle(GetListCtrl(), LVS_EX_FULLROWSELECT);

      CListCtrl & m_listView = GetListCtrl();

      m_listView.ModifyStyle(NULL, LVS_REPORT);

      LV_COLUMN lvColumn;

    lvColumn.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|WS_CHILD|WS_BORDER|WS_GROUP|LVS_REPORT|LVS_EDITLABELS;

    lvColumn.fmt=LVCFMT_CENTER;

    lvColumn.cx=75;



    lvColumn.iSubItem=0;

    lvColumn.pszText="Column 0";

    m_listView.InsertColumn(0,&lvColumn);



    lvColumn.iSubItem=1;

    lvColumn.pszText="Column 1";

    m_listView.InsertColumn(1,&lvColumn);



    lvColumn.iSubItem=2;

    lvColumn.pszText="Column 2";

    m_listView.InsertColumn(2,&lvColumn);



    lvColumn.iSubItem=3;

    lvColumn.pszText="Column 3";

m_listView.InsertColumn(3,&lvColumn);

}

为了方面消息的传递在CmyEditDoc类里加入四个公共成员变量:

      CString str4;

      CString str3;

      CString str2;

      LPTSTR str1;

在BOOL CMyEditDoc::OnNewDocument()把这四个变量初始化为

  str1="";

  str2="";

  str3="";

  str4="";

为CmyEditView类里加入一个无返回值的自定义的公共函数

void CMyEditView::m_index()

在函数里加入代码:

CMyEditDoc *pDoc=GetDocument();

//获取文档指针

    CListCtrl & clc = GetListCtrl();

//获取当前视图list视图控件

LV_ITEM lvitem;

lvitem.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;

lvitem.state=0;

lvitem.stateMask=0;

lvitem.iImage=0;



lvitem.iItem=0;

lvitem.iSubItem=0;

lvitem.pszText=pDoc->str1;

clc.InsertItem(&lvitem);

clc.SetItemText(0,1,pDoc->str2);

clc.SetItemText(0,2,pDoc->str3);

clc.SetItemText(0,3,pDoc->str4);

//默认都插入第一行

void CMyListView::OnLButtonDblClk(UINT nFlags, CPoint point)函数里加入事件发生所产生的消息:

CMyEditDoc * pDoc=(class CMyEditDoc *)GetDocument();   

            int num=ListView_GetSelectionMark(m_listView);

//获取点击事件所发生的那一行

              if (num==0)

      {

              pDoc->str1="Item 0";

              pDoc->str2="Sub item 0.1";

              pDoc->str3="Sub item 0.2";

              pDoc->str4="Sub item 0.3";

              View4->m_int=1;

              View4->m_index();

//调用CmyEditView的函数m_index()

      }

              else if(num==1)

      {

              pDoc->str1="Item 1";

              pDoc->str2="Sub item 1.1";

              pDoc->str3="Sub item 1.2";

              pDoc->str4="Sub item 1.3";

              View4->m_int=1;

              View4->m_index();

      }

              else if (num==2)

      {

              pDoc->str1="Item 2";

              pDoc->str2="Sub item 2.1";

              pDoc->str3="Sub item 2.2";

              pDoc->str4="Sub item 2.3";

              View4->m_int=1;

              View4->m_index();

      }

//对四个变量在不同的情形下的赋值(字符串)

8.        在类为CMyTreeVIew的视图里当树型被展开时的信息传递

为了传递这样的消息,加入这样的函数void CMyTreeVIew::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult),在里面加入的代码为:

      NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

      CTreeCtrl & MytreeView = GetTreeCtrl();

      HTREEITEM index=TreeView_GetSelection(MytreeView);

    //获取当前的接点

      CMyEditDoc * pDoc=(class CMyEditDoc *)GetDocument();   

      if (TreeView_GetParent(MytreeView,index))

      {

              CMainFrame* MainFrame1=(CMainFrame*)this->GetParent()->GetParent();

        CMyEditView* View4=(CMyEditView*)MainFrame1->m_wndSplitter.GetPane(2,0);

        pDoc->str1="Child Item 2";

              pDoc->str2="";

              pDoc->str3="";

              pDoc->str4="";

              View4->m_index();

      }

      else

      {            CMainFrame* MainFrame1=(CMainFrame*)this->GetParent()->GetParent();

        CMyEditView* View4=(CMyEditView*)MainFrame1->m_wndSplitter.GetPane(2,0);

              pDoc->str1="Child Item 1";

              pDoc->str2="Child Item 3";

              pDoc->str3="Child Item 4";

              pDoc->str4="";

              View4->m_index();

      }

//这样的实现方案不太好,可以由HTREEITEM的变量值直接进行操作。

      *pResult = 0;

9.        其它一些函数或变量,如果不是MFC自动生成都是我个人测试所用,无实在的意义,可删去。

五.        运行结果:



六.        结论:

从这个文档视图的VC++6.0的实现,初步掌握了MFC的文档视图的操作,能够做一些稍微复杂的文档视图的可执行的程序,但我们也发现在这个程序里有许多不成功的地方。

1.        MainFrame1->m_wndSplitter.DeleteView(1,0);的功能没有实现,所以在程序运行时可以很明显的看到开始有分割条,但双击两次后发现分割条不见了。

2.        当分割条不见了,使用CsplitterWnd类的函数或参数没有成功的再现分割条。

3.        我只是把两个视图位置转移到看不到的位置,没有实现真正的动态的生成和删除视图。

4.        在我的程序里没有实现文档与视图的动态的联接的功能。

七.        推广:

在本程序还可以用  CTreeCtrl m_treeView;CListCtrl m_listView;这两个控件来实现,这样只要一个视图就行了。使用这种方案没有上面分割条的问题。由于这两个控件只有ID,而在MFC ClassWizard里没有它们的ID,所以使用这种方案不能向前面的消息传递,但可以通过OnNotify来实现:TV_DISPINFO *tv_dispinfo=(TV_DISPINFO *)lParam;

      if (tv_dispinfo->hdr.code==NM_CLICK)//TVN_ITEMEXPANDING)

      {

}


地主 发表时间: 04-06-03 04:09

论坛: 编程破解

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号