创建非模态对话框,并同时介绍Tree和List控件的使用。
非模态对话框的特征之一是在其关闭之前,程序可以继续执行其它部分。非模态对话框一般用来显示信息,或者实时地进行各种设置。
创建非模态对话框资源的方法与创建模态对话框资源的方法是相同的,不同之处在于,视类中显示对话框必须调用不同的函数,显示模态对话框所调用的函数为:DoModal()(CDialogModal m_Dlg;),显示非模态对话框所调用的函数为:Create()。
下面我们以创建如下图所示的非模态对话框为例,讨论非模态对话框的创建以及Tree控件、List控件的使用。
所设计的对话框如下图所示:
程序将C盘根目录下的目录加入到Tree控件中,把根目录下的文件加入到List控件中。如果用鼠标在Tree框中选择根下的各子目录,则被选目录下的所有文件列表会自动显示在List框中。
1. 编辑对话框资源、添加Tree和List控件
(1)对话框的标识号为IDD_FILELIST_DIALOG,其余属性均取默认值。
(2)对话框上所添加的各个控件的主要属性设置:
控件 | ID号 | 主要属性 |
Tree Control | IDC_TREE | Styles标签上的下列三项被选:Has buttons Has lines Lines at root |
List Control | IDC_SEX2 | Styles | View:Report |
Button | IDC_INSTEREST1 | Caption:确定 |
其它属性为择默认值。2.为新增的对话框创建对话框类
类名为:CDialogFileList,该类的头文件和源文件名自动命名为:DialogFileList.h和DialogFileList.cpp
创建方法:略
3.添加菜单资源
与该对话框相对应的菜单功能项是对话框 | 文件选择,其资源标识号为:ID_DIALOG_FILELISTDIALOG,其Caption为:文件选择(&S)。
操作步骤:略
4. 在视类中添加菜单响应函数及相关成员
菜单命令是由视类来响应的,因此必须在该类中添加菜单命令响应函数(本例为OnDialogFileList()函数),该函数与COMMAND消息有关。
在视类中还要定义一个指向非模态对话框对象的指针成员,在菜单命令的响应函数中通过该指针动态地建立为非模态对话框,该指针必须在视类的构造函数进行初始化,并在视类的析构函数中释放。
1)在视类中添加指向对话框的指针成员
(1) 执行视类数据成员的添加操作(Add Member Variable),完成如下设置:
Variable Type(成员类型):CDialogFileList*;
Variable Name:m_pFileListDlg;
(2)修改视类的Head文件
因为视类中含有类型为对话框类指针的成员,所以必须在视类的Head文件中包含对话框类的Head 文件:
#include “DialogFileList.h”
2)添加菜单消息响应函数
函数名:OnDialogFilelistdialog();
该函数对应的菜单项目ID为:(Object ID:ID_DIALOG_MODALDIALOG);
该函数对应的消息为:COMMAND
(2)该函数的代码:
void CDialogView::OnDialogFilelistdialog()
{
// TODO: Add your command handler code here
if (m_pFileListDlg == NULL)
{
//如果指针指向NULL,说明对话框未创建,则动态创建之
m_pFileListDlg = new CDialogFileList;
m_pFileListDlg->Create (IDD_FILELIST_DIALOG,this);
}
//显示非模态对话框
m_pFileListDlg->ShowWindow(SW_SHOW);//显示模态对话框的命令是m_Dlg.DoModal()
}
(注意:显示非模态对话框与显示模态对话框的区别,下面的代码用来显示模态对话框:
CDialogFileList m_Dlg;
m_Dlg.DoModal();)
操作步骤:略
3)修改视类的构造函数和析构函数
(1) 在构造函数添加将对话框指针初始化为NULL,其代码如下:
CDialogView::CDialogView()
{
// TODO: add construction code here
m_pFileListDlg = NULL;//初始化非模态对话框指针
}
(2)在析构函数中释放对话框所占的内存空间,其代码如下:
CDialogView::~CDialogView()
{
if (m_pFileListDlg!=NULL)
delete m_pFileListDlg;//释放非模态对话框对象所占空间
}
5.为新增的对话框类添加成员
1)添加数据成员
(1)所添加的数据成员如下:
控件ID | 成员类型 | 成员名 | 备注 |
IDC_LIST | CListCtrl | m_List | List控件对象 |
IDC_Tree | CTreeCtrl | m_Tree | Tree控件对象 |
(2)操作步骤:
略。
2)添加成员函数
(1)添加如下函数:
① 初始化函数
该函数执行Tree框和List框的初始设置。
函数名:OnInitDialog();
对应的Object Ids:CDialogFileList;
对应的Message是WM_INITDIALOG;
函数代码:
BOOL CDialogFileList::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
//往List控件中插入一列
m_List.InsertColumn(0,"文件名",LVCFMT_LEFT,150,-1);
TV_INSERTSTRUCT TreeItem;
HTREEITEM hTreeItem;
TreeItem.hInsertAfter=TVI_LAST;
TreeItem.item.mask=TVIF_TEXT|TVIF_PARAM;
//第一级
CString str="C:\\";//C盘根目录上的文件
TreeItem.hParent = TVI_ROOT;//父级为根目录
TreeItem.item.pszText = str.GetBuffer(50);//设置缓冲区的大小并赋值
TreeItem.item.lParam =1;//对于根目录,设置为1
hTreeItem = m_Tree.InsertItem(&TreeItem);//插入Tree控件中
int number=0;//计算文件数
CFileFind file;
BOOL bfind;
CString str1;
//第二级
TreeItem.hParent = hTreeItem;
TreeItem.item.lParam=10;//对于子目录,设置为10
bfind = file.FindFile("C:\\*.*");//查找C盘根目录下的所有文件和子目录
while (bfind) //如果文件存在
{
bfind = file.FindNextFile();//查找下一个文件
if (file.IsDirectory()) //判断是否为子目录
{
//得到目录名并复制字符串
strcpy(TreeItem.item.pszText,file.GetFileName());
hTreeItem = m_Tree.InsertItem(&TreeItem);//将子目录插入到Tree控件中
}
else //不是子目录,则插入到List控件中
{
str1 = file.GetFileName();//得到文件名
m_List.InsertItem(number,str1);//将文件名插入到List控件的第number行
number++;
}
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
② 文件目录选择函数
该函数响应用户在Tree框中所选中的目录条目上单击鼠标左键,并将该文件目录的所有文件信息显示在List框中。
- 函数名:OnSelchangedTree();
- 对应的Object Ids:IDC_TREE;
- 对应的Message:TVN_SELCHANGED;
函数代码:
void CDialogFileList::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
CString str1,str2;
//获取当前被选择的Tree View项
HTREEITEM CurItem = m_Tree.GetSelectedItem();
TV_ITEM TreeItem;
TreeItem.hItem = CurItem;
m_Tree.GetItem(&TreeItem);//获取指定Tree View项的属性
//获取当前选中项的文本
str1 = m_Tree.GetItemText(m_Tree.GetSelectedItem());
long CurlParam = TreeItem.lParam;//当前条目的序号
if (CurlParam != 1)//如果是子目录
{
//获取当前被选项的父项
TreeItem.hItem = m_Tree.GetParentItem(m_Tree.GetSelectedItem());
m_Tree.GetItem (&TreeItem);
CurItem = TreeItem.hItem;
//获取当前被选项的文本
str2 = m_Tree.GetItemText(CurItem);
str2+=str1;
str2+="\\";
}
else
str2=str1;
m_List.DeleteAllItems();//删除List控件中的所有项
CFileFind file;
BOOL bFind;
int number = 0;
str2+="*.*";
bFind = file.FindFile (str2);//在当前目录中查找文件
while (bFind) //如果文件存在
{
bFind = file.FindNextFile();//查找下一个文件
if (!file.IsDirectory()) //判断是否为子目录
{
//如果不是目录,插入到List控件中
str1 =file.GetFileName();//得到文件名
m_List.InsertItem(number,str1);//将文件名插入到List控件的第number行
number++;
}
}
UpdateData (false);//更新控件中的值
*pResult = 0;
}
③ 确认按钮响应函数
- 该函数响应用户单击确认按钮,关闭对话框。
- 函数名:OnOk();
- 对应的Object Ids:IDOK;
- 对应的Message:BN_CLICKED。
函数代码:
void CDialogFileList::OnOK()
{
// TODO: Add extra validation here
CDialog::OnCancel();//退出非模态对话框
}
6.项目的编译、链接和运行