演练:使用新的 MFC Shell 控件
在本演练中,你将创建一个类似于文件资源管理器的应用程序。 你将创建包含两个窗格的窗口。 左侧窗格包含一个 CMFCShellTreeCtrl 对象,该对象在分层视图中显示桌面。 右侧窗格包含一个 CMFCShellListCtrl,该对象显示左侧窗格中选择的文件夹中的文件。
先决条件
在 Visual Studio 2017 和更高版本中,MFC 支持是一个可选组件。 若要安装它,请从 Windows“开始”菜单打开 Visual Studio 安装程序。 找到你正在使用的 Visual Studio 版本,然后选择“修改”按钮。 确保选中“使用 C++ 的桌面开发”磁贴。 在“可选组件”下,选中“MFC 支持”按钮。
本演练假设已将 Visual Studio 设置为使用“常规开发设置”。 如果你使用其他开发设置,在本演练中使用的某些 Visual Studio 窗口默认可能不会显示。
使用 MFC 应用程序向导创建新的 MFC 应用程序
这些步骤根据你使用的 Visual Studio 版本而有所不同。 若要查看 Visual Studio 首选项的文档,请使用“版本”选择器控件。 它位于此页面上目录表的顶部。
在 Visual Studio 中创建 MFC 项目
在主菜单中,选择“文件”>“新建”>“项目”,打开“创建新项目”对话框。
在顶部的搜索框中键入“MFC”,然后从结果列表中选择“MFC 应用”。
单击“下一步”。 在下一页中,输入项目的名称,并根据需要指定项目位置。
选择“创建”按钮创建项目。
显示“MFC 应用程序向导”后,使用以下选项:
选择左侧的“应用程序类型”。 然后依次选择“单个文档”和“文档/查看体系结构支持”。 在“项目样式”下选择“Visual Studio”,然后从“视觉样式和颜色”下拉列表中选择“Office 2007 (蓝色主题)”。
在“复合文档支持”窗格中选择“无”。
不要对“文档模板属性”窗格进行任何更改。
在“用户界面功能”窗格中,确保选择了“使用菜单栏和工具栏”选项。 将所有其他选项保留原样。
在“高级功能”窗格中,选择“ActiveX 控件”、“通用控件清单”和“导航窗格”选项。 其他所有内容保持原样。 “导航窗格”选项会使向导在窗口左侧创建已嵌入
CMFCShellTreeCtrl
的窗格。我们不会对“生成的类”窗格进行任何更改,因此请单击“完成”以创建新的 MFC 项目。
在 Visual Studio 2017 或更低版本中创建 MFC 项目
使用“MFC 应用程序向导”创建新的 MFC 应用程序。 若要运行该向导,请从“文件”菜单中选择“新建”,然后选择“项目”。 此时会显示“新建项目”对话框。
在“新建项目”对话框中,展开“项目类型”窗格中的“Visual C++”节点并选择“MFC”。 然后,在“模板”窗格中选择“MFC 应用程序”。 键入项目的名称(例如
MFCShellControls
),然后单击“确定”。显示“MFC 应用程序向导”后,使用以下选项:
在“应用程序类型”窗格中的“应用程序类型”下,清除“选项卡式文档”选项。 接下来,依次选择“单个文档”和“文档/查看体系结构支持”。 在“项目样式”下选择“Visual Studio”,然后从“视觉样式和颜色”下拉列表中选择“Office 2007 (蓝色主题)”。
在“复合文档支持”窗格中选择“无”。
不要对“文档模板字符串”窗格进行任何更改。
在“数据库支持”窗格(Visual Studio 2015 和更低版本)中选择“无”,因为该应用程序不使用数据库。
在“用户界面功能”窗格中,确保选择了“使用菜单栏和工具栏”选项。 将所有其他选项保留原样。
在“高级功能”窗格中的“高级功能”下,仅选择“ActiveX 控件”和“通用控件清单”。 在“高级框架窗格”下,仅选择“导航窗格”选项。 该选项会使向导在窗口左侧创建已嵌入
CMFCShellTreeCtrl
的窗格。我们不会对“生成的类”窗格进行任何更改,因此请单击“完成”以创建新的 MFC 项目。
通过生成并运行应用程序来验证其是否已成功创建。 若要生成应用程序,请从“生成”菜单中选择“生成解决方案”。 如果成功生成了该应用程序,请在“调试”菜单中选择“开始调试”来运行该应用程序。
向导会自动创建一个应用程序,该应用程序带有标准的菜单栏、标准的工具栏、标准的状态栏和位于窗口左侧的 Outlook 栏,其中包含“文件夹”视图和“日历”视图。
将 shell 列表控件添加到文档视图
在本部分,你会将一个
CMFCShellListCtrl
实例添加到向导创建的视图。 在“解决方案资源管理器”中双击“MFCShellControlsView.h”打开视图头文件。找到靠近头文件顶部的
#pragma once
指令。 紧接在此指令的下方添加以下代码以包含CMFCShellListCtrl
的头文件:#include <afxShellListCtrl.h>
现在添加一个类型为
CMFCShellListCtrl
的成员变量。 首先,在头文件中找到以下注释:// Generated message map functions
紧靠在该注释的上方添加以下代码:
private: CMFCShellListCtrl m_wndList;
“MFC 应用程序向导”已在
CMainFrame
类中创建了一个CMFCShellTreeCtrl
对象,但该对象是一个受保护的成员。 我们稍后将访问该对象,因此现在请为它创建一个访问器。 在“解决方案资源管理器”中双击 MainFrm.h 头文件以将它打开。 找到以下注释:// Attributes
紧接在该注释的下方添加以下方法声明:
public: CMFCShellTreeCtrl& GetShellTreeCtrl();
接下来,在“解决方案资源管理器”中双击 MainFrm.cpp 源文件以将它打开。 在该文件的底部添加以下方法定义:
CMFCShellTreeCtrl& CMainFrame::GetShellTreeCtrl() { return m_wndTree; }
现在我们更新
CMFCShellControlsView
类以处理WM_CREATE
窗口消息。 打开“类视图”窗口并选择CMFCShellControlsView
类。 右键单击并选择 “属性”。接下来,在类向导中单击“消息”选项卡。向下滚动,直到看到
WM_CREATE
消息。 在WM_CREATE
旁边的下拉菜单中,选择“<Add> OnCreate”。 该命令创建一个消息处理程序并自动更新 MFC 消息映射。现在,我们在
OnCreate
方法中创建CMFCShellListCtrl
对象。 在 MFCShellControlsView.cpp 源文件中找到OnCreate
方法定义,并将其实现替换为以下代码:int CMFCShellControlsView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; CRect rectDummy (0, 0, 0, 0); m_wndList.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT, rectDummy, this, 1); return 0; }
针对
WM_SIZE
消息重复上一步骤。 这样,每当用户更改应用程序窗口的大小时,应用程序视图就会重绘。 将OnSize
方法的定义替换为以下代码:void CMFCShellControlsView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); m_wndList.SetWindowPos(NULL, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); }
最后一步是使用 CMFCShellTreeCtrl::SetRelatedList 方法连接
CMFCShellTreeCtrl
和CMFCShellListCtrl
对象。 调用CMFCShellTreeCtrl::SetRelatedList
后,CMFCShellListCtrl
将自动显示CMFCShellTreeCtrl
中所选项的内容。 我们在通过 CView::OnActivateView 重写的OnActivateView
方法中连接对象。在 MFCShellControlsView.h 头文件中的
CMFCShellControlsView
类声明内添加以下方法声明:protected: virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView);
接下来,将该方法的定义添加到 MFCShellControlsView.cpp 源文件中:
void CMFCShellControlsView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { if (bActivate&& AfxGetMainWnd() != NULL) { ((CMainFrame*)AfxGetMainWnd())->GetShellTreeCtrl().SetRelatedList(&m_wndList); } CView::OnActivateView(bActivate, pActivateView, pDeactiveView); }
由于我们要从
CMainFrame
类调用方法,因此必须在 MFCShellControlsView.cpp 源文件的顶部添加一个#include
指令:#include "MainFrm.h"
通过生成并运行应用程序来验证其是否已成功创建。 若要生成应用程序,请从“生成”菜单中选择“生成解决方案”。 如果成功生成了该应用程序,请在“调试”菜单中选择“开始调试”来运行该应用程序。
现在应会在视图窗格中看到
CMFCShellTreeCtrl
中所选项的详细信息。 单击CMFCShellTreeCtrl
中的节点时,CMFCShellListCtrl
会自动更新。 同样,如果双击CMFCShellListCtrl
中的文件夹,CMFCShellTreeCtrl
应会自动更新。右键单击树控件或列表控件中的任何项。 你将看到一个上下文菜单,它与使用真正的“文件资源管理器”时显示的菜单相同。
后续步骤
向导创建了一个包含“文件夹”窗格和“日历”窗格的 Outlook 栏。 在“资源管理器”窗口中包含“日历”窗格可能没有意义,因此现在请删除该窗格。
CMFCShellListCtrl
支持以不同的模式查看文件,例如“大图标”、“小图标”、“列表”和“详细信息”。 更新应用程序以实现此功能。 提示:参阅 Visual C++ 示例。