Share via


關於樹視圖控件

樹檢視控件是顯示階層式專案清單的視窗,例如檔中的標題、索引中的專案,或磁碟上的檔案和目錄。 每個項目都包含標籤和選擇性點陣圖影像,因此,每個項目都可以擁有與自己相關的子項目清單。 按兩下專案,使用者可以展開或折疊相關聯的子專案清單。

下圖顯示具有根節點、展開節點和折疊節點的簡單樹視圖控件。 控件會針對選取的專案使用一個點陣圖,而另一個點陣圖則用於其他專案。

screen shot showing five nodes in a hierarchy; the text of one node is selected, but nodes are not linked to each other by lines

建立樹檢視控件之後,您可以藉由將訊息傳送至控件來新增、移除、排列或其他操作專案。 每個訊息都有一或多個對應的宏,可供您使用,而不是明確傳送訊息。

本節將討論下列主題。

樹視圖樣式

樹視圖樣式會控管樹視圖控件外觀的各個層面。 當您建立樹視圖控件時,會設定初始樣式。 您可以使用 GetWindowLong 和 SetWindowLong 函式,在建立樹視圖控件之後擷取和變更樣式。

TVS_HASLINES樣式會繪製將子項目連結到其父項目的線條,藉此增強樹視圖控件階層的圖形表示,如下圖所示。

screen shot showing the previous arrangement, but with lines joining the nodes; the first line descends from the root node

此樣式本身不會在階層的根目錄繪製線條。 若要這樣做,您必須結合TVS_HASLINESTVS_LINESATROOT樣式。 下圖顯示結果。

screen shot showing the previous arrangement, but with an additional horizontal line leading to the root node

用戶可以按兩下父項目來展開或折疊父專案的子專案清單。 具有TVS_HASBUTTONS樣式的樹視圖控件會將按鈕新增至每個父項目的左側。 使用者可以按鍵一次,而不是按兩下父項目來展開或折疊子系。 TVS_HASBUTTONS不會將按鈕新增至階層根目錄的專案。 若要這樣做,您必須結合TVS_HASLINESTVS_LINESATROOTTVS_HASBUTTONS。 下圖顯示這種樣式組合。

screen shot showing the previous arrangement, but with expand/collapse buttons at each vertex of two lines

TVS_CHECKBOXES樣式會在每個專案旁邊建立複選框。 如果您想要使用複選框樣式,您必須在建立樹視圖控件之後,以及在填入樹狀結構之前,設定TVS_CHECKBOXES樣式(使用 SetWindowLong)。 否則,根據時間問題,複選框可能會顯示為未核取。 下圖顯示複選框樣式。

screen shot showing the previous arrangement, but with a checkbox next to each node; two of the checkboxes are selected

TVS_FULLROWSELECT樣式會使選取專案反白顯示延伸至控件的完整寬度,而不只是專案本身。 下圖顯示此樣式。

screen shot showing the original arrangement of five nodes with no lines, but the selection highlight extends the full width of the control

TVS_EDITLABELS樣式可讓用戶編輯樹檢視專案的標籤。 如需編輯標籤的詳細資訊,請參閱 樹檢視標籤編輯

如需這些樣式和其他樣式的詳細資訊,請參閱 樹視圖控件窗口樣式

父項和子專案

樹視圖控件中的任何專案都可以有與其相關聯的子專案清單,稱為 子專案。 具有一或多個子專案的專案稱為 父專案。 子項目會顯示在其父專案下方,並縮排表示其屬於父專案。 沒有父代的專案會出現在階層頂端,並稱為 根專案

若要將專案新增至樹視圖控件,請將TVM_INSERTITEM訊息傳送至控件。 訊息會傳回 HTREEITEM 類型的句柄,此類型可唯一識別專案。 新增專案時,您必須指定新專案父專案的句柄。 如果您指定 NULL 或 TVI_ROOT 值,而不是 TVINSERTSTRUCT 結構中的父專案句柄,則會將專案新增為根專案。

