Windows 7, introduction à Direct2D pour les développeurs C++

Par :
ericv
jeu, 12/11/2009 - 14:47
Niveau :
Facile

Direct2D est une API pour la création de graphiques 2D. Basée sur Direct3D 10, elle offre aux développeurs Win32, une API indépendante de la résolution, et qui utilise la puissance des cartes graphiques de nouvelle génération. Vous pouvez, avec Direct2D, améliorer vos applications GDI existantes, sans être obligé de les réécrire. En effet Direct2D a été conçu pour coopérer (Interopérabilité)  avec le GDI et d'autres technologies graphiques. Enfin, Direct2D vous permet d'écrire du contenu Direct2D sur une surface GDI.

Dans ce tutoriel, vous débuterez en utilisant les primitives de bases de Direct2D, et vous finirez, en modifiant une application qui met en corrélation le GDI et Direct2D.

Note:

Vous retrouverez les sources de ce tutoriel à l'adresse suivante :

http://cid-9607f0bf305f86d2.skydrive.live.com/browse.aspx/.Public/Programmez/Tutoriel%20Direct2D

Exercice 1: Dessiner un Rectangle avec Direct2D

Dans cet exercice, nous allons dessiner un simple rectangle vert, entouré par un rectangle Orange, WOW !!!

Informations :
Nous ciblons uniquement Windows 7. Vous noterez alors que dans le fichier d'entête targetver.h, nous somme passé à une version 0x0610 correspondant à Windows 7.
Tous les fichiers de cet exercice sont localisés dans le répertoire C:\Windows 7 Labs\06 - Graphiques\Direct2D\Exercice 1\Direct2DTutoriel\"
Pour utiliser les API Direct2D, il faut inclure dans le fichier D2D1.h et ajoutez la librairie D2D1.LIB

  1. Lancez Visual Studio, et ouvrez la solution C:\Windows 7 Labs\06 - Graphiques\Direct2D\Exercice 1\Direct2DTutoriel\Direct2DTutoriel.sln"
  2. Création de l'objet ID2D1Factory : Ouvrez le fichier Direct2DTutoriel.cpp et dans la méthode DessinerUnRectangle ajoutez-y le code suivant :
    HRESULT hr;
          CComPtr<ID2D1Factory> fabriqueD2D1;
          hr=D2D1CreateFactory (D2D1_FACTORY_TYPE_SINGLE_THREADED,
                                         &fabriqueD2D1);
          if (FAILED(hr)) return -1;        
          CComPtr<ID2D1HwndRenderTarget> contexteRenduD2D1;
         

    Une factory (une fabrique), est indépendant des ressources du périphérique. Une fois créée
    il faut alors instancier un contexte de rendu cible via la méthode CreateHwndRenderTarget de notre fabrique.

Création du contexte de rendu avec l'interface ID2D1HwndRenderTarget.
RECT rc;
GetClientRect(_hwndParent,&rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left,rc.bottom - rc.top);hr=fabriqueD2D1->CreateHwndRenderTarget (D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties (_hwndParent,size),
&contexteRenduD2D1);

La méthode CreateHwndRenderTarget, prend comme paramètre une structure D2D1_RENDER_TARGET_PROPERTIES obtenue à l'aide de la méthode Helper D2D1::RenderTargetProperties().

Cette structure contient les informations du type de rendu que Direct2D doit utiliser. C'est dans cette structure que l'on indique par exemple les formats supportés, la résolution en DPI, mais surtout si le rendu doit se faire à l'aide du CPU ou du GPU (Accélération matériel ou non). La méthode Helper initialise cette structure par défaut, laissant alors le moteur Direct2D choisir le meilleur rendu possible.

