非模態(Modalless)對話框,又叫做無模式對話框,當用戶打開非模態對話框時,依然可以操作其他窗口。非模態對話框允許用戶在處理非模態對話框的同時處理目標對話框。上次的練習已經說明了Modalless與Modal的區別,此處就不贅述。
這次將做一個窗口使看見某目錄下的文件,以C盤爲例。
Ⅰ、創建對話框類並且添加控件
1>在Resource的IDR_DIALOGTYPE裏,在“查看”裏添加菜單項,取名“非模態對話框(&E)”
2>如下創建對話框,並設置相關屬性
ID | 控件 | 屬性 |
---|---|---|
IDC_TREE | Tree Control | 選中Has buttons、Has lines和Lines at root |
IDC_LIST | List Control | Styles|View: Report |
IDC_OK | Button | Caption:OK |
IDC_CANCEL | Button | Caption:Cancel |
Ⅱ、顯示非模態對話框
由於模態對話框生存週期較長,通常和父級窗口一樣長。爲此,我們使用非模態對話框指針,在父級窗口類的構造函數當中或菜單響應函數中動態爲指針分配空間並顯示對話框。最後記得在CDialogView的析構函數當中釋放指針的空間。
1>在DialogView.h裏添加#include "DialogModalless.h"
2>在CDialogView裏Add member variable,添加類型爲CDialogModalless*,名稱爲m_pModallessDlg
3>按下Ctrl+W,並在Class name裏選CDialogView,在Object IDs裏選ID_VIEW_MODALLESSDIALOG,在Message裏選COMMAND,最後以默認函數名Add Function並進行Edit Code。相關代碼如下:
void CDialogView::OnViewModallessdialog()
{
// TODO: Add your command handler code here
if(NULL == m_pModallessDlg)
{
m_pModallessDlg = new CDialogModalless;
m_pModallessDlg->Create(IDD_MODALLESS_DIALOG,this);
}
m_pModallessDlg->ShowWindow(SW_SHOW);//顯示非模態對話框
}
4>修改視類的構造與析構函數
CDialogView::CDialogView()
{
// TODO: add construction code here
m_pModallessDlg = NULL;
}
CDialogView::~CDialogView()
{
if(NULL == m_pModallessDlg)
delete m_pModallessDlg;
}
Ⅲ、實現對話框功能
1>爲之前添加的相關控件添加變量如下
控件 | Type | Member |
IDC_LIST | ClistCtrl | m_List |
IDC_Tree | CteeCtrl | m_Tree |
2>按下Ctrl+W,在Class name裏選中CDialogModalless,在Object IDs裏選中CDialogModalless,在Message裏選中WM_INITDIALOG,最後Add Function
3>在Object IDs裏選中ID_OK、ID_CANCEL和IDC_TREE,在Message裏分別選中BN_CLICKED(OK與CANCEL)與TVN_SELCHANGED,添加OnOK()、OnCancel()和OnSelchangedTree()函數。相關代碼添加如下:
BOOL CDialogModalless::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:\\";
TreeItem.hParent = TVI_ROOT;//父級爲根部
TreeItem.item.pszText = str.GetBuffer(50);//設置緩衝區大小並賦值
TreeItem.item.lParam = 1;//對於根目錄,設置爲
hTreeItem = m_Tree.InsertItem(&TreeItem);//插入Tree控件
int number = 0;//計算文件個數
CFileFind file;
BOOL bfind;
CString temp;
//第二級
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控件
{
temp = file.GetFileName();//獲取文件名
m_List.InsertItem(number, temp);//將文件插入第number行
++number;
}
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CDialogModalless::OnOK()
{
// TODO: Add extra validation here
CDialog::OnOK();
}
void CDialogModalless::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
CString temp,str;
//獲取當前被選的tree view項
HTREEITEM CurItem = m_Tree.GetSelectedItem();
TV_ITEM TreeItem;
TreeItem.hItem = CurItem;
m_Tree.GetItem(&TreeItem);//獲取指定的tree view屬性
temp = m_Tree.GetItemText(m_Tree.GetSelectedItem());//獲取當前條目的序號
long CurlParam = TreeItem.lParam;//當前條目序號
if (1 != CurlParam)//若爲子目錄
{
//獲取當前被選項的父親
TreeItem.hItem = m_Tree.GetParentItem(m_Tree.GetSelectedItem());
m_Tree.GetItem(&TreeItem);
CurItem = TreeItem.hItem;
//獲取當前選中項的文本
str = m_Tree.GetItemText(CurItem);
str += temp;
str += "\\";
}
else str = temp;
m_List.DeleteAllItems();//刪除控件中所有的項
CFileFind file;
BOOL bFind;
int number = 0;
str += "*.*";
bFind = file.FindFile(str);//在str目錄下查找
while(bFind)//一旦找到
{
bFind = file.FindNextFile();
if(!file.IsDirectory())//判斷是否爲目錄,不是插入List控件
{
temp = file.GetFileName();
m_List.InsertItem(number, temp);
++number;
}
}
UpdateData(false);//更新控件值
*pResult = 0;
}
void CDialogModalless::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
}
4>運行檢測效果,記得是在多文檔的“查看”菜單下運行這個非模態對話框。