Menggunakan Gaya Visual dengan Kontrol Kustom dan Digambar Pemilik

Topik ini menjelaskan cara menggunakan API gaya visual untuk menerapkan gaya visual ke kontrol kustom atau kontrol yang digambar pemilik.

Kontrol Gambar dengan Gaya Visual

Gaya visual didukung oleh ComCtrl32.dll versi 6 dan yang lebih baru. Jika aplikasi Anda dikonfigurasi untuk menggunakan ComCtrl32.dll versi 6 dan yang lebih baru, dan jika versi tersebut tersedia pada sistem, gaya visual saat ini secara otomatis diterapkan ke semua kontrol umum di aplikasi Anda. Namun, gaya visual saat ini tidak diterapkan secara otomatis ke kontrol kustom atau kontrol yang digambar pemilik. Aplikasi Anda harus menyertakan kode yang memeriksa apakah gaya visual tersedia dan, jika demikian, menggunakan API gaya visual untuk menerapkan gaya visual yang saat ini dipilih ke kontrol kustom dan digambar pemilik Anda.

Untuk memeriksa apakah gaya visual tersedia, panggil fungsi IsAppThemed. Jika gaya visual tidak tersedia, gunakan kode fallback untuk menggambar kontrol.

Jika gaya visual tersedia, Anda dapat menggunakan fungsi gaya visual seperti DrawThemeText untuk merender kontrol Anda. Perhatikan bahwa DrawThemeTextEx memungkinkan Anda menyesuaikan tampilan teks, mempertahankan beberapa properti font tema sambil memodifikasi yang lain.

Untuk menggambar kontrol dalam gaya visual saat ini

  1. Panggil OpenThemeData, melewati hwnd kontrol yang ingin Anda terapkan gaya visualnya dan daftar kelas yang menjelaskan jenis kontrol. Kelas didefinisikan dalam Vssym32.h. OpenThemeData mengembalikan handel HTHEME, tetapi jika manajer gaya visual dinonaktifkan atau gaya visual saat ini tidak menyediakan informasi tertentu untuk kontrol tertentu, fungsi mengembalikan NULL. Jika nilai yang dikembalikan adalah NULL, gunakan fungsi gambar gaya non-visual.
  2. Untuk menggambar latar belakang kontrol, panggil DrawThemeBackground atau DrawThemeBackgroundEx.
  3. Untuk menentukan lokasi persegi panjang konten, panggil GetThemeBackgroundContentRect.
  4. Untuk merender teks, gunakan DrawThemeText atau DrawThemeTextEx, dengan mendasarkan koordinat pada persegi yang dikembalikan oleh GetThemeBackgroundContentRect. Fungsi-fungsi ini dapat merender teks baik di font tema untuk bagian kontrol dan status tertentu, atau dalam font yang saat ini dipilih ke dalam konteks perangkat (DC).
  5. Saat kontrol Anda menerima pesan WM_DESTROY, panggil CloseThemeData untuk merilis handel tema yang dikembalikan saat Anda memanggil OpenThemeData.

Contoh kode berikut menunjukkan salah satu cara untuk menggambar kontrol tombol dalam gaya visual saat ini.

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

Contoh kode berikut ada di handler pesan WM_PAINT untuk kontrol tombol subkelas. Teks untuk kontrol digambar dalam font gaya visual, tetapi warnanya ditentukan aplikasi tergantung pada status kontrol.

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

Anda dapat menggunakan bagian dari kontrol lain dan merender setiap bagian secara terpisah. Misalnya, untuk kontrol kalender yang terdiri dari kisi, Anda dapat memperlakukan setiap persegi yang dibentuk oleh kisi sebagai tombol toolbar, dengan mendapatkan handel tema sebagai berikut:

OpenThemeData(hwnd, L"Toolbar");

Anda dapat mencampur dan mencocokkan bagian kontrol dengan memanggil OpenThemeData beberapa kali untuk kontrol tertentu dan menggunakan handel tema yang sesuai untuk menggambar bagian yang berbeda. Namun, dalam beberapa gaya visual, bagian tertentu mungkin tidak kompatibel dengan bagian lain.

Pendekatan lain untuk merender kontrol dalam gaya visual aktif adalah menggunakan warna sistem. Misalnya, Anda dapat menggunakan warna sistem untuk mengatur warna teks saat memanggil fungsi DrawThemeTextEx. Sebagian besar warna sistem diatur ketika file gaya visual diterapkan.

Menanggapi Perubahan Tema

Saat kontrol Anda menerima pesan WM_THEMECHANGED dan memegang handel global ke tema, kontrol harus melakukan hal berikut:

  • Panggil CloseThemeData untuk menutup handel tema yang ada.
  • Panggil OpenThemeData untuk mendapatkan handel tema ke gaya visual yang baru dimuat.

Contoh berikut mengilustrasikan dua panggilan.

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

Mengaktifkan Gaya Visual

Gaya Visual