MFC之Frame-Splitter模型

Posted htj10

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

// CMainFrame

IMPLEMENT_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("未能创建视图窗口
");
    //    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("未能创建工具栏
");
        return -1;      // 未能创建
    }

    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("未能创建状态栏
");
        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 _DEBUG
void 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);
}
View Code

LeftView.cpp

技术图片
// LeftView.cpp : 实现文件
//

#include "stdafx.h"
#include "sp.h"
#include "LeftView.h"


// CLeftView

IMPLEMENT_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 _DEBUG
void CLeftView::AssertValid() const
{
    CTreeView::AssertValid();
}

#ifndef _WIN32_WCE
void 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;
}
View Code

RightView.cpp

技术图片
// RightView.cpp : 实现文件
//

#include "stdafx.h"
#include "sp.h"
#include "RightView.h"


// CRightView

IMPLEMENT_DYNCREATE(CRightView, CListView)

CRightView::CRightView() :m_list(GetListCtrl())
{

}

CRightView::~CRightView()
{
}

BEGIN_MESSAGE_MAP(CRightView, CListView)
END_MESSAGE_MAP()


// CRightView 诊断

#ifdef _DEBUG
void CRightView::AssertValid() const
{
    CListView::AssertValid();
}

#ifndef _WIN32_WCE
void 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;
    }
}
View Code

运行结果:

技术图片

 

以上是关于MFC之Frame-Splitter模型的主要内容,如果未能解决你的问题,请参考以下文章

c++编程 qt mfc

MFC之实现无边窗口移动

面向面试编程代码片段之GC

AJAX相关JS代码片段和部分浏览器模型

MFC之简单计算器

使用片段时 Intellij 无法正确识别 Thymeleaf 模型变量