Le second paramètre, est la structure D2D1_HWND_RENDER_TARGET_PROPERTIES décrivant entre autre la taille initiale en pixel du contexte de rendu obtenu par l'appel de la méthode GetClientRect.

  1. Enfin le troisième paramètre correspond à un pointeur sur l'interface ID2D1HwndRenderTarget.

    Une fois que notre contexte de rendu est crée, nous allons alors créer les ressources quoi vont nous permettre de dessiner à l'écran. Nous utiliserons la méthode CreateSolidColorBrush de notre contexte de rendu, pour créer des brosses verte et orange.

  2. Création des brosses (Brush) verte et orange pour dessiner les rectangles
    CComPtr<ID2D1SolidColorBrush> brosseVerte;
    hr=contexteRenduD2D1->CreateSolidColorBrush (D2D1::ColorF(D2D1::ColorF::Green),
    &brosseVerte);
    //code omis pour plus de clarté
    CComPtr<ID2D1SolidColorBrush> brosseOrange;
    hr=contexteRenduD2D1->CreateSolidColorBrush (D2D1::ColorF(D2D1::ColorF::Orange),&brosseOrange);
    //Code omis pour plus de clarté

    Une fois nos brosses créées, nous allons pouvoir dessiner nos deux rectangles.

  3. Dessiner les rectangles à l'écran.
    contexteRenduD2D1->BeginDraw ();
    D2D1_RECT_F rectangleVert = D2D1::RectF(size.width/4 - 50.0f,
                                             size.height/2 - 50.0f,
                                             size.width/2 + 50.0f,
                                             size.height/2 + 50.0f);
    contexteRenduD2D1->FillRectangle (rectangleVert,brosseVerte);
    D2D1_RECT_F rectangleOrange = D2D1::RectF(size.width/4 - 100.0f,
                                             size.height/2 - 100.0f,
                                             size.width/2 + 100.0f,
                                             size.height/2 + 100.0f);
    contexteRenduD2D1->DrawRectangle (rectangleOrange ,brosseOrange);
    contexteRenduD2D1->EndDraw ();

    Toutes opérations de dessin avec Direct2D doit se faire entre les méthodes BeginDraw et EndDraw. Une fois le dessin initialisé, On définit ici deux rectangles D2D1_RECT_F, un vert et un orange que l'on passe respectivement aux méthodes FillRectangle, pour remplir le rectangle de vert et DrawRectangle pour créer un rectangle vide mais aux contours Orange.

Nous allons maintenant initialiser notre contexte et dessiner nos rectangles en appelant notre méthode DessinerRectangle.

  1. Dans la procédure de fenêtre WndProc, ajoutez l'appel à DessinerRectangle pour le message
    ID_DESSINER_RECTANGLE.

    case ID_DESSINER_RECTANGLE:
          DessinerUnRectangle();
          break;

Compilez et lancez l'application. Activez le menu Dessiner->Rectangle. Si tous ce passe correctement vous devriez voir apparaître la figure comme sur l'image suivante :

Exercice 2: Dessiner avec des figures géométriques

Cet exercice introduit la notion de figures géométriques en Direct2D. Nous allons également les manipuler au travers de transformations et apprendre comment appliquer un gradient de couleur à une figure.

L'exercice 2 contient 3 sections :

  1. Comment créer et dessiner une figure géométrique.
  2. Réaliser une transformation sur un objet en lui appliquant un dégradé de couleur.
  3. Combiner deux objets géométriques pour n'en faire qu'un seul.

Exercice 2.1 : Dessiner un sablier

Note : Dans cet exercice, pour des soucis de clarté et de réutilisation, la création de la fabrique indépendante ce fait dans la méthode CreerFabriqueEtRessourcesIndependantes et est appelée dans la méthode InitInstance.

