MFC Frame-Splitter模型实例原理解析

1. 新建一个SDI工程,去掉“Document/View architecture support”

2. 添加 CTreeView 类的派生类 CLeftView 作为分隔器的左侧视图,添加 CListView 的派生类 CRightView 作为右边视图。可能需要 #include <afxcview.h>

3. 在CLeftView类中添加成员变量 CTreeCtrl& m_tree; 在CRightView类中添加成员变量 CListCtrl& m_list; 并在构造函数中初始化

CLeftView::CLeftView() :m_tree(GetTreeCtrl()){}CRightView::CRightView() :m_list(GetListCtrl()){}

4. 在主框架类 CMainFrame 类的头文件中,去掉 CChildView 类变量,添加 CSplitterWnd m_split;CLeftView* m_pLeftView;CRightView* m_pRightView;在CMainFrame的cpp文件中去掉CChildView的相关代码。

在CMainFrame类中添加虚函数OnCreateClient,该函数是在基类函数 CFrameWnd::OnCreate 执行的过程中回调OnCreateClient函数,主要用于创建视图类等客户区子窗口。

在CLeftView类中添加虚函数OnInitUpdate,该函数创建类之后第一个进入的函数,类似对话框的OnInitDialog函数。再添加TVN_SELCHANGEED消息映射函数,并修改代码调用CRightView的Refresh函数。

在CRightView类中添加虚函数OnInitUpdate,添加普通成员函数 Refresh。

代码如下:

MainFrm.cpp

// MainFrm.cpp : CMainFrame 类的实现//#include "stdafx.h"#include "sp.h"#include "MainFrm.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// CMainFrameIMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)  ON_WM_CREATE()  ON_WM_SETFOCUS()END_MESSAGE_MAP()static UINT indicators[] ={  ID_SEPARATOR,      // 状态行指示器  ID_INDICATOR_CAPS,  ID_INDICATOR_NUM,  ID_INDICATOR_SCRL,};// CMainFrame 构造/析构CMainFrame::CMainFrame(){  // TODO: 在此添加成员初始化代码}CMainFrame::~CMainFrame(){}BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext){  // TODO: 在此添加专用代码和/或调用基类  if (!m_split.CreateStatic(this, 1, 2))    return FALSE;  m_split.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(150, 0), NULL);  m_split.CreateView(0, 1, RUNTIME_CLASS(CRightView), CSize(0, 0), NULL);  m_pLeftView = (CLeftView*)m_split.GetPane(0, 0);  m_pRightView = (CRightView*)m_split.GetPane(0, 1);  return TRUE;  //  return CFrameWnd::OnCreateClient(lpcs, pContext);}int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){  if (CFrameWnd::OnCreate(lpCreateStruct) == -1)    return -1;  // 创建一个视图以占用框架的工作区  //if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))  //{  //  TRACE0("未能创建视图窗口\n");  //  return -1;  //}  if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||    !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))  {    TRACE0("未能创建工具栏\n");    return -1;   // 未能创建  }  if (!m_wndStatusBar.Create(this))  {    TRACE0("未能创建状态栏\n");    return -1;   // 未能创建  }  m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));  // TODO: 如果不需要可停靠工具栏,则删除这三行  m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);  EnableDocking(CBRS_ALIGN_ANY);  DockControlBar(&m_wndToolBar);  return 0;}BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs){  if( !CFrameWnd::PreCreateWindow(cs) )    return FALSE;  // TODO: 在此处通过修改  // CREATESTRUCT cs 来修改窗口类或样式  cs.dwExStyle &= ~WS_EX_CLIENTEDGE;  cs.lpszClass = AfxRegisterWndClass(0);    return TRUE;}// CMainFrame 诊断#ifdef _DEBUGvoid CMainFrame::AssertValid() const{  CFrameWnd::AssertValid();}void CMainFrame::Dump(CDumpContext& dc) const{  CFrameWnd::Dump(dc);}#endif //_DEBUG// CMainFrame 消息处理程序void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/){  // 将焦点前移到视图窗口//  m_wndView.SetFocus();  m_pLeftView->SetFocus();}BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo){  // 让视图第一次尝试该命令  //if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))  //  return TRUE;  CWnd* pWnd = GetFocus();  if (pWnd && pWnd != this && pWnd->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))  {    return TRUE;  }  // 否则,执行默认处理  return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);}

LeftView.cpp

