Share via


關於屬性表

屬性 是一個視窗,可讓用戶檢視和編輯項目的屬性。 例如,電子錶格應用程式可以使用屬性表來允許使用者設定單元格的字型和框線屬性,或檢視和設定裝置的屬性,例如磁碟驅動器、印表機或滑鼠。

本節討論下列主題。

屬性表基本概念

若要在應用程式中實作屬性表,請在專案中加入Prsht.h頭檔。 Prsht.h 包含與屬性表搭配使用的所有標識碼。

屬性表包含一或多個稱為頁面的重迭子視窗,每個視窗都包含用於設定相關屬性群組的控制視窗。 例如,頁面可以包含控件來設定專案的字型屬性,包括類型樣式、點大小、色彩等等。 每個頁面都有一個索引標籤,用戶可以選取將頁面帶入屬性表的前景。 例如,[日期時間] 控制面板應用程式會顯示下列屬性表。

screen shot of a property sheet with two tabs, one of which shows a clock and a monthly calendar control

具有多個索引標籤頁面的標準屬性表可讓使用者隨機存取所有屬性。 如果更適合讓屬性依序設定,您可以使用 精靈

屬性表對話框

屬性表及其包含的頁面實際上是對話框。 屬性表是系統定義的對話框,可管理頁面並提供它們的通用容器。 屬性表對話框可以是強制回應或無模式。 其中包含框架、標題列和四個按鈕:[確定]、[取消]、[套用] 和 [選擇性] [說明]。 當使用者按鍵時,頁面的 對話框程式會以WM_NOTIFY 訊息的形式接收通知碼。

注意

本節中的所有資訊都不適用於精靈,其外觀和行為有些不同。 例如,精靈有一組不同的按鈕,而且沒有索引標籤。 如需詳細資訊,請參閱 建立精靈。

屬性表中的每個頁面都是應用程式定義的無模式對話框,可管理用來檢視和編輯專案屬性的控件視窗。 您提供用來建立每個頁面的對話框範本,以及管理控件及設定對應專案屬性的對話框程式。

屬性表會在頁面取得或遺失啟用時,以及使用者按兩下 [確定]、[取消]、[套用] 或 [說明] 按鈕時,將通知碼傳送至頁面的對話框程式。 通知會以WM_NOTIFY訊息的形式傳送。 lParam 參數是NMHDR結構的位址,其中包含屬性表對話框的視窗句柄。

某些通知代碼需要頁面傳回 TRUEFALSE ,以回應 WM_NOTIFY 訊息。 若要這樣做,頁面必須使用 SetWindowLong 函式,將頁面對話框的DWL_MSGRESULT值設定TRUEFALSE

頁面

屬性表必須至少包含一個頁面,但不能包含超過 Windows 頭檔中所定義的 MAXPROPPAGES。 每個頁面都有以零起始的索引,屬性表會根據頁面加入至屬性表的順序來指派。 索引會用於您傳送至屬性表的訊息中。

屬性頁可以包含巢狀對話框。 如果這樣做,您必須包含最上層對話框的WS_EX_CONTROLPARENT樣式,並使用父對話框的句柄呼叫 IsDialogMessage 函式。 這可確保使用者可以使用助記鍵和對話框導覽鍵,將焦點移至巢狀對話框中的控件。

每個頁面都有對應的圖示和標籤。 屬性表會為每個頁面建立索引標籤,並在索引標籤中顯示圖示和標籤。所有屬性表頁面都預期會使用非Bold 字型。 若要確保字型不是粗體,請在 對話框範本中指定DS_3DLOOK 樣式。

頁面的對話框程式不得呼叫 EndDialog 函式。 這麼做將會終結整個屬性表,而不只是頁面。

屬性表頁面的大小下限是水準 212 個對話框單位,垂直 114 個對話框單位。 如果頁面對話框小於這個,頁面將會放大,直到符合最小大小為止。 Prsht.h 頭檔包含三組屬性表頁面的建議大小,如下表所示。

大小 描述
PROP_SM_CXDLG 小屬性表頁面的對話框單位寬度。
PROP_SM_CYDLG 小屬性表頁面的對話框單位的高度。
PROP_MED_CXDLG 寬度,以對話框單位為單位,為中型屬性表頁面。
PROP_MED_CYDLG [高度],以對話框單位表示的中型屬性表頁面。
PROP_LG_CXDLG 大型屬性表頁面的對話框單位寬度。
PROP_LG_CYDLG 大型屬性表頁面的對話框單位的高度。

使用這些建議的大小有助於確保應用程式與其他 Microsoft Windows 應用程式之間的視覺一致性。