在任何指定時間內,父項目的子項目清單狀態可以是展開或摺疊。 當其狀態為展開時,表示子項目會顯示在父項目下方。 當它摺疊時,則不會顯示子項目。 當使用者按兩下父專案時,清單會自動在展開和折疊狀態之間切換,或者當使用者按兩下與父專案相關聯的按鈕時,如果父專案具有 TVS_HASBUTTONS 樣式, 清單就會自動切換。 應用程式可以使用TVM_EXPAND訊息來展開或折疊子專案

當父項專案的子專案清單即將展開或折疊時,樹視圖控件會傳送父視窗 TVN_ITEMEXPANDING 通知訊息。 通知可讓應用程式有機會防止變更,或設定父專案的任何屬性,而該屬性取決於子專案清單的狀態。 變更清單的狀態之後,樹視圖控件會將TVN_ITEMEXPANDED通知訊息傳送給父視窗

當子項目清單展開時,它會以相對於父項目的位置進行縮排。 您可以使用TVM_SETINDENT訊息來設定縮排量,或使用TVM_GETINDENT訊息擷取目前的數量。

樹視圖控件會使用從建立樹視圖控件的進程堆積配置的記憶體。 樹視圖中的項目數目上限是以堆積中可用的記憶體數量為基礎。

項目標籤

當您將專案加入樹視圖控件時,通常會指定專案標籤的文字。 TVM_INSERTITEM訊息包含定義項目屬性的TVITEM結構,包括包含標籤文字的字串。

樹檢視控件會配置記憶體來儲存每個專案;項目標籤的文字佔用此記憶體的很大一部分。 如果您的應用程式在樹視圖控件中維護字串的複本,您可以藉由在TVITEM的 pszText 成員中指定LPSTR_TEXTCALLBACK值來減少控件的記憶體需求,而不是將實際字串傳遞至樹視圖。 使用 LPSTR_TEXTCALLBACK會導致樹視圖控件在需要重新繪製專案時,從父視窗擷取專案的標籤文字。 為了擷取文字,樹視圖控件會傳送TVN_GETDISPINFO通知訊息,其中包含NMTVDISPINFO結構的位址。 父窗口必須填滿包含結構的適當成員。

樹檢視標籤編輯

用戶可以在具有TVS_EDITLABELS樣式的樹視圖控件中,直接編輯專案的標籤。 按一下具有焦點的項目標籤,使用者就可以開始進行編輯。 應用程式會使用 TVM_EDITLABEL 訊息開始編輯。 樹檢視控件會在編輯開始時以及取消或完成時通知父視窗。 編輯完成時,父視窗會負責視需要更新專案的標籤。

標籤編輯開始時,樹視圖控件會傳送其父視窗TVN_BEGINLABELEDIT通知訊息。 藉由處理此通知,應用程式可以允許編輯某些標籤,並防止編輯其他標籤。 傳回零允許編輯,並傳回非零會防止它。

當標籤編輯取消或完成時,樹視圖控件會傳送其父視窗 TVN_ENDLABELEDIT 通知訊息。 lParam 參數是NMTVDISPINFO結構的位址 item 參數是一種 TVITEM 結構,可識別專案並包含編輯的文字。 如果父視窗想要保留新標籤,則父視窗會負責更新專案的標籤。 如果取消編輯,TVITEMpszText 成員為零。

在標籤編輯期間,通常是為了回應TVN_BEGINLABELEDIT通知訊息,您可以使用TVM_GETEDITCONTROL訊息來擷取用於標籤編輯的編輯控制件的句柄。 您可以將編輯控件 傳送EM_SETLIMITTEXT 訊息,以限制使用者可以輸入或子類別編輯控件的文字數量,以攔截和捨棄無效字元。 不過請注意,只有在 傳送TVN_BEGINLABELEDIT之後 ,才會顯示編輯控件。

樹視圖專案位置

