樹型視的三個結構TVINSERTSTRUCT、TVITEM、NMTREEVIEW
TVINSERTSTRUCT
包含添加新項到樹形視控件所使用的信息。這個結構被
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成員指出的位的當前狀態。
一個狀態圖像是僅次於指出應用程序定義的狀態的項的圖標顯示的。經過發送
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
-
若是這個結構指定了項屬性,那麼這個成員是指向一個以空字符結束的字符串,包含有項的文本。若是這個成員是值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 act
ion;
TVITEM itemOld;
TVITEM itemNew;
POINT ptDrag;
} NMTREEVIEW, FAR *LPNMTREEVIEW;
成員
-
hdr
-
NMHDR結構,包含了關於這個通知消息的信息
-
action
-
通知指定的動做標記。
-
itemOld
-
包含關於舊項狀態信息的
TVITEM結構。通知消息沒有使用它時,這個成員爲0。
-
itemNew
-
包含關於新項狀態信息的
TVITEM結構。通知消息沒有使用它時,這個成員爲0。
-
ptDrag
-
包含引發通知消息發送的事件信息的
POINT結構。
參見
***********************************************************************************************************************************
樹形控件是用於構造樹形的結構,其中有一個根接點(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 On
XXXTree(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::On
GetDispInfoTree(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::On
BeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
if(pTVDI->item.lParam == 0);//判斷是否取消該操做
*pResult = 0;
else
*pResult = 1;
}
//處理消息 TVN_BEGINLABELEDIT
void CParentWnd::On
BeginEditTree(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的全部消息都須要在父窗口中處理)。