在 Microsoft Visual Studio 資源編輯器中,您可以在 [新增資源] 對話框中建立適當大小的頁面。 展開 [對話框] 節點,然後選取 [IDD_PROPPAGE_LARGE]、[IDD_PROPPAGE_MEDIUM] 或 [IDD_PROPPAGE_SMALL]。

屬性表會自動調整大小以容納最大的頁面。

屬性表建立

建立屬性表之前,您必須定義一或多個頁面。 這牽涉到填入 PROPSHEETPAGE 結構,其中包含頁面的相關信息,也就是其圖示、標籤、對話框範本、對話框程式等等,然後在呼叫 CreatePropertySheetPage 函式時指定結構的位址。 函式會傳回可唯一識別頁面之 HPROPSHEETPAGE 類型的句柄。

若要建立屬性表,您可以在對 PropertySheet 函式的呼叫中指定 PROPSHEETHEADER 結構的位址。 結構會定義屬性表的圖示和標題,也包含您使用 CreatePropertySheetPage 取得之 HPROPSHEETPAGE 句柄數位的位址。 當 PropertySheet 建立屬性表時,它會包含數位中識別的頁面。 頁面會以數位中包含的相同順序出現在屬性表中。

將頁面指派給屬性表的另一種方式是指定 PROPSHEETPAGE 結構的數位,而不是 HPROPSHEETPAGE 句柄的數位。 在此情況下, PropertySheet 會在將頁面新增至屬性表之前,先建立頁面的句柄。

建立頁面時,其對話框程式會收到 WM_INITDIALOG 訊息。 訊息的 lParam 參數是建立頁面時所定義 PROPSHEETPAGE 結構的複本指標。 特別是建立頁面時,結構的 lParam 成員可用來將應用程式定義的資訊傳遞至對話框程式。 除了 lParam 成員之外,這個結構必須視為唯讀。 修改 lParam 以外的任何專案將會產生無法預測的結果。

當系統後續將頁面的 PROPSHEETPAGE 結構複本傳遞至您的應用程式時,它會使用相同的指標。 結構的任何變更都會一併傳遞。 因為系統會忽略 lParam 成員,所以可以修改它,將資訊傳送至應用程式的其他部分。 例如,您可以使用 lParam 將資訊傳遞至頁面的 PropSheetPageProc 回呼函式。

PropertySheet 會自動設定屬性表的大小和初始位置。 此位置是以擁有者視窗的位置為基礎,而大小是以建立屬性表時頁面陣列中指定的最大頁面為基礎。 如果您希望頁面符合屬性表底部四個按鈕的寬度,請將最寬頁面的寬度設定為190個對話框單位。

屬性表的大小是從資源檔中對話框範本的寬度高度屬性計算。 如需詳細資訊,請參閱 DIALOG ResourceDIALOGEX 資源 不過請注意,基於相容性考慮,維度會相對於 MS Shell Dlg 字型計算,而不是頁面所使用的字型。 如果您設計使用另一個字型的頁面,可以使用下列其中一個建議。

  • 調整對話框範本的維度,以補償 MS Shell Dlg 字型與頁面實際使用的字型之間的大小差異。 例如,如果您選擇寬度為 MS Shell Dlg 兩倍的字型,請將對話框範本的 width 屬性設定為一般用法的兩倍。
  • 使用 DIALOGEX 範本並設定DS_SHELLFONT對話框樣式。 在此情況下,屬性表管理員會解譯對話框範本維度,相對於對話框範本所使用的字型。

新增和移除頁面

建立屬性表之後,應用程式可以藉由傳送 PSM_ADDPAGE 訊息,將頁面新增至現有頁面集的結尾。 若要在現有頁面之間插入頁面,請傳送 PropSheet_InsertPage 訊息。 請注意,屬性表的大小無法在建立之後變更。 任何新增或插入的頁面都必須不大於屬性表中目前最大的頁面。 若要移除頁面,請傳送 PSM_REMOVEPAGE 訊息。

當您定義頁面時,您可以指定屬性表在建立或移除頁面時所呼叫之 PropSheetPageProc 回 呼函式的位址。 使用 PropSheetPageProc 可讓您執行個別頁面的初始化和清除作業。

注意

當屬性表正在操作頁面清單時,會發生許多訊息和一個函數調用。 執行此動作時,嘗試修改頁面清單將會產生無法預期的結果。 請勿在您的 PropSheetPageProc 實作中新增、插入或移除頁面,或處理下列通知和 Windows 訊息時。