La création du contexte de rendu cible ce fait dans la méthode CreerRessourcesPeripherique et est initialisée dans la méthode DessinerContenuDirect2D qui se charge d'appeler nos méthodes de dessin. Cette dernière est désormais appelée dans la procèdure WndProc pour les messages WM_PAINT et WM_DISPLAYCHANGE

  1. Création d'un objet tracé géométrique qui représentera le sablier:
    Ouvrez la solution
    C:\Windows 7 Labs\06 - Graphiques\Direct2D\Exercice 2\2.1\Direct2DTutoriel\Direct2DTutoriel.sln
  2. Ouvrez le fichier d'entête Direct2DTutoriel.h et ajoutez -y une référence à l'interface ID2D1PathGeometry.

    CComPtr<ID2D1PathGeometry> _geometriePath;

  3. Dans le fichier Direct2DTutoriel.cpp à la méthode CreerFabriqueEtRessourcesIndependantes nous allons ajouter la création de notre interface ID2D1PathGeometry. On l'ajoute à cette méthode parce que les objets géométriques, ne sont pas liées à un matériel spécifique et peuvent être utilisés avec n'importe quel contexte de rendu cible crée par la même fabrique.

    HRESULT hr;
    hr=D2D1CreateFactory (D2D1_FACTORY_TYPE_SINGLE_THREADED,
                             &_fabriqueD2D1);
          //code omis pour plus de clarté
          hr=_fabriqueD2D1->CreatePathGeometry (&_geometriePath);

  4. Ensuite nous allons ajouter la création à l'interface ID2D1GeometrySink afin de remplir notre objet tracé géométrique.
    CComPtr<ID2D1GeometrySink > geometrieSink;
    hr=_geometriePath->Open(&geometrieSink);
    geometrieSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);

    On utilise la méthode Open de l'interface ID2D1PathGeometry et on lui passe l'objet ID2D1GeometrySink. Ensuite on précise le mode de remplissage qui définit si un point donné sur la surface de dessin (le canvas) est dans l'objet géométrique ou pas.

  5. Puis on crée la figure géométrique en commençant et finissant respectivement par les méthodes BeginFigure et EndFigure.
    geometrieSink->BeginFigure(D2D1::Point2F(10, 10),D2D1_FIGURE_BEGIN_FILLED);
    geometrieSink->AddLine(D2D1::Point2F(200,10));
    geometrieSink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(150, 50),
                                                 D2D1::Point2F(150, 150),
                                                 D2D1::Point2F(200, 200)));

    geometrieSink->AddLine(D2D1::Point2F(0, 200));
    geometrieSink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(50, 150),
                                                 D2D1::Point2F(50, 50),
                                                 D2D1::Point2F(10, 10)));

    geometrieSink->EndFigure(D2D1_FIGURE_END_CLOSED);

  6. Puis on ferme l'objet ID2D1GeometrySink
    geometrieSink->Close ();
  7. Dessiner le contenu de notre figure.
    - Dans la méthode DessinerUnSablier ajoutez-y l'appel à DrawGeometry

_contexteRenduD2D1->DrawGeometry (_geometriePath,_brosseBleu);
l'objet _brosseBleu a été crée dans la méthode CreerRessourcesPeripherique, comme à l'exercice 1.

-Dans la méthode DessinerContenuDirect2D, ajoutez-y l'appel à la méthode DessinerUnSablier.
_contexteRenduD2D1->BeginDraw ();
 _contexteRenduD2D1->Clear(D2D1::ColorF(D2D1::ColorF::Black));
 //DessinerUnRectangleBleuEtRouge ();
 DessinerUnSablier();
_contexteRenduD2D1->EndDraw ();

