MFC控制元件程式設計:列表控制元件、樹控制元件、屬性頁對話方塊 (未完)

eldn__發表於2014-08-01

一、列表控制元件

     先直觀的認識下吧:

      工具欄裡的位置:

   

拖出來是這個樣子:


  MFC的所有可見的控制元件都只是一種視窗,要想操作它們必須通過MFC中和其相關聯的類中提供的函式

  和列表控制元件相關的類:

           CListCtrl   :列表控制元件,父類是CWnd類,控制元件類,故常用在對話方塊程式中。

           CListView :列表檢視,父類是CCtrlView類,檢視類,故常用在文件檢視應用程式中。

                                  該類可以通過呼叫CListView::GetListCtrl()函式,返回相關的列表控制元件。

  列表控制元件有四種顯示方式(樣式): ICon (圖示)、Small ICon(小圖示)、List(列表)、Report(報表) 

  CListCtrl類的使用:

   這裡我編寫一個顯示指定路徑下所有檔案並且雙擊列表專案能進入到相應目錄,然後重新設定列表控制元件為選中路徑下的檔案列表的程式。

   新建一個普通的對話方塊程式,拖放一個List Control控制元件,然後在其上面放置一個Combo Box控制元件(新增列表控制元件的四種顯示樣式資料)以便後面選擇切換不同的樣式

 

為List Control 控制元件關聯名為m_wndListCtrl的控制元件變數,為Combo Box 關聯名為m_wndComboBox的控制元件變數

為了顯示列表控制元件圖示,新建兩個點陣圖資源(一套大圖示,一套小圖示)


新增CImageList成員m_ilNormal、m_ilSmall     : 儲存圖示列表

新增CStringLis成員m_strListPath : 儲存列表控制元件裡的路徑資訊

private:
	CStringList m_strListPath;
	CImageList m_ilSmall;
	CImageList m_ilNormal;

給我們工程的Dlg類新增一個成員函式InitListCtrl用來初始化並顯示顯示控制元件,程式碼如下:

void CCListCtrlDlg::InitListCtrl()
{
	// 為保證統一性初始設定組合框為Report
	m_wndComboBox.SetCurSel (3);

	// 建立圖示列表
	m_ilNormal.Create (IDB_BITMAP_NORMAL, 32, 1, RGB (255, 255, 255));
	m_ilSmall.Create (IDB_BITMAP_SMALL, 16, 1, RGB (255, 255, 255));

	// 設定圖示列表
	m_wndListCtrl.SetImageList (&m_ilNormal, LVSIL_NORMAL);
	m_wndListCtrl.SetImageList (&m_ilSmall, LVSIL_SMALL);

	// 新增ListCtrl表頭
        m_wndListCtrl.InsertColumn (0, "Name", LVCFMT_LEFT, 100);
	m_wndListCtrl.InsertColumn (1, "Type", LVCFMT_LEFT, 100);
	m_wndListCtrl.InsertColumn (2, "Size", LVCFMT_LEFT, 100);
	m_wndListCtrl.InsertColumn (3, "LastWriteTime", LVCFMT_LEFT, 150);

	// 為ListCtrl設定背景圖片,記得先初始化Ole元件,設定字型背景為透明
	AfxOleInit ();
	m_wndListCtrl.SetTextBkColor (CLR_NONE);
	m_wndListCtrl.SetBkImage ("D:/1.jpg");
}

關於List Control 控制元件的資料的插入(這裡以Report樣式為列):

      1 首先呼叫CListCtrl::InsertColumn 插入表頭資訊

      2 呼叫CListCtrl::InsertItem 插入每行的第一列

     3  呼叫CListCtrl::SetItemText 插入每行的其餘列資料


另外: 在ClistCtrl::SetBkImage的函式說明中有提到使用該函式必須先初始化


AfxOleInit ();
新增顯示指定路徑的函式ShowPath (strPath)

void CCListCtrlDlg::ShowPath(CString strPath)
{
	// 顯示列表控制元件之前清空控制元件和控制元件路徑資訊m_strListPath
	m_wndListCtrl.DeleteAllItems ();
	m_strListPath.RemoveAll ();

	// 查詢strPath(D:)目錄下的所有(*.*)檔案
	strPath += "/*.*";

	CFileFind find;
	BOOL bRet = find.FindFile (strPath);
	if (!bRet)
		return;
	int nItem = 0;
	while (bRet)
	{
		bRet = find.FindNextFile ();
		if (bRet == -1)
			return;
		if (find.IsDirectory ())
		{
			m_wndListCtrl.InsertItem (nItem, find.GetFileName(), 1);// Name
			m_wndListCtrl.SetItemText (nItem, 1, "Directory");// Type
			
		}
		else
		{
			m_wndListCtrl.InsertItem (nItem, find.GetFileName(), 0);// Name
			m_wndListCtrl.SetItemText (nItem, 1, find.GetFileName ().Mid (find.GetFileTitle().GetLength() + 1));// Type
                        // Size
			DWORD dSize = find.GetLength () / 1024;
			CString strFileSize;
			strFileSize.Format ("%d KB", dSize);
			m_wndListCtrl.SetItemText (nItem, 2, strFileSize);
			// LastWriteTime
			CTime tm;
			find.GetLastWriteTime (tm);
		        CString strLastWriteTime;
		  	strLastWriteTime = tm.Format ("%Y-%m-%d, %H-%M-%S");
			m_wndListCtrl.SetItemText (nItem, 3, strLastWriteTime);

		}
		// 儲存路徑
		m_strListPath.AddTail (find.GetFilePath());
		++nItem;
	}
}

