Verwenden von visuellen Formatvorlagen mit benutzerdefinierten und Owner-Drawn Steuerelementen

In diesem Thema wird beschrieben, wie Sie die API für visuelle Stile verwenden, um visuelle Stile auf benutzerdefinierte Steuerelemente oder von Besitzern gezeichnete Steuerelemente anzuwenden.

Zeichnen von Steuerelementen mit visuellen Formatvorlagen

Visuelle Stile werden von ComCtrl32.dll Version 6 und höher unterstützt. Wenn Ihre Anwendung für die Verwendung ComCtrl32.dll Version 6 und höher konfiguriert ist und diese Version auf dem System verfügbar ist, werden die aktuellen visuellen Stile automatisch auf alle gängigen Steuerelemente in Ihrer Anwendung angewendet. Die aktuellen visuellen Stile werden jedoch nicht automatisch auf benutzerdefinierte Steuerelemente oder von Besitzern gezeichnete Steuerelemente angewendet. Ihre Anwendung muss Code enthalten, der überprüft, ob visuelle Stile verfügbar sind, und, wenn ja, die API für visuelle Stile verwendet, um die derzeit ausgewählten visuellen Stile auf Ihre benutzerdefinierten und vom Besitzer gezeichneten Steuerelemente anzuwenden.

Um zu überprüfen, ob visuelle Stile verfügbar sind, rufen Sie die IsAppThemed-Funktion auf. Wenn keine visuellen Stile verfügbar sind, verwenden Sie Fallbackcode, um das Steuerelement zu zeichnen.

Wenn visuelle Stile verfügbar sind, können Sie visuelle Stilfunktionen wie DrawThemeText verwenden, um Ihr Steuerelement zu rendern. Beachten Sie, dass Sie mit DrawThemeTextEx die Darstellung von Text anpassen können, wobei einige Eigenschaften der Designschriftart beibehalten und andere geändert werden.

So zeichnen Sie ein Steuerelement im aktuellen visuellen Stil

  1. Rufen Sie OpenThemeData auf, und übergeben Sie den hwnd des Steuerelements, auf das Sie visuelle Stile anwenden möchten, und eine Klassenliste, die den Typ des Steuerelements beschreibt. Die Klassen sind in Vssym32.h definiert. OpenThemeData gibt ein HTHEME-Handle zurück, aber wenn der Manager für visuelle Stile deaktiviert ist oder der aktuelle visuelle Stil keine spezifischen Informationen für ein bestimmtes Steuerelement liefert, gibt die Funktion NULL zurück. Wenn der Rückgabewert NULL ist, verwenden Sie Zeichnungsfunktionen für nicht visuelle Stile.
  2. Um den Hintergrund des Steuerelements zu zeichnen, rufen Sie DrawThemeBackground oder DrawThemeBackgroundEx auf.
  3. Um den Speicherort des Inhaltsrechtecks zu bestimmen, rufen Sie GetThemeBackgroundContentRect auf.
  4. Verwenden Sie zum Rendern von Text entweder DrawThemeText oderDrawThemeTextEx, wobei die Koordinaten auf dem von GetThemeBackgroundContentRect zurückgegebenen Rechteck basiert. Diese Funktionen können Text entweder in der Schriftart des Designs für einen angegebenen Steuerelementteil und -zustand oder in der Schriftart rendern, die derzeit im Gerätekontext (DC) ausgewählt ist.
  5. Wenn Ihr Steuerelement eine WM_DESTROY-Nachricht empfängt, rufen Sie CloseThemeData auf, um das Designhandle freizugeben, das beim Aufrufen von OpenThemeData zurückgegeben wurde.

Der folgende Beispielcode veranschaulicht eine Möglichkeit, ein Schaltflächensteuerelement im aktuellen visuellen Stil zu zeichnen.

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.
    }
}

Der folgende Beispielcode befindet sich im WM_PAINT Nachrichtenhandler für ein unterklassiges Schaltflächensteuerelement. Der Text für das Steuerelement wird in der Schriftart für visuelle Stile gezeichnet, die Farbe ist jedoch je nach Zustand des Steuerelements anwendungsdefiniert.

// 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.
}

Sie können Teile aus anderen Steuerelementen verwenden und jedes Teil separat rendern. Für ein Kalendersteuerelement, das aus einem Raster besteht, können Sie z. B. jedes durch das Raster gebildete Quadrat als Symbolleistenschaltfläche behandeln, indem Sie das Designhandle wie folgt abrufen:

OpenThemeData(hwnd, L"Toolbar");

Sie können Steuerelementteile mischen und abgleichen, indem Sie OpenThemeData mehrmals für ein bestimmtes Steuerelement aufrufen und den entsprechenden Designhandle verwenden, um verschiedene Teile zu zeichnen. In einigen visuellen Stilen sind bestimmte Teile jedoch möglicherweise nicht mit anderen Teilen kompatibel.

Ein weiterer Ansatz zum Rendern von Steuerelementen im aktiven visuellen Stil besteht darin, die Systemfarben zu verwenden. Sie können beispielsweise Systemfarben verwenden, um die Textfarbe festzulegen, wenn Sie die DrawThemeTextEx-Funktion aufrufen. Die meisten Systemfarben werden festgelegt, wenn eine visuelle Formatdatei angewendet wird.

Reagieren auf Designänderungen

Wenn Ihr Steuerelement eine WM_THEMECHANGED Nachricht empfängt und ein globales Handle für das Design enthält, sollte es die folgenden Schritte ausführen:

  • Rufen Sie CloseThemeData auf, um das vorhandene Designhandle zu schließen.
  • Rufen Sie OpenThemeData auf, um das Designhandle für den neu geladenen visuellen Stil zu erhalten.

Das folgende Beispiel veranschaulicht die beiden Aufrufe.

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

Aktivieren von visuellen Stilen

Visuelle Stile