VS2010/MFC編程(常用控件:樹形控件Tree Control控件創(chuàng)建h和實(shí)例)
前面一節(jié)講了樹形控件Tree Control的簡介、通知消息以及相關(guān)數(shù)據(jù)結(jié)構(gòu),本節(jié)繼續(xù)講下半部分,包括樹形控件的創(chuàng)建、CTreeCtrl類的主要成員函數(shù)和應(yīng)用實(shí)例。
樹形控件的創(chuàng)建
MFC為樹形控件提供了CTreeCtrl類,它封裝了樹形控件的所有操作。
樹形控件的創(chuàng)建也是有兩種方式,一種是在對話框模板中直接拖入Tree Control控件創(chuàng)建,另一種就是通過CTreeCtrl類的Create成員函數(shù)創(chuàng)建。下面主要講后者。
CTreeCtrl類的Create成員函數(shù)的原型如下:
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
此函數(shù)的原型與前面講到的所有控件類的Create函數(shù)都類似。dwStyle指定樹形控件風(fēng)格的組合,rect指定樹形控件窗口的位置和大小,pParentWnd為指向樹形控件父窗口的指針,nID指定樹形控件的ID。下面還是主要講講樹形控件的主要風(fēng)格以及含義。
- TVS_DISABLEDRAGDROP:禁止樹形控件發(fā)送TVN_BEGINDRAG通知消息,即不支持拖動操作
- TVS_EDITLABELS:用戶可以編輯節(jié)點(diǎn)的標(biāo)簽文本
- TVS_HASBUTTONS:顯示帶有"+"或"-"的小方框來表示某項(xiàng)能否被展開或已展開
- TVS_HASLINES:在父節(jié)點(diǎn)與子節(jié)點(diǎn)間連線以更清晰地顯示樹的結(jié)構(gòu)
- TVS_LINESATROOT:在根節(jié)點(diǎn)處連線
- TVS_SHOWSELALWAYS:即使控件失去輸入焦點(diǎn),仍顯示出項(xiàng)的選擇狀態(tài)
同樣,動態(tài)創(chuàng)建樹形控件時,除了能夠指定上述風(fēng)格的組合外,一般還要指定WS_CHILD和WS_VISIBLE風(fēng)格。
在對話框模板中直接拖入Tree Control創(chuàng)建樹形控件時,可以在樹形控件的屬性頁中設(shè)置其風(fēng)格,與上面的風(fēng)格是對應(yīng)的,例如,屬性Has Lines對應(yīng)的就是TVS_HASLINES風(fēng)格。
CTreeCtrl類的主要成員函數(shù)
CImageList* SetImageList(CImageList * pImageList,int nImageListType);
如果樹節(jié)點(diǎn)需要顯示圖標(biāo)時,則必須先創(chuàng)建一個CImageList類的對象,并為其添加多個圖像組成一個圖像序列,然后調(diào)用SetImageList函數(shù)為樹形控件設(shè)置圖像序列,在用InsertItem插入節(jié)點(diǎn)時傳入所需圖像在圖像序列中的索引即可。后面的例子中會演示。參數(shù)pImageList為指向圖像序列類CImageList的對象的指針,若為NULL則刪除樹形控件的所有圖像。參數(shù)nImageListType指定圖像序列的類型,可以是TVSIL_NORMAL(普通圖像序列)或TVSIL_STATE(狀態(tài)圖像序列,用圖像表示節(jié)點(diǎn)的狀態(tài))。
UINT GetCount( ) const;
獲取樹形控件中節(jié)點(diǎn)的數(shù)量。
DWORD_PTR GetItemData(HTREEITEM hItem) const;
獲取樹形控件中某個指定節(jié)點(diǎn)的附加32位數(shù)據(jù)。參數(shù)hItem為指定的樹節(jié)點(diǎn)的句柄。
BOOL SetItemData(HTREEITEM hItem,DWORD_PTR dwData);
為樹形控件中某個指定節(jié)點(diǎn)設(shè)置附加的32位數(shù)據(jù)。參數(shù)hItem同上,dwData為要設(shè)置的32位數(shù)據(jù)。
CString GetItemText(HTREEITEM hItem) const;
獲取樹形控件中某個指定節(jié)點(diǎn)的標(biāo)簽文本。參數(shù)hItem同上。返回值是包含標(biāo)簽文本的字符串。
BOOL SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);
為樹形控件中某個指定節(jié)點(diǎn)設(shè)置標(biāo)簽文本。參數(shù)hItem同上,lpszItem為包含標(biāo)簽文本的字符串的指針。
HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const;
獲取樹形控件中某個指定節(jié)點(diǎn)的下一個兄弟節(jié)點(diǎn)。參數(shù)hItem同上。返回值是下一個兄弟節(jié)點(diǎn)的句柄。
HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const;
獲取樹形控件中某個指定節(jié)點(diǎn)的上一個兄弟節(jié)點(diǎn)。參數(shù)hItem同上。返回值是上一個兄弟節(jié)點(diǎn)的句柄。
HTREEITEM GetParentItem(HTREEITEM hItem) const;
獲取樹形控件中某個指定節(jié)點(diǎn)的父節(jié)點(diǎn)。參數(shù)hItem同上。返回值是父節(jié)點(diǎn)的句柄。
HTREEITEM GetRootItem( ) const;
獲取樹形控件根節(jié)點(diǎn)的句柄。
HTREEITEM GetSelectedItem( ) const;
獲取樹形控件當(dāng)前選中節(jié)點(diǎn)的句柄。
BOOL DeleteAllItems( );
刪除樹形控件中的所有節(jié)點(diǎn)。刪除成功則返回TRUE,否則返回FALSE。
BOOL DeleteItem(HTREEITEM hItem);
刪除樹形控件中的某個節(jié)點(diǎn)。參數(shù)hItem為要刪除的節(jié)點(diǎn)的句柄。刪除成功則返回TRUE,否則返回FALSE。
HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST);
在樹形控件中插入一個新節(jié)點(diǎn)。參數(shù)lpszItem為新節(jié)點(diǎn)的標(biāo)簽文本字符串的指針,參數(shù)nImage為新節(jié)點(diǎn)的圖標(biāo)在樹形控件圖像序列中的索引,參數(shù)nSelectedImage為新節(jié)點(diǎn)被選中時的圖標(biāo)在圖像序列中的索引,參數(shù)hParent為插入節(jié)點(diǎn)的父節(jié)點(diǎn)的句柄,參數(shù)hInsertAfter為新節(jié)點(diǎn)的前一個節(jié)點(diǎn)的句柄,即新節(jié)點(diǎn)將被插入到hInsertAfter節(jié)點(diǎn)之后。
BOOL SelectItem(HTREEITEM hItem);
選中指定的樹節(jié)點(diǎn)。參數(shù)hItem為要選擇的節(jié)點(diǎn)的句柄。若成功則返回TRUE,否則返回FALSE。
樹形控件的應(yīng)用實(shí)例
最后還是給大家寫一個簡單的實(shí)例,說明CListCtrl類的幾個成員函數(shù)及樹形控件通知消息等的使用方法。
此實(shí)例實(shí)現(xiàn)的功能:在一個樹形控件中顯示網(wǎng)站的簡單結(jié)構(gòu)分層,共有三層,分別為網(wǎng)站、各個分類和文章。用鼠標(biāo)左鍵單擊改變選中節(jié)點(diǎn)后,將選中節(jié)點(diǎn)的文本顯示到編輯框中。另外,還要實(shí)現(xiàn)一個常見的效果,就是鼠標(biāo)劃過除根節(jié)點(diǎn)外的某個樹節(jié)點(diǎn)時,顯示相應(yīng)的Tip提示信息。下面是具體實(shí)現(xiàn)步驟:
1. 創(chuàng)建一個基于對話框的MFC工程,名稱設(shè)置為“Example31”。
2. 在自動生成的對話框模板IDD_EXAMPLE31_DIALOG中,刪除“TODO: Place dialog controls here.”靜態(tài)文本框、“OK”按鈕和“Cancel”按鈕。添加一個Tree Control控件,ID設(shè)置為IDC_WEB_TREE,屬性Has Buttons、Has Lines和Lines At Root都設(shè)為True,為了在鼠標(biāo)劃過某個節(jié)點(diǎn)時顯示提示信息還需要將Info Tip屬性設(shè)為True。再添加一個靜態(tài)文本框和一個編輯框,靜態(tài)文本框的Caption屬性設(shè)為“您選擇的節(jié)點(diǎn):”,編輯框的ID設(shè)為IDC_ITEM_SEL_EDIT,Read Only屬性設(shè)為True。此時的對話框模板如下圖:
3. 導(dǎo)入需要為樹形控件的節(jié)點(diǎn)添加的圖標(biāo)。在這里找了三個32x32的Icon圖標(biāo),保存到工程的res目錄下。然后在Resource View資源視圖中,右鍵點(diǎn)擊Icon節(jié)點(diǎn),在右鍵菜單中選擇“Add Resource...”,彈出“Add Resource”對話框,再從左邊“Resource type”列表中選擇“Icon”,點(diǎn)擊右邊的“Import...”按鈕,就可以選擇三個圖標(biāo)文件進(jìn)行導(dǎo)入了。導(dǎo)入成功后,分別修改它們ID為IDI_WEB_ICON、IDI_CATALOG_ICON和IDI_ARTICLE_ICON。
4. 為樹形控件IDC_WEB_TREE添加CTreeCtrl類型的控件變量m_webTree。并在Example31Dlg.h文件中為CExample31Dlg類添加成員對象:CImageList m_imageList;。
5. 在對話框初始化時,我們在樹形控件中添加網(wǎng)站的樹形結(jié)構(gòu),那么需要修改CExample31Dlg::OnInitDialog()函數(shù)為:
BOOL CExample31Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); ......略 // TODO: Add extra initialization here HICON hIcon[3]; // 圖標(biāo)句柄數(shù)組 HTREEITEM hRoot; // 樹的根節(jié)點(diǎn)的句柄 HTREEITEM hCataItem; // 可表示任一分類節(jié)點(diǎn)的句柄 HTREEITEM hArtItem; // 可表示任一文章節(jié)點(diǎn)的句柄 // 加載三個圖標(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對象 m_imageList.Create(32, 32, ILC_COLOR32, 3, 3); // 將三個圖標(biāo)添加到圖像序列 for (int i=0; i<3; i++) { m_imageList.Add(hIcon[i]); } // 為樹形控件設(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)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 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)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 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)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hArtItem, 3); // 在根節(jié)點(diǎn)下插入第二個子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("數(shù)碼生活"), 1, 1, hRoot, TVI_LAST); // 為“數(shù)碼生活”節(jié)點(diǎn)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 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)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 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)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hArtItem, 6); // 在根節(jié)點(diǎn)下插入第三個子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("軟件開發(fā)"), 1, 1, hRoot, TVI_LAST); // 為“軟件開發(fā)”節(jié)點(diǎn)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hCataItem, 7); // 在“軟件開發(fā)”節(jié)點(diǎn)下插入子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("C++編程入門系列1"), 2, 2, hCataItem, TVI_LAST); // 為“C++編程入門系列1”節(jié)點(diǎn)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hArtItem, 8); // 在“軟件開發(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)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hArtItem, 9); // 在根節(jié)點(diǎn)下插入第四個子節(jié)點(diǎn) hCataItem = m_webTree.InsertItem(_T("娛樂休閑"), 1, 1, hRoot, TVI_LAST); // 為“娛樂休閑”節(jié)點(diǎn)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hCataItem, 10); // 在“娛樂休閑”節(jié)點(diǎn)下插入子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("瑪雅文明文章1"), 2, 2, hCataItem, TVI_LAST); // 為“瑪雅文明文章1”節(jié)點(diǎn)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hArtItem, 11); // 在“娛樂休閑”節(jié)點(diǎn)下插入另一子節(jié)點(diǎn) hArtItem = m_webTree.InsertItem(_T("IT笑話2"), 2, 2, hCataItem, TVI_LAST); // 為“IT笑話2”節(jié)點(diǎn)添加附加的編號數(shù)據(jù),在鼠標(biāo)劃過該節(jié)點(diǎn)時顯示 m_webTree.SetItemData(hArtItem, 12); return TRUE; // return TRUE unless you set the focus to a control }
6. 我們希望在選中節(jié)點(diǎn)改變時,將最新的選擇項(xiàng)實(shí)時顯示到編輯框中,那么可以響應(yīng)TVN_SELCHANGED通知消息。為樹形控件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; // 樹節(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. 還有一個功能需要實(shí)現(xiàn),那就是鼠標(biāo)劃過除根節(jié)點(diǎn)外的某個樹節(jié)點(diǎn)時,顯示相應(yīng)的Tip提示信息,本實(shí)例中提示信息為節(jié)點(diǎn)的編號。這需要響應(yīng)TVN_GETINFOTIP通知消息。為樹形控件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(); // 獲取樹的根節(jié)點(diǎn) CString strText; // 每個樹節(jié)點(diǎn)的提示信息 if (pTVTipInfo->hItem == hRoot) { // 如果鼠標(biāo)劃過的節(jié)點(diǎn)是根節(jié)點(diǎn),則提示信息為空 strText = _T(""); } else { // 如果鼠標(biāo)劃過的節(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é)果對話框。效果如下圖:
樹形控件的知識就講到這里了,相比之前的控件可能稍有復(fù)雜。不過用的多了,就會覺得得心應(yīng)手了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++?auto關(guān)鍵字的小知識點(diǎn)分享
這篇文章主要是來和大家介紹一些C++中的小知識點(diǎn),本文將從auto關(guān)鍵字開始講起,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-05-05C語言數(shù)據(jù)結(jié)構(gòu)之二分法查找詳解
二分查找算法是在有序數(shù)組中用到的較為頻繁的一種算法,在未接觸二分查找算法時,最通用的一種做法是,對數(shù)組進(jìn)行遍歷,跟每個元素進(jìn)行比較,其時間為O(n),但二分查找算法更優(yōu)2022-02-02C語言實(shí)現(xiàn)24點(diǎn)游戲源代碼
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)24點(diǎn)游戲源代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-10-10C++ 非遞歸實(shí)現(xiàn)二叉樹的前中后序遍歷
本文將結(jié)合動畫和代碼演示如何通過C++ 非遞歸實(shí)現(xiàn)二叉樹的前中后序的遍歷,代碼具有一定的價值,感興趣的同學(xué)可以學(xué)習(xí)一下2021-11-11C++11中value category(值類別)及move semantics(移動語義)的介紹
這篇文章主要給大家介紹了C++11中value category(值類別)及move semantics(移動語義)的介紹,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05