這裡使用CStringList物件儲存路徑資訊,每次顯示CListCtrl是都清空一次,這樣也具備CListCtrl::SetItemData關聯資料的效果還能有效防止記憶體洩漏

為了能雙擊進入列表控制元件選中的目錄,為ClistCtrl新增NMDBCLK事件響應函式,編寫如下程式碼:

void CCListCtrlDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	LPNMITEMACTIVATE pItem = (LPNMITEMACTIVATE)pNMHDR;
        ShowPath (m_strListPath.GetAt (m_strListPath.FindIndex (pItem->iItem)));
	
	*pResult = 0;
}

最後給組合框控制元件新增CBN_SELCHANGE訊息響應事件,編寫如下程式碼:

void CCListCtrlDlg::OnSelchangeCombo() 
{
	// TODO: Add your control notification handler code here
	int nSel = m_wndComboBox.GetCurSel ();
	switch (nSel)
	{
	case 0:// 圖示
		m_wndListCtrl.ModifyStyle (LVS_LIST | LVS_REPORT | LVS_SMALLICON, LVS_ICON);
		break;
	case 1:// 小圖示
		m_wndListCtrl.ModifyStyle (LVS_ICON | LVS_REPORT | LVS_LIST, LVS_SMALLICON);
		break;
	case 2:// 列表
		m_wndListCtrl.ModifyStyle (LVS_ICON | LVS_SMALLICON | LVS_REPORT, LVS_LIST);
		break;
	case 3:// 報表
		m_wndListCtrl.ModifyStyle (LVS_ICON | LVS_SMALLICON | LVS_LIST, LVS_REPORT);
		break;
	}
}

這裡奇怪的是呼叫CListCtrl::ModifyStyle如果後列表控制元件立刻就做響應的改變,推測MFC在該函式內部呼叫了使列表控制元件重繪的函式。

程式執行截圖:


二、 樹控制元件

       和樹控制元件相關的類:

      CTreeCtrl  :樹控制元件 ,父類是CWnd,故通常在對話方塊程式中使用

      CTreeView :樹檢視,父類是CCtrlView,故通常在文件檢視應用程式中使用, 該類GetTreeCtrl可以獲取樹控制元件,把對樹檢視的操作轉化為對樹控制元件的操作

     下面介紹CTreeCtrl的使用:

      

      同樣建立一個基於對話方塊的程式,拖放一個Tree Control控制元件並且為之關聯一個控制元件變數m_wndTreeCtrl

      設定控制元件的樣式如下:

      

     這裡由於樹控制元件的節點有選中和未選中兩種狀態,每種狀態需設定不同的圖示,故新建一個圖示資源包含兩個圖示,為Dlg類新增一個CImageList的成員:m_ilNormal

     新增控制元件初始化函式InitTreeCtrl()函式並在OnInitDialog中呼叫,InitTreeCtrl()函式如下:

    

void CMFCTreeDlg::InitTreeCtrl()
{
	// 建立圖示列表
	m_ilNormal.Create (IDB_BITMAP_NORMAL, 32, 1, RGB (255, 255, 255));
	// 設定圖示列表
	m_wndTreeCtrl.SetImageList (&m_ilNormal, TVSIL_NORMAL);
	// 設定節點高度
	m_wndTreeCtrl.SetItemHeight (36);

	// 插入根節點
	HTREEITEM hRoot1 = m_wndTreeCtrl.InsertItem ("root1", 0, 1);
	
	// 插入子節點, 其中的0表示未選中的圖示序號,1表示選中時的圖示序號
	HTREEITEM hChild1 = m_wndTreeCtrl.InsertItem ("Child-One", 0, 1, hRoot1);
	HTREEITEM hChild2 = m_wndTreeCtrl.InsertItem ("Child-Tow", 0, 1, hRoot1);
	HTREEITEM hChild3 = m_wndTreeCtrl.InsertItem ("Child-Three", 0, 1, hRoot1);
	HTREEITEM hChild5= m_wndTreeCtrl.InsertItem ("Child-Four", 0, 1, hRoot1);
	// 注意這裡插入到hChild3之後
	HTREEITEM hChild4 = m_wndTreeCtrl.InsertItem ("Child-One", 0, 1, hRoot1, hChild3);

	HTREEITEM hRoot2 = m_wndTreeCtrl.InsertItem ("root2", 0, 1);
	hChild1 = m_wndTreeCtrl.InsertItem ("Child-One", 0, 1, hRoot2);
	hChild2 = m_wndTreeCtrl.InsertItem ("Child-Tow", 0, 1, hRoot2);
    hChild3 = m_wndTreeCtrl.InsertItem ("Child-Three", 0, 1, hRoot2);

	// 設定展開狀態
	m_wndTreeCtrl.Expand (hRoot2, TVE_EXPAND);
}

注意其中的CTreeCtrl::InsertItem函式的慘數:

 HTREEITEM InsertItem(
      PCTSTR lpszItem,//樹節點的文字 
      int nImage,//未選中時圖示索引 
      int nSelectedImage,//選中時的圖示索引 
      HTREEITEM hParent = TVI_ROOT,//如果使用預設值,則插入的節點是根節點;如果指定該引數,該引數作為節點的父節點。 
      HTREEITEM hInsertAfter = TVI_LAST//在某個節點後插入當前節點。如果不指定該引數,在末尾新增節點
     ); 

程式執行截圖:






     

     

     

相關文章