如果您在處理其中一則訊息時或 PropSheetPageProc 運作時需要修改屬性表頁面,請張貼私人 Windows 訊息。 在屬性表管理員完成其工作之後,您的應用程式才會收到該訊息,此時可以安全地修改頁面清單。

當屬性表終結時,它會自動終結已新增至它的所有頁面。 頁面會依用來建立頁面的陣列中指定的反向順序終結。 若要終結 CreatePropertySheetPage 函式所建立但未新增至屬性表的頁面,請使用 DestroyPropertySheetPage 函式。

屬性表標題和頁面標籤

您可以在用來建立屬性表的 PROPSHEETHEADER 結構中指定屬性表的標題。 如果 dwFlags 成員包含PSH_PROPTITLE值,則屬性表會根據版本新增後綴 “Properties” 或前置詞 “Properties for”。 您可以使用PSM_SETTITLE訊息,在屬性表建立之後變更標題。 在 Aero Wizard 中,此訊息可用來動態變更內部頁面的標題。

根據預設,屬性表會使用對話框範本中指定的名稱字串做為頁面的標籤。 您可以在定義頁面之 PROPSHEETPAGE 結構的 dwFlags 成員中包含PSP_USETITLE值,以覆寫名稱字串。 指定PSP_USETITLEpszTitle 成員必須包含頁面標籤字串的位址。

頁面啟用

屬性表一次只能有一個使用中的頁面。 啟用的頁面位於頁面重疊堆疊的前景。 用戶選取其索引標籤來啟動頁面;應用程式會使用 PSM_SETCURSEL 訊息來啟動頁面。

屬性表會將 PSN_KILLACTIVE 通知碼傳送至即將遺失啟用的頁面。 回應中,頁面必須驗證使用者對頁面所做的任何變更。 如果頁面在遺失啟用之前需要額外的用戶輸入,請使用SetWindowLong函式將頁面的DWL_MSGRESULT值設定TRUE 此外,頁面必須顯示描述問題的消息框,並提供建議的動作。 當無法啟用時,請將DWL_MSGRESULT設定FALSE

在看到取得啟用的頁面之前,屬性表會將PSN_SETACTIVE通知碼傳送至頁面。 頁面必須藉由初始化其控件視窗來回應。

說明按鈕

屬性表可以顯示兩個 [說明] 按鈕:顯示在框架底部的屬性表 [說明] 按鈕、[確定/取消套/] 按鈕旁,以及提供內容相關說明的標準 標題 列按鈕。

屬性表 [說明] 按鈕是選擇性的,可以逐頁啟用。 若要顯示一或多個頁面的屬性表 [說明] 按鈕:

  • 屬性表 PROPSHEETHEADER 結構的 dwFlags 成員中設定PSH_HASHELP旗標。
  • 針對將顯示 [說明] 按鈕的每個頁面,在頁面 PROPSHEETPAGE 結構的 dwFlags 成員中設定PSP_HASHELP旗標。

當使用者按兩下 [說明] 按鈕時,使用中的頁面會收到 PSN_HELP 通知碼。 頁面必須藉由顯示說明資訊來回應,通常是藉由呼叫 WinHelp 函 式。

拿掉標題列說明按鈕

默認會顯示 標題 列 [說明] 按鈕,讓內容相關說明一律可供 [確定/取消/套用] 按鈕使用。 不過,如有必要,可以移除此按鈕。 若要移除屬性表的 標題 列 [說明] 按鈕:

若要實作屬性表回呼函式,以移除 標題 列 [說明] 按鈕:

  • 屬性表 PROPSHEETHEADER 結構的 dwFlags 成員中設定PSH_USECALLBACK旗標。
  • 將 PROPSHEETHEADER 結構的 pfnCallBack 成員設定為指向回呼函式。
  • 實作回調函式。 當此函式收到 PSCB_PRECREATE 訊息時,它也會收到屬性表對話框範本的指標。 從此範本中移除DS_CONTEXTHELP樣式。

下列範例說明如何實作這類回呼函式:

int CALLBACK RemoveContextHelpProc(HWND hwnd, UINT message, LPARAM lParam)
{
    switch (message) 
    {
    case PSCB_PRECREATE:
        // Remove the DS_CONTEXTHELP style from the
        // dialog box template
        if (((LPDLGTEMPLATEEX)lParam)->signature ==    
           0xFFFF)
           {
            ((LPDLGTEMPLATEEX)lParam)->style 
            &= ~DS_CONTEXTHELP;
        }
        else {
            ((LPDLGTEMPLATE)lParam)->style 
            &= ~DS_CONTEXTHELP;
        }
        return TRUE;
    }
    return TRUE;
}