當專案使用 TVM_INSERTITEM 訊息新增至樹視圖控件時,就會設定專案的初始位置。 訊息包含 TVINSERTSTRUCT 結構,指定要插入新專案的父專案句柄和專案的句柄。 第二個句柄必須識別指定父系的子專案或下列其中一個值:TVI_FIRST、TVI_LAST或TVI_SORT。

指定TVI_FIRST或TVI_LAST時,樹視圖控件會將新專案放在指定父專案子專案清單的開頭或結尾。 指定TVI_SORT時,樹視圖控件會根據專案標籤的文字,依字母順序將新專案插入子項目清單中。

您可以使用TVM_SORTCHILDREN訊息,依字母順序放置父專案的子項目清單。 訊息包含參數,指定是否依字母順序排序從指定父專案遞減的所有子專案層級。

TVM_SORTCHILDRENCB訊息可讓您根據您定義的準則來排序子專案。 當您使用此訊息時,您會指定一個應用程式定義的回調函式,每當需要決定兩個子項目的相對順序時,樹視圖控件就可以呼叫該函式。 回呼函式會針對要比較的專案接收兩個 32 位的應用程式定義值,以及您在傳送 TVM_SORTCHILDRENCB時指定的第三個 32 位值。

樹視圖項目狀態概觀

樹視圖控件中的每個專案都有目前的狀態。 每個專案的狀態資訊都包含一組位旗標,以及指出項目狀態影像和重疊影像的影像清單索引。 位旗標會指出專案是否已選取、停用、展開等等。 在大多數情況下,樹視圖控件會自動設定項目的狀態以反映用戶動作,例如選取專案。 不過,您也可以使用TVM_SETITEM訊息來設定項目的狀態,也可以使用TVM_GETITEM訊息來擷取專案的目前狀態。 如需項目狀態的完整清單,請參閱 樹視圖控件項目狀態

專案的目前狀態是由TVITEM結構的狀態成員所指定。 樹視圖控件可能會變更項目的狀態以反映用戶動作,例如選取專案或將焦點設定為專案。 此外,應用程式可變更項目的狀態以停用或隱藏項目,或指定重疊影像或狀態影像。

當您指定或變更項目的狀態時,TVITEM 的狀態掩碼成員會指定要設定的狀態位,而狀態成員會包含這些位的新值。

若要設定專案的重疊影像,狀態掩碼必須包含TVIS_OVERLAYMASK值,而且狀態必須包含使用 INDEXTOOVERLAYMASK 宏來移動左 8 位重疊影像的單一索引。 索引可以是零,以指定沒有重疊影像。

狀態影像會顯示在項目圖示旁,以指出應用程式定義的狀態。 狀態映像包含在傳送TVM_SETIMAGELIST訊息所指定的狀態映像清單中。 若要設定專案的狀態影像,請在TVITEM結構的狀態掩碼成員中包含TVIS_STATEIMAGEMASK值。 結構 狀態成員的位 12 到 15 位會指定要繪製之影像的狀態 影像清單中索引。

若要設定狀態影像索引,請使用 INDEXTOSTATEIMAGEMASK 此宏會採用索引,並適當地設定位 12 到 15。 若要指出項目沒有狀態影像,請將索引設定為零。 此慣例表示狀態映像清單中的影像零不能當做狀態映像使用。 若要隔離狀態成員的12到15位,請使用TVIS_STATEIMAGEMASK遮罩。 如需重疊和狀態影像的詳細資訊,請參閱 樹視圖影像清單

項目選取

樹視圖控件會在選取範圍從某個專案變更為另一個專案時通知父視窗,方法是傳送 TVN_SELCHANGINGTVN_SELCHANGED 通知訊息。 兩個通知均包含一個值,該值指定變更為按一下滑鼠或是按下按鍵的結果。 通知還包含取得選取範圍的項目和遺失選取範圍的項目的相關資訊。 您可以使用這項資訊來設定項目屬性,而其屬性則視項目的選取狀態而定。 傳 回 TRUE 以回應TVN_SELCHANGING可防止選取範圍變更,並傳回 FALSE 允許變更。

