Didacticiel : Prise en main avec DirectWrite
ce document vous montre comment utiliser DirectWrite et Direct2D pour créer du texte simple qui contient un format unique, puis du texte qui contient plusieurs formats.
Ce didacticiel contient les éléments suivants :
- Code source
- Dessiner du texte simple
- partie 1 : déclarer des ressources DirectWrite et Direct2D.
- Partie 2 : créer des ressources indépendantes de l’appareil.
- Partie 3 : créer des ressources Device-Dependent.
- Partie 4 : dessiner du texte à l’aide de la méthode DrawText de Direct2D.
- Partie 5 : rendu du contenu de la fenêtre à l’aide de Direct2D
- Dessin de texte avec plusieurs formats.
Code source
le code source présenté dans cette vue d’ensemble est tiré de l' exemple DirectWrite Hello World. Chaque partie est implémentée dans une classe distincte (SimpleText et MultiformattedText) et s’affiche dans une fenêtre enfant distincte. Chaque classe représente une fenêtre Microsoft Win32. En plus de la méthode WndProc , chaque classe contient les méthodes suivantes :
| Fonction | Description |
|---|---|
| CreateDeviceIndependentResources | Crée des ressources indépendantes des appareils, afin qu’elles puissent être réutilisées n’importe où. |
| DiscardDeviceIndependentResources | Libère les ressources indépendantes du périphérique une fois qu’elles ne sont plus nécessaires. |
| CreateDeviceResources | Crée des ressources, telles que des pinceaux et des cibles de rendu, qui sont liées à un appareil particulier. |
| DiscardDeviceResources | Libère les ressources dépendantes de l’appareil une fois qu’elles ne sont plus nécessaires. |
| DrawD2DContent | Utilise Direct2D pour effectuer le rendu à l’écran. |
| DrawText | Dessine la chaîne de texte à l’aide de Direct2D. |
| OnResize | Redimensionne la cible de rendu Direct2D lorsque la taille de la fenêtre est modifiée. |
vous pouvez utiliser l’exemple fourni ou suivre les instructions qui suivent pour ajouter DirectWrite et Direct2D à votre propre application Win32. Pour plus d’informations sur l’exemple et les fichiers projet associés, consultez l' exemple DirectWriteHelloWorld.
Dessiner du texte simple
cette section montre comment utiliser DirectWrite et Direct2D pour afficher du texte simple avec un format unique, comme illustré dans la capture d’écran suivante.

