前面一節(jié)講了樹(shù)形控件Tree Control的簡(jiǎn)介、通知消息以及相關(guān)數(shù)據(jù)結(jié)構(gòu),本節(jié)繼續(xù)講下半部分,包括樹(shù)形控件的創(chuàng)建、CTreeCtrl類的主要成員函數(shù)和應(yīng)用實(shí)例。
樹(shù)形控件的創(chuàng)建
MFC為樹(shù)形控件提供了CTreeCtrl類,它封裝了樹(shù)形控件的所有操作。
樹(shù)形控件的創(chuàng)建也是有兩種方式,一種是在對(duì)話框模板中直接拖入Tree Control控件創(chuàng)建,另一種就是通過(guò)CTreeCtrl類的Create成員函數(shù)創(chuàng)建。下面主要講后者。
CTreeCtrl類的Create成員函數(shù)的原型如下:
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
此函數(shù)的原型與前面講到的所有控件類的Create函數(shù)都類似。dwStyle指定樹(shù)形控件風(fēng)格的組合,rect指定樹(shù)形控件窗口的位置和大小,pParentWnd為指向樹(shù)形控件父窗口的指針,nID指定樹(shù)形控件的ID。下面還是主要講講樹(shù)形控件的主要風(fēng)格以及含義。
同樣,動(dòng)態(tài)創(chuàng)建樹(shù)形控件時(shí),除了能夠指定上述風(fēng)格的組合外,一般還要指定WS_CHILD和WS_VISIBLE風(fēng)格。
在對(duì)話框模板中直接拖入Tree Control創(chuàng)建樹(shù)形控件時(shí),可以在樹(shù)形控件的屬性頁(yè)中設(shè)置其風(fēng)格,與上面的風(fēng)格是對(duì)應(yīng)的,例如,屬性Has Lines對(duì)應(yīng)的就是TVS_HASLINES風(fēng)格。
CTreeCtrl類的主要成員函數(shù)
CImageList* SetImageList(CImageList * pImageList,int nImageListType);
如果樹(shù)節(jié)點(diǎn)需要顯示圖標(biāo)時(shí),則必須先創(chuàng)建一個(gè)CImageList類的對(duì)象,并為其添加多個(gè)圖像組成一個(gè)圖像序列,然后調(diào)用SetImageList函數(shù)為樹(shù)形控件設(shè)置圖像序列,在用InsertItem插入節(jié)點(diǎn)時(shí)傳入所需圖像在圖像序列中的索引即可。后面的例子中會(huì)演示。參數(shù)pImageList為指向圖像序列類CImageList的對(duì)象的指針,若為NULL則刪除樹(shù)形控件的所有圖像。參數(shù)nImageListType指定圖像序列的類型,可以是TVSIL_NORMAL(普通圖像序列)或TVSIL_STATE(狀態(tài)圖像序列,用圖像表示節(jié)點(diǎn)的狀態(tài))。
UINT GetCount( ) const;
獲取樹(shù)形控件中節(jié)點(diǎn)的數(shù)量。
DWORD_PTR GetItemData(HTREEITEM hItem) const;
獲取樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)的附加32位數(shù)據(jù)。參數(shù)hItem為指定的樹(shù)節(jié)點(diǎn)的句柄。
BOOL SetItemData(HTREEITEM hItem,DWORD_PTR dwData);
為樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)設(shè)置附加的32位數(shù)據(jù)。參數(shù)hItem同上,dwData為要設(shè)置的32位數(shù)據(jù)。
CString GetItemText(HTREEITEM hItem) const;
獲取樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)的標(biāo)簽文本。參數(shù)hItem同上。返回值是包含標(biāo)簽文本的字符串。
BOOL SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);
為樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)設(shè)置標(biāo)簽文本。參數(shù)hItem同上,lpszItem為包含標(biāo)簽文本的字符串的指針。
HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const;
獲取樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)。參數(shù)hItem同上。返回值是下一個(gè)兄弟節(jié)點(diǎn)的句柄。
HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const;
獲取樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)的上一個(gè)兄弟節(jié)點(diǎn)。參數(shù)hItem同上。返回值是上一個(gè)兄弟節(jié)點(diǎn)的句柄。
HTREEITEM GetParentItem(HTREEITEM hItem) const;
獲取樹(shù)形控件中某個(gè)指定節(jié)點(diǎn)的父節(jié)點(diǎn)。參數(shù)hItem同上。返回值是父節(jié)點(diǎn)的句柄。
HTREEITEM GetRootItem( ) const;
獲取樹(shù)形控件根節(jié)點(diǎn)的句柄。
HTREEITEM GetSelectedItem( ) const;
獲取樹(shù)形控件當(dāng)前選中節(jié)點(diǎn)的句柄。
BOOL DeleteAllItems( );
刪除樹(shù)形控件中的所有節(jié)點(diǎn)。刪除成功則返回TRUE,否則返回FALSE。
BOOL DeleteItem(HTREEITEM hItem);
刪除樹(shù)形控件中的某個(gè)節(jié)點(diǎn)。參數(shù)hItem為要?jiǎng)h除的節(jié)點(diǎn)的句柄。刪除成功則返回TRUE,否則返回FALSE。
HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST);
在樹(shù)形控件中插入一個(gè)新節(jié)點(diǎn)。參數(shù)lpszItem為新節(jié)點(diǎn)的標(biāo)簽文本字符串的指針,參數(shù)nImage為新節(jié)點(diǎn)的圖標(biāo)在樹(shù)形控件圖像序列中的索引,參數(shù)nSelectedImage為新節(jié)點(diǎn)被選中時(shí)的圖標(biāo)在圖像序列中的索引,參數(shù)hParent為插入節(jié)點(diǎn)的父節(jié)點(diǎn)的句柄,參數(shù)hInsertAfter為新節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)的句柄,即新節(jié)點(diǎn)將被插入到hInsertAfter節(jié)點(diǎn)之后。
BOOL SelectItem(HTREEITEM hItem);
選中指定的樹(shù)節(jié)點(diǎn)。參數(shù)hItem為要選擇的節(jié)點(diǎn)的句柄。若成功則返回TRUE,否則返回FALSE。
樹(shù)形控件的應(yīng)用實(shí)例
最后還是給大家寫一個(gè)簡(jiǎn)單的實(shí)例,說(shuō)明CListCtrl類的幾個(gè)成員函數(shù)及樹(shù)形控件通知消息等的使用方法。
此實(shí)例實(shí)現(xiàn)的功能:在一個(gè)樹(shù)形控件中顯示網(wǎng)站的簡(jiǎn)單結(jié)構(gòu)分層,共有三層,分別為網(wǎng)站、各個(gè)分類和文章。用鼠標(biāo)左鍵單擊改變選中節(jié)點(diǎn)后,將選中節(jié)點(diǎn)的文本顯示到編輯框中。另外,還要實(shí)現(xiàn)一個(gè)常見(jiàn)的效果,就是鼠標(biāo)劃過(guò)除根節(jié)點(diǎn)外的某個(gè)樹(shù)節(jié)點(diǎn)時(shí),顯示相應(yīng)的Tip提示信息。下面是具體實(shí)現(xiàn)步驟:
1. 創(chuàng)建一個(gè)基于對(duì)話框的MFC工程,名稱設(shè)置為“Example31”。
2. 在自動(dòng)生成的對(duì)話框模板IDD_EXAMPLE31_DIALOG中,刪除“TODO: Place dialog controls here.”靜態(tài)文本框、“OK”按鈕和“Cancel”按鈕。添加一個(gè)Tree Control控件,ID設(shè)置為IDC_WEB_TREE,屬性Has Buttons、Has Lines和Lines At Root都設(shè)為True,為了在鼠標(biāo)劃過(guò)某個(gè)節(jié)點(diǎn)時(shí)顯示提示信息還需要將Info Tip屬性設(shè)為True。再添加一個(gè)靜態(tài)文本框和一個(gè)編輯框,靜態(tài)文本框的Caption屬性設(shè)為“您選擇的節(jié)點(diǎn):”,編輯框的ID設(shè)為IDC_ITEM_SEL_EDIT,Read Only屬性設(shè)為True。此時(shí)的對(duì)話框模板如下圖:
3. 導(dǎo)入需要為樹(shù)形控件的節(jié)點(diǎn)添加的圖標(biāo)。在這里找了三個(gè)32x32的Icon圖標(biāo),保存到工程的res目錄下。然后在Resource View資源視圖中,右鍵點(diǎn)擊Icon節(jié)點(diǎn),在右鍵菜單中選擇“Add Resource...”,彈出“Add Resource”對(duì)話框,再?gòu)淖筮叀癛esource type”列表中選擇“Icon”,點(diǎn)擊右邊的“Import...”按鈕,就可以選擇三個(gè)圖標(biāo)文件進(jìn)行導(dǎo)入了。導(dǎo)入成功后,分別修改它們ID為IDI_WEB_ICON、IDI_CATALOG_ICON和IDI_ARTICLE_ICON。
4. 為樹(shù)形控件IDC_WEB_TREE添加CTreeCtrl類型的控件變量m_webTree。并在Example31Dlg.h文件中為CExample31Dlg類添加成員對(duì)象:CImageList m_imageList;。
5. 在對(duì)話框初始化時(shí),我們?cè)跇?shù)形控件中添加網(wǎng)站的樹(shù)形結(jié)構(gòu),那么需要修改CExample31Dlg::OnInitDialog()函數(shù)為:
BOOL CExample31Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); ......略 // TODO: Add extra initialization here HICON hIcon[3]; // 圖標(biāo)句柄數(shù)組 HTREEITEM hRoot; // 樹(shù)的根節(jié)點(diǎn)的句柄 HTREEITEM hCataItem; // 可表示任一分類節(jié)點(diǎn)的句柄 HTREEITEM hArtItem; // 可表示任一文章節(jié)點(diǎn)的句柄 // 加載三個(gè)圖標(biāo),并將它們的句柄保存到數(shù)組 hIcon[0] = theApp.LoadIcon(IDI_WEB_ICON); hIcon[1] = theApp.LoadIcon(IDI_CATALOG_ICON); hIcon[2] = theApp.LoadIcon(IDI_ARTICLE_ICON); // 創(chuàng)建圖像序列CImageList對(duì)象 m_imageList.Create(32, 32, ILC_COLOR32, 3, 3); // 將三個(gè)圖標(biāo)添加到圖像序列 for (int i=0; i<3; i++) { m_imageList.Add(hIcon[i]); } // 為樹(shù)形控件設(shè)置圖像序列 m_webTree.SetImageList(&m_imageList, TVSIL_NORMAL); // 插入根節(jié)點(diǎn) hRoot = m_webTree.InsertItem(_T("雞啄米"), 0, 0); // 在根節(jié)點(diǎn)下插入子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("IT互聯(lián)網(wǎng)"), 1, 1, hRoot, TVI_LAST); // 為“IT互聯(lián)網(wǎng)”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hCataItem, 1); // 在“IT互聯(lián)網(wǎng)”節(jié)點(diǎn)下插入子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("百度文章1"), 2, 2, hCataItem, TVI_LAST); // 為“百度文章1”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 2); // 在“IT互聯(lián)網(wǎng)”節(jié)點(diǎn)下插入另一子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("谷歌文章2"), 2, 2, hCataItem, TVI_LAST); // 為“谷歌文章2”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 3); // 在根節(jié)點(diǎn)下插入第二個(gè)子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("數(shù)碼生活"), 1, 1, hRoot, TVI_LAST); // 為“數(shù)碼生活”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hCataItem, 4); // 在“數(shù)碼生活”節(jié)點(diǎn)下插入子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("智能手機(jī)文章1"), 2, 2, hCataItem, TVI_LAST); // 為“智能手機(jī)文章1”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 5); // 在“數(shù)碼生活”節(jié)點(diǎn)下插入另一子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("平板電腦文章2"), 2, 2, hCataItem, TVI_LAST); // 為“平板電腦文章2”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 6); // 在根節(jié)點(diǎn)下插入第三個(gè)子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("軟件開(kāi)發(fā)"), 1, 1, hRoot, TVI_LAST); // 為“軟件開(kāi)發(fā)”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hCataItem, 7); // 在“軟件開(kāi)發(fā)”節(jié)點(diǎn)下插入子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("C++編程入門系列1"), 2, 2, hCataItem, TVI_LAST); // 為“C++編程入門系列1”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 8); // 在“軟件開(kāi)發(fā)”節(jié)點(diǎn)下插入另一子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("VS2010/MFC編程入門2"), 2, 2, hCataItem, TVI_LAST); // 為“VS2010/MFC編程入門2”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 9); // 在根節(jié)點(diǎn)下插入第四個(gè)子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("娛樂(lè)休閑"), 1, 1, hRoot, TVI_LAST); // 為“娛樂(lè)休閑”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hCataItem, 10); // 在“娛樂(lè)休閑”節(jié)點(diǎn)下插入子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("瑪雅文明文章1"), 2, 2, hCataItem, TVI_LAST); // 為“瑪雅文明文章1”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 11); // 在“娛樂(lè)休閑”節(jié)點(diǎn)下插入另一子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("IT笑話2"), 2, 2, hCataItem, TVI_LAST); // 為“IT笑話2”節(jié)點(diǎn)添加附加的編號(hào)數(shù)據(jù),在鼠標(biāo)劃過(guò)該節(jié)點(diǎn)時(shí)顯示 m_webTree.SetItemData(hArtItem, 12); return TRUE; // return TRUE unless you set the focus to a control }
6. 我們希望在選中節(jié)點(diǎn)改變時(shí),將最新的選擇項(xiàng)實(shí)時(shí)顯示到編輯框中,那么可以響應(yīng)TVN_SELCHANGED通知消息。為樹(shù)形控件IDC_WEB_TREE的通知消息TVN_SELCHANGED添加消息處理函數(shù)CExample31Dlg::OnTvnSelchangedWebTree,并修改函數(shù)體如下:
void CExample31Dlg::OnTvnSelchangedWebTree(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // TODO: Add your control notification handler code here *pResult = 0; CString strText; // 樹(shù)節(jié)點(diǎn)的標(biāo)簽文本字符串 // 獲取當(dāng)前選中節(jié)點(diǎn)的句柄 HTREEITEM hItem = m_webTree.GetSelectedItem(); // 獲取選中節(jié)點(diǎn)的標(biāo)簽文本字符串 strText = m_webTree.GetItemText(hItem); // 將字符串顯示到編輯框中 SetDlgItemText(IDC_ITEM_SEL_EDIT, strText); }
7. 還有一個(gè)功能需要實(shí)現(xiàn),那就是鼠標(biāo)劃過(guò)除根節(jié)點(diǎn)外的某個(gè)樹(shù)節(jié)點(diǎn)時(shí),顯示相應(yīng)的Tip提示信息,本實(shí)例中提示信息為節(jié)點(diǎn)的編號(hào)。這需要響應(yīng)TVN_GETINFOTIP通知消息。為樹(shù)形控件IDC_WEB_TREE的通知消息TVN_GETINFOTIP添加消息處理函數(shù)CExample31Dlg::OnTvnGetInfoTipWebTree,并修改函數(shù)體如下:
void CExample31Dlg::OnTvnGetInfoTipWebTree(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR); // TODO: Add your control notification handler code here *pResult = 0; NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR; // 將傳入的pNMHDR轉(zhuǎn)換為NMTVGETINFOTIP指針類型 HTREEITEM hRoot = m_webTree.GetRootItem(); // 獲取樹(shù)的根節(jié)點(diǎn) CString strText; // 每個(gè)樹(shù)節(jié)點(diǎn)的提示信息 if (pTVTipInfo->hItem == hRoot) { // 如果鼠標(biāo)劃過(guò)的節(jié)點(diǎn)是根節(jié)點(diǎn),則提示信息為空 strText = _T(""); } else { // 如果鼠標(biāo)劃過(guò)的節(jié)點(diǎn)不是根節(jié)點(diǎn),則將該節(jié)點(diǎn)的附加32位數(shù)據(jù)格式化為字符串 strText.Format(_T("%d"), pTVTipInfo->lParam); } // 將strText字符串拷貝到pTVTipInfo結(jié)構(gòu)體變量的pszText成員中,這樣就能顯示內(nèi)容為strText的提示信息 wcscpy(pTVTipInfo->pszText, strText); }
8. 運(yùn)行程序,彈出結(jié)果對(duì)話框。效果如下圖:
樹(shù)形控件的知識(shí)就講到這里了,相比之前的控件可能稍有復(fù)雜。不過(guò)用的多了,就會(huì)覺(jué)得得心應(yīng)手了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。
|
新聞熱點(diǎn)
疑難解答
圖片精選