Bagikan melalui


Tutorial: Memulai DirectWrite

Dokumen ini memperlihatkan kepada Anda cara menggunakan DirectWrite dan Direct2D untuk membuat teks sederhana yang berisi satu format, lalu teks yang berisi beberapa format.

Tutorial ini berisi bagian-bagian berikut:

Kode Sumber

Kode sumber yang ditunjukkan dalam gambaran umum ini diambil dari sampel DirectWrite Halo Dunia. Setiap bagian diimplementasikan dalam kelas terpisah (SimpleText dan MultiformattedText) dan ditampilkan di jendela anak terpisah. Setiap kelas mewakili jendela Microsoft Win32. Selain metode WndProc , setiap kelas berisi metode berikut:

Fungsi Deskripsi
CreateDeviceIndependentResources Membuat sumber daya yang independen untuk perangkat, sehingga dapat digunakan kembali di mana saja.
DiscardDeviceIndependentResources Merilis sumber daya independen perangkat setelah tidak lagi diperlukan.
CreateDeviceResources Membuat sumber daya, seperti kuas dan merender target, yang terkait dengan perangkat tertentu.
BuangDeviceResources Merilis sumber daya yang bergantung pada perangkat setelah tidak lagi diperlukan.
DrawD2DContent Menggunakan Direct2D untuk merender ke layar.
DrawText Menggambar string teks dengan menggunakan Direct2D.
OnResize Mengubah ukuran target render Direct2D saat ukuran jendela diubah.

 

Anda dapat menggunakan sampel yang disediakan, atau menggunakan instruksi berikut untuk menambahkan DirectWrite dan Direct2D ke aplikasi Win32 Anda sendiri. Untuk informasi selengkapnya tentang sampel dan file proyek terkait, lihat DirectWrite HelloWorld.

Menggambar Teks Sederhana

Bagian ini memperlihatkan cara menggunakan DirectWrite dan Direct2D untuk merender teks sederhana yang memiliki satu format, seperti yang ditunjukkan pada cuplikan layar berikut.

cuplikan layar

Menggambar teks sederhana ke layar memerlukan empat komponen:

  • String karakter yang akan dirender.
  • Instans IDWriteTextFormat.
  • Dimensi area untuk memuat teks.
  • Objek yang dapat merender teks. Dalam tutorial ini. Anda menggunakan target render Direct2D .

Antarmuka IDWriteTextFormat menjelaskan nama, ukuran, berat, gaya, dan peregangan font-keluarga yang digunakan untuk memformat teks, dan menjelaskan informasi lokal. IDWriteTextFormat juga mendefinisikan metode untuk mengatur dan mendapatkan properti berikut:

  • Penspasian baris.
  • Perataan teks relatif terhadap tepi kiri dan kanan kotak tata letak.
  • Perataan paragraf relatif terhadap bagian atas dan bawah kotak tata letak.
  • Arah membaca.
  • Granularitas pemangkasan teks untuk teks yang melebihi kotak tata letak.
  • Pemberhentian tab inkremental.
  • Arah alur paragraf.

Antarmuka IDWriteTextFormat diperlukan untuk menggambar teks yang menggunakan kedua proses yang dijelaskan dalam dokumen ini .

Sebelum Anda dapat membuat objek IDWriteTextFormat, atau objek DirectWrite lainnya, Anda memerlukan instans IDWriteFactory. Anda menggunakan IDWriteFactory untuk membuat instans IDWriteTextFormat dan objek DirectWrite lainnya. Untuk mendapatkan instans pabrik, gunakan fungsi DWriteCreateFactory .

Bagian 1: Nyatakan sumber daya DirectWrite dan Direct2D.