Exercice 2.2 : Appliquer une transformation et un dégradé de couleur à notre sablier

  1. Ouvrez le fichier Direct2DTutoriel.cpp et dans la méthode DessinerUnSablier ajoutez-y le code suivant :
    D2D1_SIZE_U size = D2D1::SizeU((rc.right - rc.left),(rc.bottom - rc.top));
    _contexteRenduD2D1->DrawGeometry (_geometriePath,_brosseBleu); 
    _contexteRenduD2D1->SetTransform (D2D1::Matrix3x2F::Translation(size.width/2-100.0f,                              size.height/2-100.0f));

    La méthode SetTransform effectue une translation de notre sablier du haut gauche vers le bas droit. Nous allons maintenant y ajouter le dégradé de couleurs

  2. Ouvrez le fichier d'entête Direct2DTutoriel.h, et ajoutez-y la variable globale suivante :
    CComPtr<ID2D1LinearGradientBrush> _brosseDegradee;
    On déclare ici une brosse de type dégradée linéaire
  3. Dans le fichier Direct2DTutoriel.cpp, ajoutez-y le code suivant dans la méthode
    CreerRessourcesPeripherique

    - La déclaration à la collection ID2D1GradientStopCollection, permet de définir le point de départ et les couleurs du dégradé.

    CComPtr<ID2D1GradientStopCollection> stopGradient;

    -Tableau correspondant à la position et à la couleur de la graduation
    D2D1_COLOR_F color1Depart;
    D2D1_COLOR_F color2Arrivee;
    color1Depart.r =0.f; //Rouge
    color1Depart.g =1.f; //Vert
    color1Depart.b =1.f; //Bleu
    color1Depart.a =1.f; //Alpha

    color2Arrivee.r =1.f;
    color2Arrivee.g =0.f; 
    color2Arrivee.b  =1.f;
    color2Arrivee.a =1.f;
         
    D2D1_GRADIENT_STOP stopDepart;
    D2D1_GRADIENT_STOP stopArrivee;
         
    stopDepart.color =color1Depart;
    stopDepart.position =0.f;

    stopArrivee.color =color2Arrivee;
    stopArrivee.position =1.f;

    static const D2D1_GRADIENT_STOP stops[]={stopDepart,stopArrivee};
    - Création de la collection de gradients
    hr=_contexteRenduD2D1->CreateGradientStopCollection(stops,                                                     ARRAY_SIZE (stops),
                                                   &stopGradient);

  4. Enfin nous allons créer la brosse graduée.
     D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linearGradientProperties=D2D1::LinearGradientBrushProperties(                                      D2D1::Point2F (100,0),                                          D2D1::Point2F(200,100));
    D2D1_BRUSH_PROPERTIES brosseProperties=D2D1::BrushProperties();
    hr=_contexteRenduD2D1->CreateLinearGradientBrush (linearGradientProperties,brosseProperties,stopGradient, &_brosseDegradee);

    Une fois que notre brosse est créée, il suffit maintenant de la passer à la méthode FillGeometry de notre contexte de rendu

  5. Dans la méthode DessinerUnSablier, ajoutez le code suivant :
    _contexteRenduD2D1->SetTransform (D2D1::Matrix3x2F::Translation(size.width/2-100.0f, 
                                   size.height/2-100.0f));   
    _contexteRenduD2D1->FillGeometry (_geometriePath,_brosseDegradee);
  6. Compilez et testez l'application

Exercice 2.3 : Combiner un objet de type géométrique

  1. Ouvrez le fichier d'entête Direct2DTutoriel.h et ajoutez -y une référence à l'interface ID2D1TransformedGeometry.
    CComPtr<ID2D1TransformedGeometry> _transformationGeometrique;
  2. Ajoutez le code suivant dans la méthode CreerFabriqueEtRessourcesIndependantes, qui créée un objet de type transformation.
    hr=_fabriqueD2D1->CreateTransformedGeometry (_geometriePath,      D2D1::Matrix3x2F::Rotation(45.0f, D2D1::Point2F(100.0f, 100.0f)),      &_transformationGeometrique);
          if (FAILED(hr)) return hr;        
  3. Dans le fichier d'entête Direct2DTutoriel.h ajoutez-y la variable globale suivante qui permettra de sauvegarder une combinaison de plusieurs objets de type tracé géométrique :
    CComPtr<ID2D1PathGeometry>   _geometriePathCombine;
  4. Puis dans la méthode CreerFabriqueEtRessourcesIndependantes nous allons créer notre objet combiné.
    hr=_fabriqueD2D1->CreatePathGeometry (&_geometriePathCombine);
          if (FAILED(hr)) return hr;
  5. Ensuite nous ouvrons un objet de type sink (comme pour l'exercice précédent)
    _geometriePathCombine->Open (&geometrieSink);
    geometrieSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);
  6. Enfin nous réalisons notre combinaison entre l'ancien objet tracé géométrique et l'objet de transformation.
    hr=_geometriePath->CombineWithGeometry(_transformationGeometrique,
                                          D2D1_COMBINE_MODE_UNION,
                                          D2D1::Matrix3x2F::Identity(),
                                         0.25f,
                                         geometrieSink);
          if (FAILED(hr)) return hr;  
  7. Ne pas oublier de fermer l'objet de type sink.
    hr=geometrieSink->Close ();
  8. Enfin, il faut maintenant afficher le contenu de notre combinaison de figures. Dans la méthode DessinerUnSablier, ajoutez-y l'appel suivant :
    _contexteRenduD2D1->DrawGeometry(_geometriePathCombine,_brosseRouge);