如果未定義 DLGTEMPLATEEX 結構,請包含下列宣告:

#include <pshpack1.h>

typedef struct DLGTEMPLATEEX
{
    WORD dlgVer;
    WORD signature;
    DWORD helpID;
    DWORD exStyle;
    DWORD style;
    WORD cDlgItems;
    short x;
    short y;
    short cx;
    short cy;
} DLGTEMPLATEEX, *LPDLGTEMPLATEEX;

#include <poppack.h>

確定、取消和套用按鈕

[確定] 和 [套用] 按鈕很類似;兩者都會指示屬性表的頁面來驗證並套用使用者所做的屬性變更。 唯一的差別在於按兩下 [ 確定 ] 按鈕會導致套用變更之後終結屬性表。

當使用者按兩下 [確定] 或 [套用] 按鈕時,屬性表會將PSN_KILLACTIVE通知傳送至使用中頁面,讓您有機會驗證用戶的變更。 如果變更有效,頁面必須呼叫 SetWindowLong 函式,並將DWL_MSGRESULT值設定為 FALSE 如果使用者的變更無效,頁面必須將DWL_MSGRESULT設定TRUE,並顯示對話框,告知用戶問題。 頁面會保持使用中狀態,直到將DWL_MSGRESULT設定FALSE,以回應PSN_KILLACTIVE訊息。

在頁面將DWL_MSGRESULT設定為 FALSE 以回應PSN_KILLACTIVE通知之後,屬性表會將PSN_APPLY通知傳送給每個頁面。 當頁面收到此通知時,它必須將新的屬性套用至對應的專案。 若要向屬性表指出變更對頁面有效,請呼叫 SetWindowLong,並將 DWL_MSGRESULT設定為 PSNRET_NOERROR 如果頁面的變更無效,請傳回錯誤。 這樣做可防止屬性表被終結,並將焦點傳回至收到PSN_APPLY通知的頁面,或按下 [套用] 按鈕時具有焦點的頁面。 若要傳回錯誤,並指出哪個頁面會收到焦點,請將DWL_MSGRESULT設定為下列其中一個值。

  • PSNRET_INVALID。 屬性表將不會終結,並將焦點傳回至此頁面。
  • PSNRET_INVALID_NOCHANGEPAGE。 屬性表將不會終結,焦點將會傳回按下按鈕時具有焦點的頁面。

應用程式可以使用PSM_APPLY訊息來模擬 [套用] 按鈕的選取範圍。

當頁面變成使用中時,[套用] 按鈕一開始會停用,表示尚未套用任何屬性變更。 當頁面透過其中一個控件接收輸入,指出使用者已編輯屬性時,頁面必須將PSM_CHANGED訊息傳送至屬性表。 訊息會導致屬性表啟用 [ 套用 ] 按鈕。 如果使用者後續按兩下 [套用] 或 [取消] 按鈕,頁面必須重新初始化其控件,然後傳送PSM_UNCHANGED訊息,以再次停用 [用] 按鈕。

有時候[ 套用 ] 按鈕會導致頁面對屬性表進行變更,而且無法復原變更。 發生這種情況時,頁面必須將PSM_CANCELTOCLOSE訊息傳送至屬性表。 訊息會使屬性表將 [確定] 按鈕的文字變更為 [關閉],表示無法取消套用的變更。

有時候頁面會變更需要重新啟動 Windows 的系統設定,或在變更生效之前重新啟動系統。 進行這類變更之後,頁面必須將PSM_RESTARTWINDOWSPSM_REBOOTSYSTEM訊息傳送至屬性表。 這些訊息會導致 PropertySheet 函式在屬性表終結之後傳回 ID_PSRESTARTWINDOWSID_PSREBOOTSYSTEM 值。

當使用者按兩下 [取消] 按鈕時,屬性表會將PSN_RESET通知碼傳送至所有頁面,表示屬性表即將終結。 頁面必須使用通知來執行清除作業。

精靈

精靈是屬性表的特殊類型。 精靈的設計目的是以應用程式所控制的順序一次呈現一個頁面。 使用者不必按下索引標籤來從頁面群組中選取,而是透過按下按鈕,一次巡覽一個頁面。 例如,下列螢幕快照顯示 [新增硬體精靈] 中的歡迎頁面:

screen shot of the welcome page of a wizard

下列螢幕快照顯示「航空精靈」的第一頁,這是 Windows Vista 中引進的新樣式。

screen shot of the first page of an aero wizard

如需精靈的完整討論,請參閱 建立精靈