Di bagian ini, Anda mendeklarasikan objek yang akan Anda gunakan nanti untuk membuat dan menampilkan teks sebagai anggota data privat kelas Anda. Semua antarmuka, fungsi, dan jenis data untuk DirectWrite dideklarasikan dalam file header dwrite.h, dan yang untuk Direct2D dideklarasikan dalam d2d1.h; jika Anda belum melakukan ini, sertakan header ini dalam proyek Anda.

  1. Di file header kelas Anda (SimpleText.h), deklarasikan pointer ke antarmuka IDWriteFactory dan IDWriteTextFormat sebagai anggota privat.

    IDWriteFactory* pDWriteFactory_;
    IDWriteTextFormat* pTextFormat_;
    
    
  2. Nyatakan anggota untuk menahan string teks untuk dirender dan panjang string.

    const wchar_t* wszText_;
    UINT32 cTextLength_;
    
    
  3. Deklarasikan pointer ke antarmuka ID2D1Factory, ID2D1HwndRenderTarget, dan ID2D1SolidColorBrush untuk merender teks dengan Direct2D.

    ID2D1Factory* pD2DFactory_;
    ID2D1HwndRenderTarget* pRT_;
    ID2D1SolidColorBrush* pBlackBrush_;
    
    

Bagian 2: Buat sumber daya independen perangkat.

Direct2D menyediakan dua jenis sumber daya: sumber daya yang bergantung pada perangkat dan sumber daya independen perangkat. Sumber daya yang bergantung pada perangkat dikaitkan dengan perangkat penyajian dan tidak lagi berfungsi jika perangkat tersebut dihapus. Sumber daya independen perangkat, di sisi lain, dapat bertahan untuk cakupan aplikasi Anda.

DirectWrite sumber daya independen perangkat.

Di bagian ini, Anda membuat sumber daya independen perangkat yang digunakan oleh aplikasi Anda. Sumber daya ini harus dibebaskan dengan panggilan ke metode Rilis antarmuka.

Beberapa sumber daya yang digunakan hanya harus dibuat satu kali dan tidak terikat dengan perangkat. Inisialisasi untuk sumber daya ini dimasukkan ke dalam metode SimpleText::CreateDeviceIndependentResources , yang dipanggil saat menginisialisasi kelas.

  1. Di dalam metode SimpleText::CreateDeviceIndependentResources dalam file implementasi kelas (SimpleText.cpp), panggil fungsi D2D1CreateFactory untuk membuat antarmuka ID2D1Factory , yang merupakan antarmuka pabrik akar untuk semua objek Direct2D . Anda menggunakan pabrik yang sama untuk membuat instans sumber daya Direct2D lainnya.

    hr = D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        &pD2DFactory_
        );
    
    
  2. Panggil fungsi DWriteCreateFactory untuk membuat antarmuka IDWriteFactory, yang merupakan antarmuka pabrik akar untuk semua objek DirectWrite. Anda menggunakan pabrik yang sama untuk membuat instans sumber daya DirectWrite lainnya.

    if (SUCCEEDED(hr))
    {
        hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(IDWriteFactory),
            reinterpret_cast<IUnknown**>(&pDWriteFactory_)
            );
    }
    
    
  3. Inisialisasi string teks dan simpan panjangnya.

    wszText_ = L"Hello World using  DirectWrite!";
    cTextLength_ = (UINT32) wcslen(wszText_);
    
    
  4. Buat objek antarmuka IDWriteTextFormat dengan menggunakan metode IDWriteFactory::CreateTextFormat . IDWriteTextFormat menentukan font, bobot, rentang, gaya, dan lokal yang akan digunakan untuk merender string teks.

    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory_->CreateTextFormat(
            L"Gabriola",                // Font family name.
            NULL,                       // Font collection (NULL sets it to use the system font collection).
            DWRITE_FONT_WEIGHT_REGULAR,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            72.0f,
            L"en-us",
            &pTextFormat_
            );
    }
    
    
  5. Tengahkan teks secara horizontal dan vertikal dengan memanggil metode IDWriteTextFormat::SetTextAlignment dan IDWriteTextFormat::SetParagraphAlignment .

    // Center align (horizontally) the text.
    if (SUCCEEDED(hr))
    {
        hr = pTextFormat_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
    }
    
    if (SUCCEEDED(hr))
    {
        hr = pTextFormat_->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
    }
    
    

Di bagian ini, Anda menginisialisasi sumber daya independen perangkat yang digunakan oleh aplikasi Anda. Di bagian berikutnya, Anda menginisialisasi sumber daya yang bergantung pada perangkat.

Bagian 3: Buat Sumber Daya Device-Dependent.

Di bagian ini, Anda membuat ID2D1HwndRenderTarget dan ID2D1SolidColorBrush untuk merender teks Anda.