Exercice 3 : Dessiner un contenu Direct2D sur une surface GDI

Informations :
Tous les fichiers de cet exercice sont localisés dans le répertoire C:\Windows 7 Labs\06 - Graphiques\Direct2D\Exercice 3\

 

Maintenant que vous savez utiliser Direct2D pour dessiner des figures, nous allons combiner Direct2D et le GDI dans la même application en dessinant un contenu Direct2D sur une surface GDI.

Pour dessiner sur une surface GDI, on utilise l'interface ID2D1RenderTarget. La section qui suit décrit la  méthode BindDC qui permet de lier un contexte Direct2D à un Device Context GDI

  1. Ouvrez la solution Visual Studio  C:\Windows 7 Labs\06 - Graphiques\Direct2D\Exercice 3\Direct2DTutoriel\Direct2DTutoriel.sln
  2. Dans le fichier d'entête Direct2DTutoriel.h, ajoutez la variable de type contexte de rendu sur un device contexte (GDI) suivante :
    CComPtr<ID2D1DCRenderTarget> _contexteDCRenduD2D1;
  3. Ensuite nous allons utiliser la fabrique que nous avons créée dans les exercices précédents, pour créer notre contexte. Dans la méthode  CreerRessourcesPeripherique, ajoutez le code suivant :
    D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
                                 D2D1_RENDER_TARGET_TYPE_DEFAULT,         D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_IGNORE),
                                                                     0.0f,0.0f,      D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,D2D1_FEATURE_LEVEL_DEFAULT);
    hr=_fabriqueD2D1->CreateDCRenderTarget(&props,
    &_contexteDCRenduD2D1);
    if (FAILED(hr)) return hr;
  4. Après le code qui crée un Device Context, ajoutez le code de création d'une brosse bleue
    hr=_contexteDCRenduD2D1->CreateSolidColorBrush (D2D1::ColorF(D2D1::ColorF::Blue),&_brosseBleu);
    if (FAILED(hr)) return hr;
  5. Pour cet exercice, nous allons utiliser une seule méthode DessinerInteropAvecGDI pour l'interopérabilité entre Direct2D et le GDI que nous appellerons dans notre procédure de fenêtre WndProc.
    case WM_PAINT:
    case WM_DISPLAYCHANGE:
          {    
                hdc = BeginPaint(hWnd, &ps);
                DessinerInteropAvecGDI(ps);
                EndPaint(hWnd, &ps);
          }
                break;
  6. Ensuite, nous allons lier le DC (GDI) au contexte Direct2D.
    Ouvrez la méthode DessinerInteropAvecGDI et ajoutez y le code suivant :
    HRESULT hr=S_OK;
    hr=CreerRessourcesPeripherique();
    if (FAILED(hr)) return hr;
    RECT rc;
    GetClientRect(_hwndParent,&rc);
    D2D1_SIZE_U size = D2D1::SizeU((rc.right - rc.left),(rc.bottom - rc.top));

    _contexteDCRenduD2D1->BindDC (ps.hdc,&rc);
          _contexteDCRenduD2D1->BeginDraw ();
                _contexteDCRenduD2D1->SetTransform(D2D1::Matrix3x2F::Identity());
                _contexteDCRenduD2D1->Clear(D2D1::ColorF(D2D1::ColorF::White));
    _contexteDCRenduD2D1->DrawEllipse( D2D1::Ellipse(D2D1::Point2F(150.0f,            150.0f),100.0f, 100.0f),_brosseBleu,3.0);

    _contexteDCRenduD2D1->DrawLine(D2D1::Point2F(150.0f, 150.0f),
                                 D2D1::Point2F((150.0f + 100.0f * 0.15425f),(150.0f - 100.0f * 0.988f)), _brosseBleu,
                                                   3.0);

    _contexteDCRenduD2D1->DrawLine(D2D1::Point2F(150.0f, 150.0f),
                                 D2D1::Point2F((150.0f + 100.0f * 0.525f),(150.0f + 100.0f * 0.8509f)),_brosseBleu,3.0);

    _contexteDCRenduD2D1->DrawLine(D2D1::Point2F(150.0f, 150.0f),
                                                   D2D1::Point2F((150.0f - 100.0f * 0.988f),(150.0f - 100.0f * 0.15425f)),_brosseBleu,3.0);
    _contexteDCRenduD2D1->EndDraw ();

  7. Puis dé-commentez le code suivant, toujours dans la méthode DessinerInteropAvecGDI

    HGDIOBJ original = NULL;
          original = SelectObject(ps.hdc,GetStockObject(DC_PEN));
         
          HPEN pinceauBleu = CreatePen(PS_SOLID, 3,RGB(0,0,255));
          SelectObject(ps.hdc, pinceauBleu);
          ::Ellipse(ps.hdc,300,50,500,250);

          POINT pntArray1[2];
          pntArray1[0].x = 400;
          pntArray1[0].y = 150;
          pntArray1[1].x = static_cast<LONG>(400 + 100 * 0.15425);
          pntArray1[1].y = static_cast<LONG>(150 - 100 * 0.9885);

          POINT pntArray2[2];
          pntArray2[0].x = 400;
          pntArray2[0].y = 150;
          pntArray2[1].x = static_cast<LONG>(400 + 100 * 0.525);
          pntArray2[1].y = static_cast<LONG>(150 + 100 * 0.8509);

          POINT pntArray3[2];
          pntArray3[0].x = 400;
          pntArray3[0].y = 150;
          pntArray3[1].x = static_cast<LONG>(400 - 100 * 0.988);
          pntArray3[1].y = static_cast<LONG>(150 - 100 * 0.15425);

          ::Polyline(ps.hdc,pntArray1,2);
          ::Polyline(ps.hdc,pntArray2,2);
          ::Polyline(ps.hdc,pntArray3,2);

          DeleteObject(pinceauBleu);

     
          SelectObject(ps.hdc, original);

