搭配自訂和Owner-Drawn控制項使用視覺化樣式

本主題描述如何使用視覺化樣式 API,將視覺化樣式套用至自訂控制項或擁有者繪製的控制項。

使用視覺化樣式繪製控制項

ComCtrl32.dll 6 版和更新版本支援視覺化樣式。 如果您的應用程式設定為使用第 6 版和更新版本ComCtrl32.dll,而且系統上有該版本可用,則目前的視覺化樣式會自動套用至應用程式中的所有通用控制項。 不過,目前的視覺化樣式不會自動套用至自訂控制項或擁有者繪製的控制項。 您的應用程式必須包含程式碼,以檢查視覺效果樣式是否可用,如果是的話,請使用視覺化樣式 API,將目前選取的視覺化樣式套用至自訂和擁有者繪製的控制項。

若要檢查視覺化樣式是否可用,請呼叫 IsAppThemed 函式 。 如果無法使用視覺化樣式,請使用後援程式碼來繪製控制項。

如果有視覺化樣式可用,您可以使用 DrawThemeText 等視覺化樣式函式來轉譯控制項。 請注意, DrawThemeTextEx 可讓您自訂文字的外觀,並保留主題字型的某些屬性,同時修改其他屬性。

在目前的視覺化樣式中繪製控制項

  1. 呼叫 OpenThemeData,將您想要套用視覺樣式的控制項 hwnd 傳遞至 ,以及描述控制項類型的類別清單。 類別定義于 Vssym32.h 中。 OpenThemeData 會傳回 HTHEME 控制碼,但如果停用視覺化樣式管理員,或目前的視覺化樣式未提供指定控制項的特定資訊,函式會傳回 Null。 如果傳回值為 Null,請使用非視覺化樣式繪圖函式。
  2. 若要繪製控制項背景,請呼叫 DrawThemeBackgroundDrawThemeBackgroundEx
  3. 若要判斷內容矩形的位置,請呼叫 GetThemeBackgroundContentRect
  4. 若要轉譯文字,請使用 DrawThemeTextDrawThemeTextEx,以 GetThemeBackgroundContentRect傳回的矩形座標為基礎。 這些函式可以在主題的字型中轉譯指定控制項部分和狀態的文字,或目前在裝置內容中選取的文字, (DC) 。
  5. 當您的控制項收到 WM_DESTROY 訊息時,請呼叫 CloseThemeData 以釋放您呼叫 OpenThemeData時所傳回的主題控制碼。

下列範例程式碼示範在目前視覺化樣式中繪製按鈕控制項的一種方式。

HTHEME hTheme = NULL;

hTheme = OpenThemeData(hwndButton, L"Button");
// ...
DrawMyControl(hDC, hwndButton, hTheme, iState);
// ...
if (hTheme)
{
    CloseThemeData(hTheme);
}


void DrawMyControl(HDC hDC, HWND hwndButton, HTHEME hTheme, int iState)
{
    RECT rc, rcContent;
    TCHAR szButtonText[255];
    HRESULT hr;
    size_t cch;

    GetWindowRect(hwndButton, &rc);
    GetWindowText(hwndButton, szButtonText,
                  (sizeof(szButtonText) / sizeof(szButtonText[0])+1));
    hr = StringCchLength(szButtonText,
         (sizeof(szButtonText) / sizeof(szButtonText[0])), &cch);
    if (hTheme)
    {
        hr = DrawThemeBackground(hTheme, hDC, BP_PUSHBUTTON, iState, &rc, 0);
        if (SUCCEEDED(hr))
        {
            hr = GetThemeBackgroundContentRect(hTheme, hDC, BP_PUSHBUTTON, 
                    iState, &rc, &rcContent);
        }

        if (SUCCEEDED(hr))
        {
            hr = DrawThemeText(hTheme, hDC, BP_PUSHBUTTON, iState, 
                    szButtonText, cch,
                    DT_CENTER | DT_VCENTER | DT_SINGLELINE,
                    0, &rcContent);
        }

    }
    else
    {
        // Draw the control without using visual styles.
    }
}

下列範例程式碼位於子類別化按鈕控制項 的WM_PAINT 訊息處理常式中。 控制項的文字是以視覺化樣式字型繪製,但色彩會根據控制項的狀態來定義。

// textColor is a COLORREF whose value has been set according to whether the button is "hot".
// paint is the PAINTSTRUCT whose members are filled in by BeginPaint.
HTHEME theme = OpenThemeData(hWnd, L"button");
if (theme)
{
    DTTOPTS opts = { 0 };
    opts.dwSize = sizeof(opts);
    opts.crText = textColor;
    opts.dwFlags |= DTT_TEXTCOLOR;
    WCHAR caption[255];
    size_t cch;
    GetWindowText(hWnd, caption, 255);
    StringCchLength(caption, 255, &cch);
    DrawThemeTextEx(theme, paint.hdc, BP_PUSHBUTTON, CBS_UNCHECKEDNORMAL, 
        caption, cch, DT_CENTER | DT_VCENTER | DT_SINGLELINE, 
        &paint.rcPaint, &opts);
    CloseThemeData(theme);
}
else
{
    // Draw the control without using visual styles.
}

您可以使用其他控制項的元件,並個別轉譯每個元件。 例如,對於包含方格的行事曆控制項,您可以藉由取得主題控制碼,將方格形成的每個方塊視為工具列按鈕,如下所示:

OpenThemeData(hwnd, L"Toolbar");

您可以為指定的控制項呼叫 OpenThemeData 多次,並使用適當的主題控制碼來繪製不同的元件,以混合和比對控制群組件。 不過,在某些視覺化樣式中,某些部分可能無法與其他元件相容。

使用中視覺化樣式轉譯控制項的另一種方法是使用系統色彩。 例如,您可以在呼叫 DrawThemeTextEx 函式時,使用系統色彩來設定文字色彩。 套用視覺樣式檔案時,會設定大部分的系統色彩。

回應主題變更

當您的控制項收到 WM_THEMECHANGED 訊息並保存主題的全域控制碼時,應該執行下列動作:

  • 呼叫 CloseThemeData 以關閉現有的主題控制碼。
  • 呼叫 OpenThemeData 以取得新載入視覺效果樣式的主題控制碼。

下列範例說明這兩個呼叫。

case WM_THEMECHANGED:
     CloseThemeData (g_hTheme);
     g_hTheme = OpenThemeData (hwnd, L"MyClassName");

啟用視覺化樣式

視覺化樣式