Target render adalah objek Direct2D yang membuat sumber daya gambar dan merender perintah gambar ke perangkat penyajian. ID2D1HwndRenderTarget adalah target render yang dirender ke HWND.

Salah satu sumber daya gambar yang dapat dibuat target render adalah kuas untuk melukis kerangka, isian, dan teks. ID2D1SolidColorBrush melukis dengan warna solid.

Antarmuka ID2D1HwndRenderTarget dan ID2D1SolidColorBrush terikat ke perangkat penyajian saat dibuat dan harus dirilis dan dibuat ulang jika perangkat menjadi tidak valid.

  1. Di dalam metode SimpleText::CreateDeviceResources, periksa apakah penunjuk target render ADALAH NULL. Jika ya, ambil ukuran area render dan buat ID2D1HwndRenderTarget dengan ukuran tersebut. Gunakan ID2D1HwndRenderTarget untuk membuat ID2D1SolidColorBrush.

    RECT rc;
    GetClientRect(hwnd_, &rc);
    
    D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
    
    if (!pRT_)
    {
        // Create a Direct2D render target.
        hr = pD2DFactory_->CreateHwndRenderTarget(
                D2D1::RenderTargetProperties(),
                D2D1::HwndRenderTargetProperties(
                    hwnd_,
                    size
                    ),
                &pRT_
                );
    
        // Create a black brush.
        if (SUCCEEDED(hr))
        {
            hr = pRT_->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black),
                &pBlackBrush_
                );
        }
    }
    
    
  2. Dalam metode SimpleText::D iscardDeviceResources, lepaskan brush dan render target.

    SafeRelease(&pRT_);
    SafeRelease(&pBlackBrush_);
    
    

Sekarang setelah Anda membuat target render dan kuas, Anda dapat menggunakannya untuk merender teks Anda.

Bagian 4: Gambar Teks Dengan Menggunakan Metode DrawText Direct2D.

  1. Dalam metode SimpleText::D rawText kelas Anda, tentukan area untuk tata letak teks dengan mengambil dimensi area penyajian, dan buat persegi panjang Direct2D yang memiliki dimensi yang sama.

    D2D1_RECT_F layoutRect = D2D1::RectF(
        static_cast<FLOAT>(rc.left) / dpiScaleX_,
        static_cast<FLOAT>(rc.top) / dpiScaleY_,
        static_cast<FLOAT>(rc.right - rc.left) / dpiScaleX_,
        static_cast<FLOAT>(rc.bottom - rc.top) / dpiScaleY_
        );
    
    
  2. Gunakan metode ID2D1RenderTarget::D rawText dan objek IDWriteTextFormat untuk merender teks ke layar. Metode ID2D1RenderTarget::D rawText mengambil parameter berikut:

    pRT_->DrawText(
        wszText_,        // The string to render.
        cTextLength_,    // The string's length.
        pTextFormat_,    // The text format.
        layoutRect,       // The region of the window where the text will be rendered.
        pBlackBrush_     // The brush used to draw the text.
        );
    
    

Bagian 5: Merender Konten Jendela Menggunakan Direct2D

Untuk merender konten jendela dengan menggunakan Direct2D saat pesan cat diterima, lakukan hal berikut:

  1. Buat sumber daya dependen perangkat dengan memanggil metode SimpleText::CreateDeviceResources yang diterapkan di Bagian 3.
  2. Panggil metode ID2D1HwndRenderTarget::BeginDraw dari target render.
  3. Hapus target render dengan memanggil metode ID2D1HwndRenderTarget::Clear .
  4. Panggil metode SimpleText::D rawText, yang diimplementasikan di Bagian 4.
  5. Panggil metode ID2D1HwndRenderTarget::EndDraw dari target render.
  6. Jika perlu, buang sumber daya yang bergantung pada perangkat sehingga dapat dibuat ulang saat jendela digambar ulang.
hr = CreateDeviceResources();

if (SUCCEEDED(hr))
{
    pRT_->BeginDraw();

    pRT_->SetTransform(D2D1::IdentityMatrix());

    pRT_->Clear(D2D1::ColorF(D2D1::ColorF::White));

    // Call the DrawText method of this class.
    hr = DrawText();

    if (SUCCEEDED(hr))
    {
        hr = pRT_->EndDraw(
            );
    }
}