Le fait de dessiner du texte simple à l’écran nécessite quatre composants :
- Chaîne de caractères à afficher.
- Une instance de IDWriteTextFormat.
- Dimensions de la zone devant contenir le texte.
- Objet qui peut restituer le texte. Dans ce didacticiel. vous utilisez une cible de rendu Direct2D .
L’interface IDWriteTextFormat décrit le nom, la taille, le poids, le style et l’étirement de la famille de polices utilisés pour mettre en forme le texte, et il décrit les informations relatives aux paramètres régionaux. IDWriteTextFormat définit également des méthodes pour définir et obtenir les propriétés suivantes :
- Interligne.
- Alignement du texte par rapport aux bords gauche et droit de la zone de disposition.
- Alignement du paragraphe par rapport au haut et au bas de la zone de disposition.
- Sens de lecture.
- Granularité de la suppression de texte pour le texte qui dépasse la zone de disposition.
- Taquet de tabulation incrémentiel.
- Sens du déroulement du paragraphe.
L’interface IDWriteTextFormat est requise pour dessiner du texte qui utilise les deux processus décrits dans ce document.
avant de pouvoir créer un objet IDWriteTextFormat ou tout autre objet DirectWrite , vous avez besoin d’une instance IDWriteFactory . vous utilisez un IDWriteFactory pour créer des instances IDWriteTextFormat et d’autres objets DirectWrite. Pour obtenir une instance de fabrique, utilisez la fonction DWriteCreateFactory .
partie 1 : déclarer des ressources DirectWrite et Direct2D.
Dans cette partie, vous déclarez les objets que vous utiliserez ultérieurement pour créer et afficher du texte sous la forme de membres de données privés de votre classe. toutes les interfaces, fonctions et types de données pour DirectWrite sont déclarés dans le fichier d’en-tête dwrite. h , et ceux de Direct2D sont déclarés dans d2d1. h. Si vous ne l’avez pas encore fait, incluez ces en-têtes dans votre projet.
Dans votre fichier d’en-tête de classe (SimpleText. h), déclarez des pointeurs vers des interfaces IDWriteFactory et IDWriteTextFormat en tant que membres privés.
IDWriteFactory* pDWriteFactory_; IDWriteTextFormat* pTextFormat_;Déclarez les membres pour contenir la chaîne de texte à restituer et la longueur de la chaîne.
const wchar_t* wszText_; UINT32 cTextLength_;Déclarez des pointeurs vers des interfaces ID2D1Factory, ID2D1HwndRenderTargetet ID2D1SolidColorBrush pour le rendu du texte avec Direct2D.
ID2D1Factory* pD2DFactory_; ID2D1HwndRenderTarget* pRT_; ID2D1SolidColorBrush* pBlackBrush_;
Partie 2 : créer des ressources indépendantes de l’appareil.
Direct2D fournit deux types de ressources : les ressources dépendantes de l’appareil et les ressources indépendantes du périphérique. Les ressources dépendantes de l’appareil sont associées à un périphérique de rendu et ne fonctionnent plus si l’appareil est supprimé. Les ressources indépendantes du périphérique, en revanche, peuvent être utilisées en dernier pour l’étendue de votre application.
les ressources de DirectWrite sont indépendantes des appareils.
Dans cette section, vous allez créer les ressources indépendantes du périphérique qui sont utilisées par votre application. Ces ressources doivent être libérées à l’aide d’un appel à la méthode Release de l’interface.
Certaines des ressources utilisées ne doivent être créées qu’une seule fois et ne sont pas liées à un appareil. L’initialisation de ces ressources est placée dans la méthode SimpleText :: CreateDeviceIndependentResources , qui est appelée lors de l’initialisation de la classe.
À l’intérieur de la méthode SimpleText :: CreateDeviceIndependentResources dans le fichier d’implémentation de classe (SimpleText. cpp), appelez la fonction D2D1CreateFactory pour créer une interface ID2D1Factory , qui est l’interface de fabrique racine pour tous les objets Direct2D . Vous utilisez la même fabrique pour instancier d’autres ressources Direct2D.
hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory_ );appelez la fonction DWriteCreateFactory pour créer une interface IDWriteFactory , qui est l’interface de fabrique racine pour tous les objets DirectWrite . vous utilisez la même fabrique pour instancier d’autres ressources de DirectWrite.
if (SUCCEEDED(hr)) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pDWriteFactory_) ); }Initialisez la chaîne de texte et stockez sa longueur.
wszText_ = L"Hello World using DirectWrite!"; cTextLength_ = (UINT32) wcslen(wszText_);Créez un objet d’interface IDWriteTextFormat à l’aide de la méthode IDWriteFactory :: CreateTextFormat . Le IDWriteTextFormat spécifie la police, le poids, l’étirement, le style et les paramètres régionaux qui seront utilisés pour le rendu de la chaîne de texte.
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_ ); }Centrez le texte horizontalement et verticalement en appelant les méthodes IDWriteTextFormat :: SetTextAlignment et 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); }
Dans cette partie, vous avez initialisé les ressources indépendantes du périphérique qui sont utilisées par votre application. Dans la partie suivante, vous initialisez les ressources dépendantes de l’appareil.
Partie 3 : créer des ressources Device-Dependent.
Dans cette partie, vous créez un ID2D1HwndRenderTarget et un ID2D1SolidColorBrush pour le rendu de votre texte.
Une cible de rendu est un objet Direct2D qui crée des ressources de dessin et restitue des commandes de dessin sur un appareil de rendu. Un ID2D1HwndRenderTarget est une cible de rendu qui est restituée à un HWND.
L’une des ressources de dessin qu’une cible de rendu peut créer est un pinceau pour peindre des contours, des remplissages et du texte. Un ID2D1SolidColorBrush peint avec une couleur unie.
Les interfaces ID2D1HwndRenderTarget et ID2D1SolidColorBrush sont liées à un appareil de rendu lorsqu’elles sont créées et doivent être libérées et recréées si l’appareil n’est plus valide.
À l’intérieur de la méthode SimpleText :: CreateDeviceResources, vérifiez si le pointeur de la cible de rendu a la valeur null. Si c’est le cas, récupérez la taille de la zone de rendu et créez un ID2D1HwndRenderTarget de cette taille. Utilisez ID2D1HwndRenderTarget pour créer un 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_ ); } }Dans la méthode SimpleText ::D iscardDeviceResources, libérez à la fois le pinceau et la cible de rendu.
SafeRelease(&pRT_); SafeRelease(&pBlackBrush_);
Maintenant que vous avez créé une cible de rendu et un pinceau, vous pouvez les utiliser pour restituer votre texte.
Partie 4 : dessiner du texte à l’aide de la méthode DrawText de Direct2D.
Dans la méthode SimpleText ::D rawText de votre classe, définissez la zone pour la disposition du texte en extrayant les dimensions de la zone de rendu et créez un rectangle Direct2D qui a les mêmes dimensions.
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_ );Utilisez la méthode ID2D1RenderTarget ::D rawtext et l’objet IDWriteTextFormat pour afficher du texte à l’écran. La méthode ID2D1RenderTarget ::D rawtext accepte les paramètres suivants :
- Chaîne à restituer.
- Pointeur vers une interface IDWriteTextFormat .
- Rectangle de disposition Direct2D .
- Pointeur vers une interface qui expose ID2D1Brush.
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. );
Partie 5 : rendu du contenu de la fenêtre à l’aide de Direct2D
Pour afficher le contenu de la fenêtre à l’aide de Direct2D lors de la réception d’un message de peinture, procédez comme suit :
- Créez les ressources dépendantes de l’appareil en appelant la méthode SimpleText :: CreateDeviceResources implémentée dans la partie 3.
- Appelez la méthode ID2D1HwndRenderTarget :: BeginDraw de la cible de rendu.
- Effacez la cible de rendu en appelant la méthode ID2D1HwndRenderTarget :: Clear .
- Appelez la méthode SimpleText ::D rawText, implémentée dans la partie 4.
- Appelez la méthode ID2D1HwndRenderTarget :: EndDraw de la cible de rendu.
- Si nécessaire, ignorez les ressources dépendantes de l’appareil afin qu’elles puissent être recréées lorsque la fenêtre est redessinée.
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();
}
La classe SimpleText est implémentée dans SimpleText. h et SimpleText. cpp.
Dessin de texte avec plusieurs formats.
cette section montre comment utiliser DirectWrite et Direct2D pour restituer du texte avec plusieurs formats, comme illustré dans la capture d’écran suivante.

