天天看點

VS2010/MFC程式設計入門之三十一(常用控件:樹形控件Tree Control 下)

http://www.jizhuomi.com/software/203.html

  前面一節講了樹形控件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。此時的對話框模闆如下圖:

VS2010/MFC程式設計入門之三十一(常用控件:樹形控件Tree Control 下)

       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()函數為:

C++代碼

  1. BOOL CExample31Dlg::OnInitDialog()   
  2. {   
  3.     CDialogEx::OnInitDialog();   
  4.          ......略   
  5.     // TODO: Add extra initialization here   
  6.     HICON hIcon[3];      // 圖示句柄數組   
  7.     HTREEITEM hRoot;     // 樹的根節點的句柄   
  8.     HTREEITEM hCataItem; // 可表示任一分類節點的句柄   
  9.     HTREEITEM hArtItem;  // 可表示任一文章節點的句柄   
  10.     // 加載三個圖示,并将它們的句柄儲存到數組   
  11.     hIcon[0] = theApp.LoadIcon(IDI_WEB_ICON);   
  12.     hIcon[1] = theApp.LoadIcon(IDI_CATALOG_ICON);   
  13.     hIcon[2] = theApp.LoadIcon(IDI_ARTICLE_ICON);   
  14.     // 建立圖像序列CImageList對象   
  15.     m_imageList.Create(32, 32, ILC_COLOR32, 3, 3);   
  16.     // 将三個圖示添加到圖像序列   
  17.     for (int i=0; i<3; i++)   
  18.     {   
  19.         m_imageList.Add(hIcon[i]);   
  20.     }   
  21.     // 為樹形控件設定圖像序列   
  22.     m_webTree.SetImageList(&m_imageList, TVSIL_NORMAL);   
  23.     // 插入根節點   
  24.     hRoot = m_webTree.InsertItem(_T("雞啄米"), 0, 0);   
  25.     // 在根節點下插入子節點   
  26.     hCataItem = m_webTree.InsertItem(_T("IT網際網路"), 1, 1, hRoot, TVI_LAST);   
  27.     // 為“IT網際網路”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  28.     m_webTree.SetItemData(hCataItem, 1);   
  29.     // 在“IT網際網路”節點下插入子節點   
  30.     hArtItem = m_webTree.InsertItem(_T("百度文章1"), 2, 2, hCataItem, TVI_LAST);   
  31.     // 為“百度文章1”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  32.     m_webTree.SetItemData(hArtItem, 2);   
  33.     // 在“IT網際網路”節點下插入另一子節點   
  34.     hArtItem = m_webTree.InsertItem(_T("谷歌文章2"), 2, 2, hCataItem, TVI_LAST);   
  35.     // 為“谷歌文章2”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  36.     m_webTree.SetItemData(hArtItem, 3);   
  37.     // 在根節點下插入第二個子節點   
  38.     hCataItem = m_webTree.InsertItem(_T("數位生活"), 1, 1, hRoot, TVI_LAST);   
  39.     // 為“數位生活”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  40.     m_webTree.SetItemData(hCataItem, 4);   
  41.     // 在“數位生活”節點下插入子節點   
  42.     hArtItem = m_webTree.InsertItem(_T("智能手機文章1"), 2, 2, hCataItem, TVI_LAST);   
  43.     // 為“智能手機文章1”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  44.     m_webTree.SetItemData(hArtItem, 5);   
  45.     // 在“數位生活”節點下插入另一子節點   
  46.     hArtItem = m_webTree.InsertItem(_T("平闆電腦文章2"), 2, 2, hCataItem, TVI_LAST);   
  47.     // 為“平闆電腦文章2”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  48.     m_webTree.SetItemData(hArtItem, 6);   
  49.     // 在根節點下插入第三個子節點   
  50.     hCataItem = m_webTree.InsertItem(_T("軟體開發"), 1, 1, hRoot, TVI_LAST);   
  51.     // 為“軟體開發”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  52.     m_webTree.SetItemData(hCataItem, 7);   
  53.     // 在“軟體開發”節點下插入子節點   
  54.     hArtItem = m_webTree.InsertItem(_T("C++程式設計入門系列1"), 2, 2, hCataItem, TVI_LAST);   
  55.     // 為“C++程式設計入門系列1”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  56.     m_webTree.SetItemData(hArtItem, 8);   
  57.     // 在“軟體開發”節點下插入另一子節點   
  58.     hArtItem = m_webTree.InsertItem(_T("VS2010/MFC程式設計入門2"), 2, 2, hCataItem, TVI_LAST);   
  59.     // 為“VS2010/MFC程式設計入門2”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  60.     m_webTree.SetItemData(hArtItem, 9);   
  61.     // 在根節點下插入第四個子節點   
  62.     hCataItem = m_webTree.InsertItem(_T("娛樂休閑"), 1, 1, hRoot, TVI_LAST);   
  63.     // 為“娛樂休閑”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  64.     m_webTree.SetItemData(hCataItem, 10);   
  65.     // 在“娛樂休閑”節點下插入子節點   
  66.     hArtItem = m_webTree.InsertItem(_T("瑪雅文明文章1"), 2, 2, hCataItem, TVI_LAST);   
  67.     // 為“瑪雅文明文章1”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  68.     m_webTree.SetItemData(hArtItem, 11);   
  69.     // 在“娛樂休閑”節點下插入另一子節點   
  70.     hArtItem = m_webTree.InsertItem(_T("IT笑話2"), 2, 2, hCataItem, TVI_LAST);   
  71.     // 為“IT笑話2”節點添加附加的編号資料,在滑鼠劃過該節點時顯示   
  72.     m_webTree.SetItemData(hArtItem, 12);   
  73.     return TRUE;  // return TRUE  unless you set the focus to a control   
  74. }  

       6. 我們希望在選中節點改變時,将最新的選擇項實時顯示到編輯框中,那麼可以響應TVN_SELCHANGED通知消息。為樹形控件IDC_WEB_TREE的通知消息TVN_SELCHANGED添加消息處理函數CExample31Dlg::OnTvnSelchangedWebTree,并修改函數體如下:

C++代碼

  1. void CExample31Dlg::OnTvnSelchangedWebTree(NMHDR *pNMHDR, LRESULT *pResult)   
  2. {   
  3.     LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);   
  4.     // TODO: Add your control notification handler code here   
  5.     *pResult = 0;   
  6.     CString strText; // 樹節點的标簽文本字元串   
  7.     // 擷取目前選中節點的句柄   
  8.     HTREEITEM hItem = m_webTree.GetSelectedItem();   
  9.     // 擷取選中節點的标簽文本字元串   
  10.     strText = m_webTree.GetItemText(hItem);   
  11.     // 将字元串顯示到編輯框中   
  12.     SetDlgItemText(IDC_ITEM_SEL_EDIT, strText);   
  13. }  

       7. 還有一個功能需要實作,那就是滑鼠劃過除根節點外的某個樹節點時,顯示相應的Tip提示資訊,本執行個體中提示資訊為節點的編号。這需要響應TVN_GETINFOTIP通知消息。為樹形控件IDC_WEB_TREE的通知消息TVN_GETINFOTIP添加消息處理函數CExample31Dlg::OnTvnGetInfoTipWebTree,并修改函數體如下:

C++代碼

  1. void CExample31Dlg::OnTvnGetInfoTipWebTree(NMHDR *pNMHDR, LRESULT *pResult)   
  2. {   
  3.     LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR);   
  4.     // TODO: Add your control notification handler code here   
  5.     *pResult = 0;   
  6.     NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;   // 将傳入的pNMHDR轉換為NMTVGETINFOTIP指針類型   
  7.     HTREEITEM hRoot = m_webTree.GetRootItem();      // 擷取樹的根節點   
  8.     CString strText;     // 每個樹節點的提示資訊   
  9.     if (pTVTipInfo->hItem == hRoot)   
  10.     {   
  11.         // 如果滑鼠劃過的節點是根節點,則提示資訊為空   
  12.         strText = _T("");   
  13.     }   
  14.     else  
  15.     {   
  16.         // 如果滑鼠劃過的節點不是根節點,則将該節點的附加32位資料格式化為字元串   
  17.         strText.Format(_T("%d"), pTVTipInfo->lParam);   
  18.     }   
  19.     // 将strText字元串拷貝到pTVTipInfo結構體變量的pszText成員中,這樣就能顯示内容為strText的提示資訊   
  20.     wcscpy(pTVTipInfo->pszText, strText);   
  21. }  

       8. 運作程式,彈出結果對話框。效果如下圖:

VS2010/MFC程式設計入門之三十一(常用控件:樹形控件Tree Control 下)

       樹形控件的知識就講到這裡了,相比之前的控件可能稍有複雜。不過用的多了,就會覺得得心應手了。雞啄米歡迎大家繼續關注後面的VS2010/MFC程式設計入門教程。

繼續閱讀