if (FAILED(hr))
{
    DiscardDeviceResources();
}

Kelas SimpleText diimplementasikan dalam SimpleText.h dan SimpleText.cpp.

Menggambar Teks dengan Beberapa Format.

Bagian ini memperlihatkan cara menggunakan DirectWrite dan Direct2D untuk merender teks dengan beberapa format, seperti yang ditunjukkan pada cuplikan layar berikut.

cuplikan layar

Kode untuk bagian ini diimplementasikan sebagai kelas MultiformattedText di DirectWrite HelloWorld. Ini didasarkan pada langkah-langkah dari bagian sebelumnya.

Untuk membuat teks multiformat, Anda menggunakan antarmuka IDWriteTextLayout selain antarmuka IDWriteTextFormat yang diperkenalkan di bagian sebelumnya. Antarmuka IDWriteTextLayout menjelaskan pemformatan dan tata letak blok teks. Selain pemformatan default yang ditentukan oleh objek IDWriteTextFormat , pemformatan untuk rentang teks tertentu dapat diubah dengan menggunakan IDWriteTextLayout. Ini termasuk nama keluarga font, ukuran, berat, gaya, peregangan, coretan, dan garis bawah.

IDWriteTextLayout juga menyediakan metode pengujian hit. Metrik pengujian klik yang dikembalikan oleh metode ini relatif terhadap kotak tata letak yang ditentukan ketika objek antarmuka IDWriteTextLayout dibuat dengan menggunakan metode CreateTextLayout dari antarmuka IDWriteFactory .

Antarmuka IDWriteTypography digunakan untuk menambahkan fitur tipografi OpenType opsional ke tata letak teks, seperti swash dan kumpulan teks gaya alternatif. Fitur tipografi dapat ditambahkan ke rentang teks tertentu dalam tata letak teks dengan memanggil metode AddFontFeature dari antarmuka IDWriteTypography . Metode ini menerima struktur DWRITE_FONT_FEATURE sebagai parameter yang berisi konstanta enumerasi DWRITE_FONT_FEATURE_TAG dan parameter eksekusi UINT32 . Daftar fitur OpenType terdaftar dapat ditemukan di OpenType Layout Tag Registry di microsoft.com. Untuk konstanta enumerasi DirectWrite yang setara, lihat DWRITE_FONT_FEATURE_TAG.

Bagian 1: Buat Antarmuka IDWriteTextLayout.

  1. Deklarasikan penunjuk ke antarmuka IDWriteTextLayout sebagai anggota kelas MultiformattedText.

    IDWriteTextLayout* pTextLayout_;
    
    
  2. Di akhir metode MultiformattedText::CreateDeviceIndependentResources, buat objek antarmuka IDWriteTextLayout dengan memanggil metode CreateTextLayout . Antarmuka IDWriteTextLayout menyediakan fitur pemformatan tambahan, seperti kemampuan untuk menerapkan format yang berbeda ke bagian teks yang dipilih.

    // Create a text layout using the text format.
    if (SUCCEEDED(hr))
    {
        RECT rect;
        GetClientRect(hwnd_, &rect); 
        float width  = rect.right  / dpiScaleX_;
        float height = rect.bottom / dpiScaleY_;
    
        hr = pDWriteFactory_->CreateTextLayout(
            wszText_,      // The string to be laid out and formatted.
            cTextLength_,  // The length of the string.
            pTextFormat_,  // The text format to apply to the string (contains font information, etc).
            width,         // The width of the layout box.
            height,        // The height of the layout box.
            &pTextLayout_  // The IDWriteTextLayout interface pointer.
            );
    }
    
    

Bagian 2: Menerapkan Pemformatan dengan IDWriteTextLayout.

