Share via


自訂控制項

本節包含應用程式定義或自定義控件的相關信息。

下列主題會討論。

建立擁有者繪製的控件

按鈕、功能表、靜態文字控件、清單框和下拉式方塊可以使用擁有者繪製的樣式旗標來建立。 當控件具有擁有者繪製樣式時,系統會像往常一樣處理使用者與控件的互動,執行偵測使用者何時選擇按鈕並通知按鈕擁有者事件的這類工作。 不過,因為控件是擁有者繪製,因此控件的父視窗負責控件的視覺外觀。 每當必須繪製控件時,父視窗就會收到訊息。

對於按鈕和靜態文字控件,擁有者繪製的樣式會影響系統繪製整個控件的方式。 對於清單框和下拉式方塊,父視窗會繪製控件內的專案,而控件會繪製自己的外框。 例如,應用程式可以自定義清單框,讓它在清單中每個專案旁邊顯示小型點陣圖。

下列範例程式代碼示範如何建立擁有者繪製的靜態文字控件。 假設已定義 Unicode。

// g_myStatic is a global HWND variable.
g_myStatic = CreateWindowEx(0, L"STATIC", L"Some static text", 
            WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 
            25, 125, 150, 20, hDlg, 0, 0, 0);

在下列範例中,從包含上一個範例中所建立控件之對話框的視窗程式, 使用預設字型以自定義色彩顯示文字來處理WM_DRAWITEM 訊息。 請注意,處理WM_DRAWITEM時,您不需要呼叫 Begin 小畫家End 小畫家。

case WM_DRAWITEM:
{
    LPDRAWITEMSTRUCT pDIS = (LPDRAWITEMSTRUCT)lParam;
    if (pDIS->hwndItem == g_myStatic)
    {
        SetTextColor(pDIS->hDC, RGB(100, 0, 100));
        WCHAR staticText[99];
        int len = SendMessage(myStatic, WM_GETTEXT, 
            ARRAYSIZE(staticText), (LPARAM)staticText);
        TextOut(pDIS->hDC, pDIS->rcItem.left, pDIS->rcItem.top, staticText, len);
    }
    return TRUE;
}

如需擁有者繪製控件的詳細資訊,請參閱 建立擁有者繪製的清單框擁有者繪製下拉式方塊。

子類別化現有控件的 Window 類別

子類別化現有的控件是建立自定義控件的另一種方式。 子類別程式可以藉由處理影響所選取行為的訊息,來改變控件的選取行為。 所有其他訊息都會傳遞至控件的原始視窗程式。 例如,應用程式可以透過子類別化控件及處理 WM_PAINT 訊息,在唯讀的單行編輯控件中顯示文字旁的小位圖。 如需詳細資訊,請參閱關於視窗程式和子類別化控件

實作應用程式定義的窗口類別

若要建立未明確根據現有控件的控件,應用程式必須建立並註冊窗口類別。 為自定義控件註冊應用程式定義的視窗類別的程式,與註冊一般窗口的類別相同。 若要建立自定義控件,請在 CreateWindowEx 函式或對話框範本中指定視窗類別的名稱。 每個類別都必須有唯一的名稱、對應的視窗程式和其他資訊。

視窗程式至少會繪製控件。 如果應用程式使用控件讓使用者輸入資訊,視窗程式也會處理鍵盤和滑鼠的輸入訊息,並將通知訊息傳送至父視窗。 此外,如果控件支援控件訊息,視窗程式會處理父視窗或其他視窗傳送給它的訊息。 例如,控件通常會處理 由對話框傳送的WM_GETDLGCODE 訊息,以指示對話框以指定方式處理鍵盤輸入。

如果訊息影響控件的作業,則應用程式定義控件的視窗程序應該在下表中處理任何預先定義的控件訊息。