Exécutez le programme. Constatez-vous une différence de rendu ? 

1.       Ouvrez la solution Visual Studio  C:\Windows 7 Labs\06 - Graphiques\Direct2D\Exercice 3\Direct2DTutoriel\Direct2DTutoriel.sln

2.       Dans le fichier d'entête Direct2DTutoriel.h, ajoutez la variable de type contexte de rendu sur un device contexte (GDI) suivante :
CComPtr<ID2D1DCRenderTarget> _contexteDCRenduD2D1;

3.       Ensuite nous allons utiliser la fabrique que nous avons créée dans les exercices précédents, pour créer notre contexte. Dans la méthode  CreerRessourcesPeripherique, ajoutez le code suivant :
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
                             D2D1_RENDER_TARGET_TYPE_DEFAULT,         D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_IGNORE),
                                                                 0.0f,0.0f,      D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,D2D1_FEATURE_LEVEL_DEFAULT);
hr=_fabriqueD2D1->CreateDCRenderTarget(&props,
&_contexteDCRenduD2D1);
if (FAILED(hr)) return hr;


4.       Après le code qui crée un Device Context, ajoutez le code de création d'une brosse bleue
hr=_contexteDCRenduD2D1->CreateSolidColorBrush (D2D1::ColorF(D2D1::ColorF::Blue),&_brosseBleu);
if (FAILED(hr)) return hr;


5.       Pour cet exercice, nous allons utiliser une seule méthode DessinerInteropAvecGDI pour l'interopérabilité entre Direct2D et le GDI que nous appellerons dans notre procédure de fenêtre WndProc.
case WM_PAINT:
case WM_DISPLAYCHANGE:
      {    
            hdc = BeginPaint(hWnd, &ps);
            DessinerInteropAvecGDI(ps);
            EndPaint(hWnd, &ps);
      }
            break