Pemformatan, seperti ukuran font, bobot, dan garis bawah, dapat diterapkan ke substring teks yang akan ditampilkan dengan menggunakan antarmuka IDWriteTextLayout .

  1. Atur ukuran font untuk substring "Di" dari "DirectWrite" ke 100 dengan mendeklarasikan DWRITE_TEXT_RANGE dan memanggil metode IDWriteTextLayout::SetFontSize.

    // Format the "DirectWrite" substring to be of font size 100.
    if (SUCCEEDED(hr))
    {
        DWRITE_TEXT_RANGE textRange = {20,        // Start index where "DirectWrite" appears.
                                        6 };      // Length of the substring "Direct" in "DirectWrite".
        hr = pTextLayout_->SetFontSize(100.0f, textRange);
    }
    
  2. Garis bawahi substring "DirectWrite" dengan memanggil metode IDWriteTextLayout::SetUnderline.

    // Format the word "DWrite" to be underlined.
    if (SUCCEEDED(hr))
    {
    
        DWRITE_TEXT_RANGE textRange = {20,      // Start index where "DirectWrite" appears.
                                       11 };    // Length of the substring "DirectWrite".
        hr = pTextLayout_->SetUnderline(TRUE, textRange);
    }
    
  3. Atur bobot font ke tebal untuk substring "DirectWrite" dengan memanggil metode IDWriteTextLayout::SetFontWeight.

    if (SUCCEEDED(hr))
    {
        // Format the word "DWrite" to be bold.
        DWRITE_TEXT_RANGE textRange = {20,
                                       11 };
        hr = pTextLayout_->SetFontWeight(DWRITE_FONT_WEIGHT_BOLD, textRange);
    }
    

Bagian 3: Menambahkan Fitur Tipografi dengan IDWriteTypography.

  1. Deklarasikan dan buat objek antarmuka IDWriteTypography dengan memanggil metode IDWriteFactory::CreateTypography .

    // Declare a typography pointer.
    IDWriteTypography* pTypography = NULL;
    
    // Create a typography interface object.
    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory_->CreateTypography(&pTypography);
    }
    
    
  2. Tambahkan fitur font dengan mendeklarasikan objek DWRITE_FONT_FEATURE yang memiliki set gaya 7 yang ditentukan dan memanggil metode IDWriteTypography::AddFontFeature .

    // Set the stylistic set.
    DWRITE_FONT_FEATURE fontFeature = {DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_7,
                                       1};
    if (SUCCEEDED(hr))
    {
        hr = pTypography->AddFontFeature(fontFeature);
    }
    
    
  3. Atur tata letak teks untuk menggunakan tipografi di seluruh string dengan mendeklarasikan variabel DWRITE_TEXT_RANGE dan memanggil metode IDWriteTextLayout::SetTypography dan meneruskan dalam rentang teks.

    if (SUCCEEDED(hr))
    {
        // Set the typography for the entire string.
        DWRITE_TEXT_RANGE textRange = {0,
                                       cTextLength_};
        hr = pTextLayout_->SetTypography(pTypography, textRange);
    }
    
    
  4. Atur lebar dan tinggi baru untuk objek tata letak teks dalam metode MultiformattedText::OnResize.

    if (pTextLayout_)
    {
        pTextLayout_->SetMaxWidth(static_cast<FLOAT>(width / dpiScaleX_));
        pTextLayout_->SetMaxHeight(static_cast<FLOAT>(height / dpiScaleY_));
    }
    

Bagian 4: Gambar Teks Menggunakan Metode DrawTextLayout Direct2D.

Untuk menggambar teks dengan pengaturan tata letak teks yang ditentukan oleh objek IDWriteTextLayout , ubah kode dalam metode MultiformattedText::D rawText untuk menggunakan IDWriteTextLayout::D rawTextLayout.

  1. Delcare variabel D2D1_POINT_2F dan atur ke titik kiri atas jendela.

    D2D1_POINT_2F origin = D2D1::Point2F(
        static_cast<FLOAT>(rc.left / dpiScaleX_),
        static_cast<FLOAT>(rc.top / dpiScaleY_)
        );
    
    
  2. Gambar teks ke layar dengan memanggil metode ID2D1RenderTarget::D rawTextLayout dari target render Direct2D dan melewati pointer IDWriteTextLayout .

    pRT_->DrawTextLayout(
        origin,
        pTextLayout_,
        pBlackBrush_
        );
    
    

Kelas MultiformattedText diimplementasikan dalam MultiformattedText.h dan MultiformattedText.cpp.