應用程式可以藉由傳送 TVM_SELECTITEM 訊息來變更選取範圍。

項目資訊

樹視圖控件支援一些擷取控件中專案相關信息的訊息。

TVM_GETITEM訊息可以擷取專案的句柄和屬性。 項目的屬性包括其目前狀態、控件影像清單中的索引,以及專案的選取和未選取的點陣圖影像、指出專案是否有子專案、專案的卷標字串位址,以及專案的應用程式定義 32 位值。

TVM_GETNEXTITEM訊息會擷取樹視圖專案,該專案具有目前專案的指定關聯性。 訊息可以擷取專案的父代、下一個或上一個可見專案、第一個子專案等等。

TVM_GETITEMRECT訊息會擷取樹視圖專案的周框。 TVM_GETCOUNT和TVM_GETVISIBLECOUNT訊息會擷取樹視圖控件中的項目計數,以及樹視圖控件視窗中可完全可見的項目計數。 您可以使用TVM_ENSUREVISIBLE訊息來確保特定項目可見

樹視圖影像清單

樹視圖控件中的每個專案都可以有四個與其相關聯的位圖影像。

  • 選取專案時所顯示的影像,例如開啟的資料夾。
  • 未選取專案時所顯示的影像,例如關閉的資料夾。
  • 在選取或未選取影像上以透明方式繪製的重疊影像。
  • 狀態影像,這是顯示在選取或未選取影像左邊的額外影像。 您可以使用狀態影像,例如已核取和已清除的複選框,來指出應用程式定義的項目狀態。

根據預設,樹視圖控件不會顯示專案影像。 若要顯示專案影像,您必須建立影像清單,並將其與 控件產生關聯。 如需影像清單的詳細資訊,請參閱 影像清單

樹視圖控件可以有兩個影像清單:一般影像清單和狀態影像清單。 一般影像清單會儲存選取、非選取和重疊影像。 狀態映像清單會儲存狀態映像。 使用 ImageList_Create 函式來建立影像清單,並使用其他影像清單函式將點陣圖新增至影像清單。 然後,若要將影像清單與樹視圖控件產生關聯,請使用 TVM_SETIMAGELIST 訊息。 TVM_GETIMAGELIST訊息會擷取其中一個樹視圖控件影像清單的句柄。 如果您需要將更多影像新增至清單,此訊息會很有用。

除了選取和未選取的影像之外,樹視圖控件的一般影像清單最多可以包含四個重疊影像。 重疊影像是由單一式索引所識別,並設計成以透明方式繪製在選取和未選取的影像上。 若要將重疊遮罩索引指派給一般影像清單中的影像,請呼叫 ImageList_SetOverlayImage 函式。

根據預設,所有專案都會在選取和未選取狀態的一般影像清單中顯示第一個影像。 此外,根據預設,專案不會顯示重疊影像或狀態影像。 您可以傳送TVM_INSERTITEMTVM_SETITEM訊息,來變更專案的這些預設行為。 這些訊息會 使用TVITEM 結構來指定專案的影像清單索引。

若要指定專案的選取和未選取的影像,請在TVITEM結構的遮罩成員設定TVIF_SELECTEDIMAGE和TVIF_IMAGE位,並從iSelectImage和image成員的控件一般影像清單中指定索引。 或者,您可以在 iSelectImage 和 iImage指定I_IMAGECALLBACK值,而不是指定索引。 這會導致控制件在每次重新繪製項目時查詢其父視窗是否有影像清單索引。 控件會 傳送TVN_GETDISPINFO 通知訊息來擷取索引。

若要將重疊影像與專案產生關聯,請使用 INDEXTOOVERLAYMASK 宏,在專案的 TVITEM 結構狀態成員中指定重疊遮罩索引。 您也必須在 stateMask 成員中設定TVIS_OVERLAYMASK位。 重迭遮罩索引是以一為基式;零的索引表示未指定重疊影像。