訊息 建議
WM_GETDLGCODE 如果控件使用 ENTER、ESC、TAB 或箭頭鍵,則處理。 IsDialogMessage 函式會將此訊息傳送至對話框中的控件,以判斷是要處理索引鍵,還是將它們傳遞至控件。
WM_GETFONT 處理 WM_SETFONT 訊息是否也已處理。
WM_GETTEXT 如果控件文字與 CreateWindowEx 函式所指定的標題不同,則處理 。
WM_GETTEXTLENGTH 如果控件文字與 CreateWindowEx 函式所指定的標題不同,則處理 。
WM_KILLFOCUS 如果控制件顯示插入號、焦點矩形或其他專案,表示其具有輸入焦點,則處理 。
WM_SETFOCUS 如果控制件顯示插入號、焦點矩形或其他專案,表示其具有輸入焦點,則處理 。
WM_SETTEXT 如果控件文字與 CreateWindowEx 函式所指定的標題不同,則處理 。
WM_SETFONT 如果控件顯示文字,則處理。 系統會在建立具有DS_SETFONT樣式的對話框時傳送此訊息。

 

應用程式定義的控件訊息專屬於指定的控件,而且必須使用 SendMessage 或 SendDlgItemMessage 函式明確地傳送至控件。 每個訊息的數值必須是唯一的,而且不得與其他視窗訊息的值衝突。 為了確保應用程式定義的訊息值不會衝突,應用程式應該藉由將唯一數位新增至WM_USER值來建立每個值。

從控件傳送通知

自定義控制項可能需要將事件的通知傳送至父視窗,讓主應用程式可以回應這些事件。 例如,當使用者選取專案時,自定義清單檢視可能會傳送通知,並在按兩下專案時傳送另一個通知。

通知會以WM_COMMANDWM_NOTIFY訊息的形式傳送。 WM_NOTIFY訊息會攜帶比WM_COMMAND訊息更多的資訊。

控件標識碼是應用程式用來識別傳送訊息之控件的唯一號碼。 應用程式會在建立控件時設定控件的標識碼。 應用程式會在 CreateWindowEx 函式的 hMenu 參數或 DLGITEMTEMPLATEEX 結構的標識符成員指定識別碼。

因為控件本身未設定控件標識碼,所以控件必須先擷取標識碼,才能傳送通知訊息。 控件必須使用 GetDlgCtrlID 函式來擷取自己的控件識別碼。 雖然控件標識碼是在建立控件時指定為功能表句柄, 但是無法使用 GetMenu 函式來擷取標識碼。 或者,控件可以在處理WM_CREATE訊息時,從 CREATESTRUCT 結構中的 hMenu 成員擷取標識碼。

下列範例顯示 hwndControl 是控件視窗的句柄,而CN_VALUECHANGED是自定義通知定義,會顯示傳送控件特定通知的兩種方式。

 // Send as WM_COMMAND.
SendMessage(GetParent(hwndControl), 
    WM_COMMAND,
    MAKEWPARAM(GetDlgCtrlID(hwndControl), CN_VALUECHANGED),
    (LPARAM)hwndControl);

// Send as WM_NOTIFY.           
NMHDR nmh;
nmh.code = CN_VALUECHANGED;
nmh.idFrom = GetDlgCtrlID(hwndControl);
nmh.hwndFrom = hwndControl;
SendMessage(GetParent(hwndControl), 
    WM_NOTIFY, 
    (WPARAM)hwndControl, 
    (LPARAM)&nmh);

請注意, NMHDR 結構可以是包含其他資訊的較大控件定義結構的一部分。 在此範例中,控件的舊值和新值可能包含在這個結構中。 (這類擴充結構會搭配許多標準通知使用;例如,請參閱LVN_INSERTITEM,其使用 NMLISTVIEW 結構。

網頁可及性

所有通用控件都支援 Microsoft Active Accessibility (MSAA),可透過螢幕助讀程式等無障礙技術應用程式,以程式設計方式存取。 MSAA 也可讓 使用者介面自動化 與控件互動,這是一項較新的技術。

自定義控件應該實作 IAccessible 介面(以支援 MSAA)或 使用者介面自動化 介面,或兩者。 否則,無障礙技術產品將只能取得控件視窗非常有限的信息、無法存取控件的屬性,而且無法觸發控件中的事件。

如需讓控件可供存取的詳細資訊,請參閱 Windows 自動化 API

概念

一般控件參考

使用自訂繪製自定義控件的外觀

控制訊息

搭配擁有者繪製控件使用可視化樣式