樹型視的三個結構TVINSERTSTRUCT、TVITEM、NMTREEVIEWTVINSERTSTRUCT 包含添加新項到樹形視控制項所使用的資訊。這個結構被TVM_INSERTITEM訊息使用。這個結構與
TV_INSERTSTRUCT結構是一樣的,但它已經按當前的命名習慣重新命名了。
typedef struct tagTVINSERTSTRUCT { HTREEITEM hParent; HTREEITEM hInsertAfter;#if (_WIN32_IE >= 0x0400) union { TVITEMEX itemex; TVITEM item; } DUMMYUNIONNAME;#else TVITEM item;#endif} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
成員
-
hParent
-
父項的控制代碼。如果這個成員的值是TVI_ROOT或NULL,這項將被作為樹形控制項的根插入。
-
hInsertAfter
-
插入的新項之後的項的控制代碼。或是下列值之一:
值 |
意味 |
TVI_FIRST |
在列表的開始插入項 |
TVI_LAST |
在列表的最後插入項 |
TVI_ROOT |
作為一個根項添加 |
TVI_SORT |
以字母順序插入項 |
-
itemex
-
版本4.71。TVITEMEX包含關於項添加的資訊。
-
item
-
TVITEM包含關於項添加的資訊。
需求
Windows NT/2000:需要Windows NT 3.51或更高版本。
Windows 95/98:需要Windows 95或更高版本。
Header:定義在commctrl.h。TVITEM指定或接收樹形視項的屬性。這個結構與
TV_ITEM結構一樣,但它已經被當前命名協議重新命名了。新的應用程式應該使用這個結構。
typedef struct tagTVITEM{ UINT mask; HTREEITEM hItem; UINT state; UINT stateMask; LPTSTR pszText; int cchTextMax; int iImage; int iSelectedImage; int cChildren; LPARAM lParam;} TVITEM, FAR *LPTVITEM;
成員
-
mask
-
指出其它的結構成員哪些包含有效資料的標記數組。當這個結構被TVM_GETITEM訊息使用時,
mask成員指出項的屬性被取回。這個成員可以是下列值的一個或多個。
TVIF_CHILDREN |
cChildren成員是有效。 |
TVIF_DI_SETITEM |
樹形視控制項將保留支援資訊並且不重新請求它。當處理TVN_GETDISPINF通知時,這個標記是有效。 |
TVIF_HANDLE |
hItem成員有效。 |
TVIF_IMAGE |
iImage成員有效。 |
TVIF_PARAM |
lParam成員有效。 |
TVIF_SELECTEDIMAGE |
iSelectedImage成員有效。 |
TVIF_STATE |
state和stateMask成員有效。 |
TVIF_TEXT |
pszText和cchTextMax成員有效。 |
-
hItem
-
這個函數引用的項。
-
state
-
位標記和映像清單索引的設定,指出項的狀態。當設定了一個項的狀態,
stateMask成員指出這個成員的位是有效。當取加一個項的狀態時,這個成員返回
stateMask成員指出的位的目前狀態。
這個成員的0至7位包含了項的狀態標記。關於可能的項狀態標記,參見Tree View Control Item States.覆蓋映像覆蓋在項的表徵圖映像之上。這個成員的8至11位指定了以1為基準的覆蓋映像索引。如果這些位是0,這個項沒有覆蓋映像。要隔離這些位,使用TVIS_OVERLAYMASK掩碼。要在這個成員中設定覆蓋映像索引,使用INDEXTOOVERLAYMASK宏。映像列表的覆蓋映像是被ImageList_SetOverlayImage函數設定的。一個狀態映像是僅次於指出應用程式定義的狀態的項的表徵圖顯示的。通過發送TVM_SETIMAGELIST訊息來指定一個狀態映像列表。要設定一個項的狀態映像,在
TVITEM結構的
stateMask成員中包含TVIS_STATEIMAGEMASK值。結構的
state成員的12至15位指定狀態映像列表中被繪製映像的索引。要設定狀態映像索引,使用INDEXTOSTATEIMAGEMASK。這個宏把一個索引適當的設定到12至15位上。要指出項沒有狀態映像,設定索引為0。這意味著在狀態映像列表中的映像0不能被作為一個狀態映像使用。要隔離
state成員的位12至15,使用TVIS_STATEIMAGEMASK掩碼。
-
stateMask
-
state成員的位是有效。如果你取回了一個項的狀態,設定
stateMask成員的位來指出
state成員中的這個位被返回。如果你設定了一個項的狀態,設定
stateMask成員的位來指出
state成員的這個位是你想設定的。要設定或取回一個項的覆蓋映像的索引,設定TVIS_OVERLAYMASK位。要設定和取回一個項的狀態映像索引,設定TVIS_STATEIMAGEMASK位。
-
pszText
-
如果這個結構指定了項屬性,那麼這個成員是指向一個以Null 字元結束的字串,包含有項的文本。如果這個成員是值LPSTR_TEXTCALLBACK,那麼父視窗為儲存名字負責。既然這樣,當樹形視控制項需要顯示、儲存或編輯項文本時,向父視窗發送TVN_GETDISPINFO通過訊息,當項文本改變時,發送TVN_SETDISPINFO通知訊息。
如果結構是取回項的屬性,這個成員是取回項文本緩衝的地址。
-
cchTextMax
-
pszText成員指定緩衝的大小,以字元為單位。如果這個結構被使用來設定項屬性,這個成員被忽略。
-
iImage
-
當項是在非選擇狀態中時,是樹形控制項的映像列表的索引。
如果這個成員是值I_IMAGECALLBACK,父視窗為儲存索引負責。既然這樣,當樹形視控制項需要顯示這個映像時,向父視窗發送TVN_GETDISPINFO通知訊息來獲得索引。
-
iSelectedImage
-
當項被選擇時,是樹形控制項映像列表的索引。
如果這個成員是值I_IMAGECALLBACK,父視窗為儲存索引負責。既然這樣,當樹形視控制項需要顯示這個映像時,向父視窗發送TVN_GETDISPINFO通知訊息來獲得索引。
-
cChildren
-
標記指出哪一個項有關聯的子項。這個成員可以是下列值之一。
zero |
這個項沒有子項。 |
one |
這個項有一個或更多的子項。 |
I_CHILDRENCALLBACK |
The parent window keeps track of whether the item has child items. In this case, when the tree view control needs to display the item, the control sends the parent a TVN_GETDISPINFO notification message to determine whether the item has child items. If the tree view control has the TVS_HASBUTTONS style, it uses this member to determine whether to display the button indicating the presence of child items. You can use this member to force the control to display the button even though the item does not have any child items inserted. This allows you to display the button while minimizing the control's memory usage by inserting child items only when the item is visible or expanded. |
-
lParam
-
與這項相關的32位值。
需要
Windows NT/2000:需要Windows NT 3.51或更高版本。
Windows 95/98:需要Windows 95或更高版本。
Header:定義在commctrl.h。NMTREEVIEW
包含關於樹形視通知訊息的資訊。這個結構與
NM_TREEVIEW結構一樣,但它已經用當前的命名規則進行了重新命名。
typedef struct tagNMTREEVIEW { NMHDR hdr; UINT action; TVITEM itemOld; TVITEM itemNew; POINT ptDrag; } NMTREEVIEW, FAR *LPNMTREEVIEW;
成員
-
hdr
-
NMHDR結構,包含了關於這個通知訊息的資訊
-
action
-
通知指定的動作標記。
-
itemOld
-
包含關於舊項狀態資訊的TVITEM結構。通知訊息沒有使用它時,這個成員為0。
-
itemNew
-
包含關於新項狀態資訊的TVITEM結構。通知訊息沒有使用它時,這個成員為0。
-
ptDrag
-
包含引起通知訊息發送的事件資訊的POINT結構。
參見WM_NOTIFY***********************************************************************************************************************************樹形控制項是用於構造樹形的結構,其中有一個根接點(Root)然後下面有許多子結點,而每個子結點上有允許有一個或多個或沒有子結點。MFC中使用CTreeCtrl類來封裝樹形控制項的各種操作。通過調用
BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
建立一個視窗,dwStyle中可以使用以下一些樹形控制項的專用風格:TVS_HASLINES 在父/子結點之間繪製連線
TVS_LINESATROOT 在根/子結點之間繪製連線
TVS_HASBUTTONS 在每一個結點前添加一個按鈕,用於表示當前結點是否已被展開
TVS_EDITLABELS 結點的顯示字元可以被編輯
TVS_SHOWSELALWAYS 在失去焦點時也顯示當前選中的結點
TVS_DISABLEDRAGDROP 不允許Drag/Drop
TVS_NOTOOLTIPS 不使用ToolTip顯示結點的顯示字元在樹形控制項中每一個結點都有一個控制代碼(HTREEITEM),同時添加結點時必須提供的參數是該結點的父結點控制代碼,(其中根Root結點只有一個,既不可以添加也不可以刪除)利用
HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST );
可以添加一個結點,pszItem為顯示的字元,hParent代表父結點的控制代碼,當前添加的結點會排在hInsertAfter表示的結點的後面,傳回值為當前建立的結點的控制代碼。下面的代碼會建立一個如下形式的樹形結構:+--- Parent1
+--- Child1_1
+--- Child1_2
+--- Child1_3
+--- Parent2
+--- Parent3/*假設m_tree為一個CTreeCtrl對象,而且該視窗已經建立*/
HTREEITEM hItem,hSubItem;
hItem = m_tree.InsertItem("Parent1",TVI_ROOT);在根結點上添加Parent1
hSubItem = m_tree.InsertItem("Child1_1",hItem);//在Parent1上添加一個子結點
hSubItem = m_tree.InsertItem("Child1_2",hItem,hSubItem);//在Parent1上添加一個子結點,排在Child1_1後面
hSubItem = m_tree.InsertItem("Child1_3",hItem,hSubItem);hItem = m_tree.InsertItem("Parent2",TVI_ROOT,hItem);
hItem = m_tree.InsertItem("Parent3",TVI_ROOT,hItem); 如果你希望在每個結點前添加一個小表徵圖,就必需先調用
CImageList* SetImageList( CImageList * pImageList, int nImageListType );
指明當前所使用的ImageList,nImageListType為TVSIL_NORMAL。在調用完成後控制項中使用圖片以設定的ImageList中圖片為準。然後調用
HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);
添加結點,nImage為結點沒被選中時所使用圖片序號,nSelectedImage為結點被選中時所使用圖片序號。下面的代碼示範了ImageList的設定。/*m_list 為CImageList對象
IDB_TREE 為16*(16*4)的位元影像,每個圖片為16*16共4個表徵圖*/
m_list.Create(IDB_TREE,16,4,RGB(0,0,0));
m_tree.SetImageList(&m_list,TVSIL_NORMAL);
m_tree.InsertItem("Parent1",0,1);//添加,選中時顯示表徵圖1,未選中時顯示表徵圖0此外CTreeCtrl還提供了一些函數用於得到/修改控制項的狀態。
HTREEITEM GetSelectedItem( );將返回當前選中的結點的控制代碼。
BOOL SelectItem( HTREEITEM hItem );將選中指明結點。
BOOL GetItemImage( HTREEITEM hItem, int& nImage, int& nSelectedImage ) / BOOL SetItemImage( HTREEITEM hItem, int nImage, int nSelectedImage )用於得到/修改某結點所使用表徵圖索引。
CString GetItemText( HTREEITEM hItem ) /BOOL SetItemText( HTREEITEM hItem, LPCTSTR lpszItem );用於得到/修改某一結點的顯示字元。
BOOL DeleteItem( HTREEITEM hItem );用於刪除某一結點,
BOOL DeleteAllItems( );將刪除所有結點。此外如果想遍曆樹可以使用下面的函數:
HTREEITEM GetRootItem( );得到根結點。
HTREEITEM GetChildItem( HTREEITEM hItem );得到子結點。
HTREEITEM GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem );得到指明結點的上/下一個兄弟結點。
HTREEITEM GetParentItem( HTREEITEM hItem );得到父結點。樹形控制項的訊息映射使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode為通知代碼,id為產生該訊息的視窗ID,memberFxn為處理函數,函數的原型如同void OnXXXTree(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR為一資料結構,在具體使用時需要轉換成其他類型的結構。對於樹形控制項可能取值和對應的資料結構為:TVN_SELCHANGED 在所選中的結點發生改變後發送,所用結構:NMTREEVIEW
TVN_ITEMEXPANDED 在某結點被展開後發送,所用結構:NMTREEVIEW
TVN_BEGINLABELEDIT 在開始編輯結點字元時發送,所用結構:NMTVDISPINFO
TVN_ENDLABELEDIT 在結束編輯結點字元時發送,所用結構:NMTVDISPINFO
TVN_GETDISPINFO 在需要得到某結點資訊時發送,(如得到結點的顯示字元)所用結構:NMTVDISPINFO
關於ON_NOTIFY有很多內容,將在以後的內容中進行詳細講解。關於動態提供結點所顯示的字元:首先你在添加結點時需要指明lpszItem參數為:LPSTR_TEXTCALLBACK。在控制項顯示該結點時會通過發送TVN_GETDISPINFO來取得所需要的字元,在處理該訊息時先將參數pNMHDR轉換為LPNMTVDISPINFO,然後填充其中item.pszText。但是我們通過什麼來知道該結點所對應的資訊呢,我的做法是在添加結點後設定其lParam參數,然後在提供資訊時利用該參數來尋找所對應的資訊。下面的代碼說明了這種方法:char szOut[8][3]={"No.1","No.2","No.3"};//添加結點
HTREEITEM hItem = m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 0 );
hItem = m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 1 );
//處理訊息
void CParentWnd::OnGetDispInfoTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
pTVDI->item.pszText=szOut[pTVDI->item.lParam];//通過lParam得到需要顯示的字元在數組中的位置
*pResult = 0;
}關於編輯結點的顯示字元:首先需要設定樹形控制項的TVS_EDITLABELS風格,在開始編輯時該控制項將會發送TVN_BEGINLABELEDIT,你可以通過在處理函數中返回TRUE來取消接下來的編輯,在編輯完成後會發送TVN_ENDLABELEDIT,在處理該訊息時需要將參數pNMHDR轉換為LPNMTVDISPINFO,然後通過其中的item.pszText得到編輯後的字元,並重設顯示字元。如果編輯在中途中取消該變數為NULL。下面的代碼說明如何處理這些訊息://處理訊息 TVN_BEGINLABELEDIT
void CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
if(pTVDI->item.lParam == 0);//判斷是否取消該操作
*pResult = 0;
else
*pResult = 1;
}
//處理訊息 TVN_BEGINLABELEDIT
void CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
if(pTVDI->item.pszText != NULL);//判斷是否已經取消取消編輯
m_tree.SetItemText(pTVDI->item.hItem,pTVDI->pszText);//重設顯示字元
*pResult = 0;
}上面講述的方法所進行的訊息映射必須在父視窗中進行(同樣WM_NOTIFY的所有訊息都需要在父視窗中處理)。