Le code de cette section est implémenté en tant que classe MultiformattedText dans l' exemple DWriteHelloWorld. Elle est basée sur les étapes de la section précédente.
Pour créer du texte à plusieurs mises en forme, vous utilisez l’interface IDWriteTextLayout en plus de l’interface IDWriteTextFormat introduite dans la section précédente. L’interface IDWriteTextLayout décrit la mise en forme et la mise en page d’un bloc de texte. En plus de la mise en forme par défaut spécifiée par un objet IDWriteTextFormat , la mise en forme de plages de texte spécifiques peut être modifiée à l’aide de IDWriteTextLayout. Cela comprend le nom de famille de polices, la taille, le poids, le style, l’étirement, le barré et le soulignement.
IDWriteTextLayout fournit également des méthodes de test de positionnement. Les métriques de test de positionnement retournées par ces méthodes sont relatives à la zone de disposition spécifiée lors de la création de l’objet d’interface IDWriteTextLayout à l’aide de la méthode CreateTextLayout de l’interface IDWriteFactory .
L’interface IDWriteTypography est utilisée pour ajouter des fonctionnalités typographiques OpenType facultatives à une disposition de texte, telles que des lettres ornées et des ensembles de texte stylistiques alternatifs. Les fonctionnalités typographiques peuvent être ajoutées à une plage de texte spécifique dans une disposition de texte en appelant la méthode AddFontFeature de l’interface IDWriteTypography . Cette méthode reçoit une structure de _ _ fonctionnalité de police DWRITE en tant que paramètre qui contient une constante d’énumération de _ _ _ balise de fonctionnalité de police DWRITE et un paramètre d’exécution UInt32 . Vous trouverez une liste des fonctionnalités OpenType inscrites dans le Registre de balises de disposition OpenType sur Microsoft.com. pour obtenir les DirectWrite équivalentes des constantes d’énumération, consultez _ _ _ balise de fonctionnalité de police DWRITE.
Partie 1 : créer une interface IDWriteTextLayout.
Déclarez un pointeur vers une interface IDWriteTextLayout en tant que membre de la classe MultiformattedText.
IDWriteTextLayout* pTextLayout_;À la fin de la méthode MultiformattedText :: CreateDeviceIndependentResources, créez un objet d’interface IDWriteTextLayout en appelant la méthode CreateTextLayout . L’interface IDWriteTextLayout fournit des fonctionnalités de mise en forme supplémentaires, telles que la possibilité d’appliquer des formats différents aux portions de texte sélectionnées.
// 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. ); }
Partie 2 : application de la mise en forme avec IDWriteTextLayout.
La mise en forme, telle que la taille de la police, le poids et le soulignement, peut être appliquée aux sous-chaînes du texte à afficher à l’aide de l’interface IDWriteTextLayout .
définissez la taille de police de la sous-chaîne « Di » de « DirectWrite » sur 100 en déclarant une _ _ plage de texte DWRITE et en appelant la méthode 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); }soulignez la sous-chaîne « DirectWrite » en appelant la méthode 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); }affectez la valeur gras à l’épaisseur de la police pour la sous-chaîne « DirectWrite » en appelant la méthode 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); }
Partie 3 : ajout de fonctionnalités typographiques avec IDWriteTypography.
Déclarez et créez un objet d’interface IDWriteTypography en appelant la méthode IDWriteFactory :: CreateTypography .
// Declare a typography pointer. IDWriteTypography* pTypography = NULL; // Create a typography interface object. if (SUCCEEDED(hr)) { hr = pDWriteFactory_->CreateTypography(&pTypography); }Ajoutez une fonctionnalité de police en déclarant un objet de _ _ fonctionnalité de police DWRITE dont le jeu stylistique 7 est spécifié et en appelant la méthode 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); }Définissez la disposition du texte pour utiliser la typographie sur l’ensemble de la chaîne en déclarant une variable de _ _ portée de texte DWRITE et en appelant la méthode IDWriteTextLayout :: SetTypography et en passant dans la plage de texte.
if (SUCCEEDED(hr)) { // Set the typography for the entire string. DWRITE_TEXT_RANGE textRange = {0, cTextLength_}; hr = pTextLayout_->SetTypography(pTypography, textRange); }Définissez la nouvelle largeur et la hauteur de l’objet de disposition du texte dans la méthode MultiformattedText :: OnResize.
if (pTextLayout_) { pTextLayout_->SetMaxWidth(static_cast<FLOAT>(width / dpiScaleX_)); pTextLayout_->SetMaxHeight(static_cast<FLOAT>(height / dpiScaleY_)); }
Partie 4 : dessiner du texte à l’aide de la méthode Direct2D DrawTextLayout.
Pour dessiner le texte avec les paramètres de disposition du texte spécifiés par l’objet IDWriteTextLayout , modifiez le code de la méthode MultiformattedText ::D rawtext de sorte qu’il utilise IDWriteTextLayout ::D rawtextlayout.
Delcare une variable d2d1 _ point _ 2F et définissez-la sur le point supérieur gauche de la fenêtre.
D2D1_POINT_2F origin = D2D1::Point2F( static_cast<FLOAT>(rc.left / dpiScaleX_), static_cast<FLOAT>(rc.top / dpiScaleY_) );Dessinez le texte à l’écran en appelant la méthode ID2D1RenderTarget ::D rawtextlayout de la cible de rendu Direct2D et en passant le pointeur IDWriteTextLayout .
pRT_->DrawTextLayout( origin, pTextLayout_, pBlackBrush_ );
La classe MultiformattedText est implémentée dans MultiformattedText. h et MultiformattedText. cpp.