狀態映像會儲存在個別的狀態映射清單中,並由其索引識別。 若要指定狀態映像清單,請傳送 TVM_SETIMAGELIST 訊息。 不同於清單檢視控件,它會使用單一式索引來識別狀態影像,樹視圖控件狀態影像是由以零起始的索引來識別。 不過,零的索引表示項目沒有狀態影像。 因此,影像零不能當做狀態映射使用。 如需專案狀態和狀態影像的進一步討論,請參閱 樹視圖項目狀態概觀

拖放作業

樹視圖控件會在用戶開始拖曳專案時通知父視窗。 當用戶開始使用滑鼠左鍵拖曳專案時,父視窗會收到TVN_BEGINDRAG通知訊息,當使用者以右按鈕開始拖曳時,就會收到TVN_BEGINRDRAG通知訊息。 您可以藉由提供樹視圖控件TVS_DISABLEDRAGDROP樣式,防止樹視圖控件傳送這些通知。

您可以使用TVM_CREATEDRAGIMAGE訊息,取得在拖曳作業期間顯示的影像。 樹視圖控件會根據所拖曳項目的標籤建立拖曳位圖。 然後樹檢視控件會建立影像清單、將點陣圖加入其中,並將句柄傳回至影像清單。

您必須提供實際拖曳項目的程式碼。 這通常牽涉到使用影像清單函式的拖曳功能,以及處理 在拖曳作業開始後傳送至父視窗的WM_MOUSEMOVEWM_LBUTTONUP (或 WM_RBUTTONUP)訊息。

如果樹檢視控件中的專案是拖放作業的目標,您必須知道滑鼠指標何時位於目標專案上。 您可以使用 TVM_HITTEST 訊息來找出。 您可以指定TVHITTESTINFO結構的位址,其中包含滑鼠指標的目前座標。 當 SendMessage 函式傳回時,結構會包含旗標,指出滑鼠指標相對於樹視圖控件的位置。 如果指標位於樹視圖控件中的專案上方,結構也會包含專案的句柄。

您可以使用TVM_SETITEM訊息,將狀態設定為TVIS_DROPHILITED值,以指出專案是拖放作業的目標。 具有這個狀態的項目會繪製為用來表示拖放目標的樣式。

樹視圖控件通知訊息

樹檢視控件會以WM_NOTIFY訊息的形式,將下列通知訊息傳送至其父視窗。

通知 描述
TVN_BEGINDRAG 發出拖放作業的開始訊號。
TVN_BEGINLABELEDIT   發出就地標籤編輯開始的訊號。
TVN_BEGINRDRAG 表示滑鼠右鍵已啟動拖放作業。
TVN_DELETEITEM 表示刪除特定專案。
TVN_ENDLABELEDIT 發出標籤編輯結尾的訊號。
TVN_GETDISPINFO 要求樹檢視控件需要顯示項目的資訊。
TVN_ITEMEXPANDED 表示父專案的子專案清單已展開或折疊。
TVN_ITEMEXPANDING 表示父專案的子專案清單即將展開或折疊。
TVN_KEYDOWN 發出鍵盤事件的訊號。
TVN_SELCHANGED 表示選取範圍已從某個項目變更為另一個專案。
TVN_SELCHANGING 表示選取範圍即將從某個項目變更為另一個專案。
TVN_SETDISPINFO 通知父視窗,它必須更新它為專案維護的資訊。

 

默認樹檢視控件訊息處理

本節描述樹檢視控件所執行的視窗訊息處理。 此檔的其他章節會討論樹視圖控件特有的訊息,因此此處並未包含這些訊息。

