前面一節講了樹形控制項Tree Control的簡介、通知訊息以及相關資料結構,本節繼續講下半部分,包括樹形控制項的建立、CTreeCtrl類的主要成員函數和應用執行個體。
樹形控制項的建立
MFC為樹形控制項提供了CTreeCtrl類,它封裝了樹形控制項的所有操作。
樹形控制項的建立也是有兩種方式,一種是在對話方塊模板中直接拖入Tree Control控制項建立,另一種就是通過CTreeCtrl類的Create成員函數建立。下面主要講後者。
CTreeCtrl類的Create成員函數的原型如下:
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
此函數的原型與前面講到的所有控制項類的Create函數都類似。dwStyle指定樹形控制項風格的組合,rect指定樹形控制項視窗的位置和大小,pParentWnd為指向樹形控制項父視窗的指標,nID指定樹形控制項的ID。下面還是主要講講樹形控制項的主要風格以及含義。
TVS_DISABLEDRAGDROP:禁止樹形控制項發送TVN_BEGINDRAG通知訊息,即不支援拖動操作
TVS_EDITLABELS:使用者可以編輯節點的標籤文本
TVS_HASBUTTONS:顯示帶有"+"或"-"的小方框來表示某項能否被展開或已展開
TVS_HASLINES:在父節點與子節點間連線以更清晰地顯示樹的結構
TVS_LINESATROOT:在根節點處連線
TVS_SHOWSELALWAYS:即使控制項失去輸入焦點,仍顯示出項的選擇狀態
同樣,動態建立樹形控制項時,除了能夠指定上述風格的組合外,一般還要指定WS_CHILD和WS_VISIBLE風格。
在對話方塊模板中直接拖入Tree Control建立樹形控制項時,可以在樹形控制項的屬性頁面中設定其風格,與上面的風格是對應的,例如,屬性Has Lines對應的就是TVS_HASLINES風格。
CTreeCtrl類的主要成員函數
CImageList* SetImageList(CImageList * pImageList,int nImageListType);
如果樹節點需要顯示表徵圖時,則必須先建立一個CImageList類的對象,並為其添加多個映像組成一個映像序列,然後調用SetImageList函數為樹形控制項設定映像序列,在用InsertItem插入節點時傳入所需映像在映像序列中的索引即可。後面的例子中會示範。參數pImageList為指向映像序列類CImageList的對象的指標,若為NULL則刪除樹形控制項的所有映像。參數nImageListType指定映像序列的類型,可以是TVSIL_NORMAL(普通映像序列)或TVSIL_STATE(狀態映像序列,用映像表示節點的狀態)。
UINT GetCount( ) const;
擷取樹形控制項中節點的數量。
DWORD_PTR GetItemData(HTREEITEM hItem) const;
擷取樹形控制項中某個指定節點的附加32位元據。參數hItem為指定的樹節點的控制代碼。
BOOL SetItemData(HTREEITEM hItem,DWORD_PTR dwData);
為樹形控制項中某個指定節點設定附加的32位元據。參數hItem同上,dwData為要設定的32位元據。
CString GetItemText(HTREEITEM hItem) const;
擷取樹形控制項中某個指定節點的標籤文本。參數hItem同上。傳回值是包含標籤文本的字串。
BOOL SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);
為樹形控制項中某個指定節點設定標籤文本。參數hItem同上,lpszItem為包含標籤文本的字串的指標。
HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const;
擷取樹形控制項中某個指定節點的下一個兄弟節點。參數hItem同上。傳回值是下一個兄弟節點的控制代碼。
HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const;
擷取樹形控制項中某個指定節點的上一個兄弟節點。參數hItem同上。傳回值是上一個兄弟節點的控制代碼。
HTREEITEM GetParentItem(HTREEITEM hItem) const;
擷取樹形控制項中某個指定節點的父節點。參數hItem同上。傳回值是父節點的控制代碼。
HTREEITEM GetRootItem( ) const;
擷取樹形控制項根節點的控制代碼。
HTREEITEM GetSelectedItem( ) const;
擷取樹形控制項當前選中節點的控制代碼。
BOOL DeleteAllItems( );
刪除樹形控制項中的所有節點。刪除成功則返回TRUE,否則返回FALSE。
BOOL DeleteItem(HTREEITEM hItem);
刪除樹形控制項中的某個節點。參數hItem為要刪除的節點的控制代碼。刪除成功則返回TRUE,否則返回FALSE。
HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST);
在樹形控制項中插入一個新節點。參數lpszItem為新節點的標籤文本字串的指標,參數nImage為新節點的表徵圖在樹形控制項映像序列中的索引,參數nSelectedImage為新節點被選中時的表徵圖在映像序列中的索引,參數hParent為插入節點的父節點的控制代碼,參數hInsertAfter為新節點的前一個節點的控制代碼,即新節點將被插入到hInsertAfter節點之後。
BOOL SelectItem(HTREEITEM hItem);
選中指定的樹節點。參數hItem為要選擇的節點的控制代碼。若成功則返回TRUE,否則返回FALSE。
樹形控制項的應用執行個體
最後還是給大家寫一個簡單的執行個體,說明CListCtrl類的幾個成員函數及樹形控制項通知訊息等的使用方法。
此執行個體實現的功能:在一個樹形控制項中顯示網站的簡單結構分層,共有三層,分別為網站、各個分類和文章。用滑鼠左鍵單擊改變選中節點後,將選中節點的文本顯示到編輯框中。另外,還要實現一個常見的效果,就是滑鼠划過除根節點外的某個樹節點時,顯示相應的Tip提示資訊。下面是具體實現步驟:
1. 建立一個基於對話方塊的MFC工程,名稱設定為“Example31”。
2. 在自動產生的對話方塊模板IDD_EXAMPLE31_DIALOG中,刪除“TODO: Place dialog controls here.”靜態文字框、“OK”按鈕和“Cancel”按鈕。添加一個Tree Control控制項,ID設定為IDC_WEB_TREE,屬性Has Buttons、Has Lines和Lines At Root都設為True,為了在滑鼠划過某個節點時顯示提示資訊還需要將Info Tip屬性設為True。再添加一個靜態文字框和一個編輯框,靜態文字框的Caption屬性設為“您選擇的節點:”,編輯框的ID設為IDC_ITEM_SEL_EDIT,Read Only屬性設為True。此時的對話方塊模板如:
3. 匯入需要為樹形控制項的節點添加的表徵圖。在這裡找了三個32x32的Icon表徵圖,儲存到工程的res目錄下。然後在Resource View資源檢視中,右鍵點擊Icon節點,在右鍵菜單中選擇“Add Resource...”,彈出“Add Resource”對話方塊,再從左邊“Resource type”列表中選擇“Icon”,點擊右邊的“Import...”按鈕,就可以選擇三個表徵圖檔案進行匯入了。匯入成功後,分別修改它們ID為IDI_WEB_ICON、IDI_CATALOG_ICON和IDI_ARTICLE_ICON。
4. 為樹形控制項IDC_WEB_TREE添加CTreeCtrl類型的控制項變數m_webTree。並在Example31Dlg.h檔案中為CExample31Dlg類新增成員對象:CImageList m_imageList;。
5. 在對話方塊初始化時,我們在樹形控制項中添加網站的樹形結構,那麼需要修改CExample31Dlg::OnInitDialog()函數為:
BOOL CExample31Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); ......略 // TODO: Add extra initialization here HICON hIcon[3]; // 表徵圖控制代碼數組 HTREEITEM hRoot; // 樹的根節點的控制代碼 HTREEITEM hCataItem; // 可表示任一分類節點的控制代碼 HTREEITEM hArtItem; // 可表示任一文章節點的控制代碼 // 載入三個表徵圖,並將它們的控制代碼儲存到數組 hIcon[0] = theApp.LoadIcon(IDI_WEB_ICON); hIcon[1] = theApp.LoadIcon(IDI_CATALOG_ICON); hIcon[2] = theApp.LoadIcon(IDI_ARTICLE_ICON); // 建立映像序列CImageList對象 m_imageList.Create(32, 32, ILC_COLOR32, 3, 3); // 將三個表徵圖添加到映像序列 for (int i=0; i<3; i++) { m_imageList.Add(hIcon[i]); } // 為樹形控制項設定映像序列 m_webTree.SetImageList(&m_imageList, TVSIL_NORMAL); // 插入根節點 hRoot = m_webTree.InsertItem(_T("雞啄米"), 0, 0); // 在根節點下插入子節點 hCataItem = m_webTree.InsertItem(_T("IT互連網"), 1, 1, hRoot, TVI_LAST); // 為“IT互連網”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hCataItem, 1); // 在“IT互連網”節點下插入子節點 hArtItem = m_webTree.InsertItem(_T("百度文章1"), 2, 2, hCataItem, TVI_LAST); // 為“百度文章1”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 2); // 在“IT互連網”節點下插入另一子節點 hArtItem = m_webTree.InsertItem(_T("Google文章2"), 2, 2, hCataItem, TVI_LAST); // 為“Google文章2”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 3); // 在根節點下插入第二個子節點 hCataItem = m_webTree.InsertItem(_T("數位生活"), 1, 1, hRoot, TVI_LAST); // 為“數位生活”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hCataItem, 4); // 在“數位生活”節點下插入子節點 hArtItem = m_webTree.InsertItem(_T("智能手機文章1"), 2, 2, hCataItem, TVI_LAST); // 為“智能手機文章1”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 5); // 在“數位生活”節點下插入另一子節點 hArtItem = m_webTree.InsertItem(_T("平板電腦文章2"), 2, 2, hCataItem, TVI_LAST); // 為“平板電腦文章2”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 6); // 在根節點下插入第三個子節點 hCataItem = m_webTree.InsertItem(_T("軟體開發"), 1, 1, hRoot, TVI_LAST); // 為“軟體開發”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hCataItem, 7); // 在“軟體開發”節點下插入子節點 hArtItem = m_webTree.InsertItem(_T("C++編程入門系列1"), 2, 2, hCataItem, TVI_LAST); // 為“C++編程入門系列1”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 8); // 在“軟體開發”節點下插入另一子節點 hArtItem = m_webTree.InsertItem(_T("VS2010/MFC編程入門2"), 2, 2, hCataItem, TVI_LAST); // 為“VS2010/MFC編程入門2”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 9); // 在根節點下插入第四個子節點 hCataItem = m_webTree.InsertItem(_T("娛樂休閑"), 1, 1, hRoot, TVI_LAST); // 為“娛樂休閑”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hCataItem, 10); // 在“娛樂休閑”節點下插入子節點 hArtItem = m_webTree.InsertItem(_T("瑪雅文明文章1"), 2, 2, hCataItem, TVI_LAST); // 為“瑪雅文明文章1”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 11); // 在“娛樂休閑”節點下插入另一子節點 hArtItem = m_webTree.InsertItem(_T("IT笑話2"), 2, 2, hCataItem, TVI_LAST); // 為“IT笑話2”節點添加附加的編號資料,在滑鼠划過該節點時顯示 m_webTree.SetItemData(hArtItem, 12); return TRUE; // return TRUE unless you set the focus to a control }
6. 我們希望在選中節點改變時,將最新的選擇項即時顯示到編輯框中,那麼可以響應TVN_SELCHANGED通知訊息。為樹形控制項IDC_WEB_TREE的通知訊息TVN_SELCHANGED添加訊息處理函數CExample31Dlg::OnTvnSelchangedWebTree,並修改函數體如下:
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; // 樹節點的標籤文本字串 // 擷取當前選中節點的控制代碼 HTREEITEM hItem = m_webTree.GetSelectedItem(); // 擷取選中節點的標籤文本字串 strText = m_webTree.GetItemText(hItem); // 將字串顯示到編輯框中 SetDlgItemText(IDC_ITEM_SEL_EDIT, strText); }
7. 還有一個功能需要實現,那就是滑鼠划過除根節點外的某個樹節點時,顯示相應的Tip提示資訊,本執行個體中提示資訊為節點的編號。這需要響應TVN_GETINFOTIP通知訊息。為樹形控制項IDC_WEB_TREE的通知訊息TVN_GETINFOTIP添加訊息處理函數CExample31Dlg::OnTvnGetInfoTipWebTree,並修改函數體如下:
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轉換為NMTVGETINFOTIP指標類型 HTREEITEM hRoot = m_webTree.GetRootItem(); // 擷取樹的根節點 CString strText; // 每個樹節點的提示資訊 if (pTVTipInfo->hItem == hRoot) { // 如果滑鼠划過的節點是根節點,則提示資訊為空白 strText = _T(""); } else { // 如果滑鼠划過的節點不是根節點,則將該節點的附加32位元據格式化為字串 strText.Format(_T("%d"), pTVTipInfo->lParam); } // 將strText字串拷貝到pTVTipInfo結構體變數的pszText成員中,這樣就能顯示內容為strText的提示資訊 wcscpy(pTVTipInfo->pszText, strText); }
8. 運行程式,彈出結果對話方塊。效果如:
樹形控制項的知識就講到這裡了,相比之前的控制項可能稍有複雜。不過用的多了,就會覺得得心應手了。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援topic.alibabacloud.com。