|
![]() | 作者: 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号