訊息 已執行處理
WM_COMMAND 處理EN_UPDATEEN_KILLFOCUS編輯控制項通知訊息,並將所有其他編輯控制項通知轉送至父視窗。 沒有傳回值。
WM_CREATE 配置記憶體並初始化內部數據結構。 如果成功,則會傳回零,否則傳回 -1。
WM_DESTROY 釋放與控件相關聯的所有系統資源。 它會傳回零。
WM_ENABLE 啟用或停用控制件。
WM_ERASEBKGND 使用樹檢視控件的目前背景色彩清除視窗背景。 它會傳 回 TRUE
WM_GETDLGCODE 傳回DLGC_WANTARROWS和DLGC_WANTCHARS值的組合。
WM_GETFONT 傳回目前標籤字型的句柄。
WM_HSCROLL 捲動樹視圖控件。 如果捲動發生,則會傳回 TRUE否則傳回 FALSE
WM_KEYDOWN TVN_KEYDOWN 通知訊息傳送至所有索引鍵的父視窗。 當使用者按下 ENTER 鍵時,傳送NM_RETURN (樹視圖) 通知訊息。 當使用者按下方向鍵或PAGE UP、PAGE DOWN、HOME、END或BACKSPACE鍵時,它會移動插入號。 當使用者按下 CTRL 鍵與這些按鍵組合時,它會捲動樹視圖控件。 如果已處理索引鍵,則會傳回 TRUE,否則傳回 FALSE
WM_KILLFOCUS 如果有的話,請重新修補焦點專案,並將NM_KILLFOCUS(樹視圖)通知訊息傳送至父視窗。
WM_LBUTTONDBLCLK 取消標籤編輯,如果按兩下專案,就會將 NM_DBLCLK(樹視圖) 通知訊息傳送至父視窗。 如果父視窗傳回 0,樹視圖控件會切換專案的展開狀態,傳送父視窗 TVN_ITEMEXPANDINGTVN_ITEMEXPANDED 通知訊息。 沒有傳回值。
WM_LBUTTONDOWN 如果使用者按兩下與父項目相關聯的按鈕,請切換展開的狀態。 如果使用者按兩下專案標籤,樹檢視控件會選取並將焦點設定為專案。 如果使用者在放開滑鼠按鈕之前移動滑鼠,則樹視圖控件會開始拖放作業。 沒有傳回值。
WM_PAINT 小畫家 樹視圖控件的無效區域。 它會傳回零。 如果 wParam 參數不是 NULL,控件會假設該值是裝置內容的句柄(HDC),並使用該裝置內容繪製。
WM_RBUTTONDOWN 檢查是否已按下專案,並開始拖曳作業。 如果作業已經開始,它會將TVN_BEGINRDRAG通知訊息傳送至父視窗,並反白顯示置放目標。 否則,它會將NM_RCLICK(樹視圖)通知訊息傳送至父視窗。 沒有傳回值。
WM_SETFOCUS 如果有的話,請重新修補焦點專案,並將NM_SETFOCUS通知訊息傳送至父視窗。
WM_SETFONT 儲存指定的字型控點,並使用新的字型重新繪出樹視圖控件。
WM_SETREDRAW 設定或清除重繪旗標。 設定重繪旗標之後,會重新繪製樹視圖控件。 它會傳回零。
WM_SIZE 重新計算取決於樹視圖控件工作區大小的內部變數。 它會傳 回 TRUE
WM_STYLECHANGED 取消標籤編輯,並使用新樣式重新繪製樹檢視控件。 它會傳回零。
WM_SYSCOLORCHANGE 如果已設定重繪旗標,請使用新的色彩重新繪製樹檢視控件。 沒有傳回值。
WM_TIMER 開始編輯專案標籤。 如果使用者按下焦點專案的標籤,則樹視圖控件會設定定時器,而不是立即進入編輯模式。 當使用者按兩下卷標時,定時器可以讓樹檢視避免進入編輯模式。 它會傳回零。
WM_VSCROLL 捲動樹視圖控件。 如果捲動發生,則會傳回 TRUE否則傳回 FALSE

 

範例:CustDTv 說明樹檢視中的自訂繪製 (Q248496)