;

6.       Ensuite, nous allons lier le DC (GDI) au contexte Direct2D.
Ouvrez la méthode
DessinerInteropAvecGDI et ajoutez y le code suivant :
HRESULT hr=S_OK;
hr=CreerRessourcesPeripherique();
if (FAILED(hr)) return hr;
RECT rc;
GetClientRect(_hwndParent,&rc);
D2D1_SIZE_U size = D2D1::SizeU((rc.right - rc.left),(rc.bottom - rc.top));

_contexteDCRenduD2D1->BindDC (ps.hdc,&rc);
      _contexteDCRenduD2D1->BeginDraw ();
            _contexteDCRenduD2D1->SetTransform(D2D1::Matrix3x2F::Identity());
            _contexteDCRenduD2D1->Clear(D2D1::ColorF(D2D1::ColorF::White));
_contexteDCRenduD2D1->DrawEllipse( D2D1::Ellipse(D2D1::Point2F(150.0f,            150.0f),100.0f, 100.0f),_brosseBleu,3.0);

_contexteDCRenduD2D1->DrawLine(D2D1::Point2F(150.0f, 150.0f),
                             D2D1::Point2F((150.0f + 100.0f * 0.15425f),(150.0f - 100.0f * 0.988f)), _brosseBleu,
                                               3.0);

_contexteDCRenduD2D1->DrawLine(D2D1::Point2F(150.0f, 150.0f),
                             D2D1::Point2F((150.0f + 100.0f * 0.525f),(150.0f + 100.0f * 0.8509f)),_brosseBleu,3.0);

_contexteDCRenduD2D1->DrawLine(D2D1::Point2F(150.0f, 150.0f),
                                               D2D1::Point2F((150.0f - 100.0f * 0.988f),(150.0f - 100.0f * 0.15425f)),_brosseBleu,3.0);
_contexteDCRenduD2D1->EndDraw ();

7.       Puis dé-commentez le code suivant, toujours dans la méthode DessinerInteropAvecGDI

HGDIOBJ original = NULL;
      original = SelectObject(ps.hdc,GetStockObject(DC_PEN));
     
      HPEN pinceauBleu = CreatePen(PS_SOLID, 3,RGB(0,0,255));
      SelectObject(ps.hdc, pinceauBleu);
      ::Ellipse(ps.hdc,300,50,500,250);

      POINT pntArray1[2];
      pntArray1[0].x = 400;
      pntArray1[0].y = 150;
      pntArray1[1].x = static_cast<LONG>(400 + 100 * 0.15425);
      pntArray1[1].y = static_cast<LONG>(150 - 100 * 0.9885);

      POINT pntArray2[2];
      pntArray2[0].x = 400;
      pntArray2[0].y = 150;
      pntArray2[1].x = static_cast<LONG>(400 + 100 * 0.525);
      pntArray2[1].y = static_cast<LONG>(150 + 100 * 0.8509);

      POINT pntArray3[2];
      pntArray3[0].x = 400;
      pntArray3[0].y = 150;
      pntArray3[1].x = static_cast<LONG>(400 - 100 * 0.988);
      pntArray3[1].y = static_cast<LONG>(150 - 100 * 0.15425);

      ::Polyline(ps.hdc,pntArray1,2);
      ::Polyline(ps.hdc,pntArray2,2);
      ::Polyline(ps.hdc,pntArray3,2);

      DeleteObject(pinceauBleu);

 
      SelectObject(ps.hdc, original);

 Exécutez le programme. Constatez-vous une différence de rendu ?

Ajouter un commentaire

Filtered HTML

Plain text

CAPTCHA
Cette question permet de vérifier que vous n'êtes pas un robot spammeur :-)
 N   N   QQQ    TTTTTT  III  Y   Y 
NN N Q Q TT I Y Y
N N N Q Q TT I Y
N NN Q QQ TT I Y
N N QQQQ TT III Y
Q