// LeftView.cpp : 实现文件//#include "stdafx.h"#include "sp.h"#include "LeftView.h"// CLeftViewIMPLEMENT_DYNCREATE(CLeftView, CTreeView)CLeftView::CLeftView() :m_tree(GetTreeCtrl()){}CLeftView::~CLeftView(){}BEGIN_MESSAGE_MAP(CLeftView, CTreeView)  ON_NOTIFY_REFLECT(TVN_SELCHANGED, &CLeftView::OnTvnSelchanged)END_MESSAGE_MAP()// CLeftView 诊断#ifdef _DEBUGvoid CLeftView::AssertValid() const{  CTreeView::AssertValid();}#ifndef _WIN32_WCEvoid CLeftView::Dump(CDumpContext& dc) const{  CTreeView::Dump(dc);}#endif#endif //_DEBUG// CLeftView 消息处理程序void CLeftView::OnInitialUpdate(){  CTreeView::OnInitialUpdate();  // TODO: 在此添加专用代码和/或调用基类  if (m_tree.GetChildItem(NULL))    return;  m_tree.ModifyStyle(0, TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS);  HTREEITEM hItem = m_tree.InsertItem(_T("我的电脑"));  char buf[100];  DWORD len = GetLogicalDriveStringsA(sizeof(buf) / sizeof(buf[0]), buf);//获取的buf,例如c:\&;null>d:\&;null><null>   char *p = buf;  CString str;  while (*p)  {    str = p;    int nLen = str.GetLength();    if (nLen < 1)      break;    if ('\\' == str[nLen - 1])      str = str.Left(nLen - 1);    m_tree.InsertItem(str, hItem);    p += nLen + 1;  }  m_tree.Expand(hItem, TVE_EXPAND);}#include "MainFrm.h"void CLeftView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult){  LPNMTREEVIEW p = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);  // TODO: 在此添加控件通知处理程序代码  HTREEITEM hItem = p->itemNew.hItem;  CString szPath;  if (hItem != m_tree.GetRootItem())    szPath = m_tree.GetItemText(hItem);  CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();  pFrame->m_pRightView->Refresh(szPath);  *pResult = 0;}

RightView.cpp

// RightView.cpp : 实现文件//#include "stdafx.h"#include "sp.h"#include "RightView.h"// CRightViewIMPLEMENT_DYNCREATE(CRightView, CListView)CRightView::CRightView() :m_list(GetListCtrl()){}CRightView::~CRightView(){}BEGIN_MESSAGE_MAP(CRightView, CListView)END_MESSAGE_MAP()// CRightView 诊断#ifdef _DEBUGvoid CRightView::AssertValid() const{  CListView::AssertValid();}#ifndef _WIN32_WCEvoid CRightView::Dump(CDumpContext& dc) const{  CListView::Dump(dc);}#endif#endif //_DEBUG// CRightView 消息处理程序void CRightView::OnInitialUpdate(){  CListView::OnInitialUpdate();  // TODO: 在此添加专用代码和/或调用基类  if (m_list.GetStyle() & LVS_REPORT)    return;  m_list.ModifyStyle(0, LVS_REPORT);  m_list.InsertColumn(0, _T("名称"), 0, 120);  m_list.InsertColumn(1, _T("大小"), 0, 120);  m_list.InsertColumn(2, _T("类型"), 0, 120);  m_list.InsertColumn(3, _T("修改日期"), 0, 120);}void CRightView::Refresh(CString szPath){  m_list.DeleteAllItems();  if (szPath.IsEmpty())    return;  CFileFind ff;  BOOL b = ff.FindFile(szPath + _T("/*.*"));  int i = 0;  while (b)  {    b = ff.FindNextFile();    if (ff.IsDots())      continue;    m_list.InsertItem(i, ff.GetFileName());    if (ff.IsDirectory())      m_list.SetItemText(i, 2, _T("文件夹"));    else    {      int nLen = ff.GetLength() / 1024;      if (!nLen)        nLen = 1;      szPath.Format(_T("%d kb"), nLen);      m_list.SetItemText(i, 1, szPath);      m_list.SetItemText(i, 2, _T("文件"));    }    FILETIME ft;    ff.GetLastWriteTime(&ft);    COleDateTime time(ft);    szPath.Format(_T("%d-%02d-%02d %02d:%02d:%02d"),      time.GetYear(), time.GetMonth(), time.GetDay(),       time.GetHour(), time.GetMinute(), time.GetSecond());    m_list.SetItemText(i, 3, szPath);    ++i;  }}

运行结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

即使是不成熟的尝试,也胜于胎死腹中的策略。

MFC Frame-Splitter模型实例原理解析

相关文章:

你感兴趣的文章:

标签云: