Un meilleur job mieux payé ?

Deviens chef de projet, développeur, ingénieur, informaticien

Mets à jour ton profil pro

ça m'intéresse

Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :



API Windows en C

6 - Dessiner.

Par CGi

Le 10 juin 2005




Introduction :

Après avoir vu les contextes de périphériques, nous allons aborder les principales fonctions de dessin.

Comme vu au chapitre 5 nous dessinerons suite à la réception du message WM_PAINT dans un contexte de périphérique obtenu avec BeginPaint.

Dessin :

Nous allons continuer sur la base de l'exemple du chapitre précédent. Nous y écrirons tout d'abord la même chaîne de caractère avec TextOut, mais une seule fois. Ensuite, nous tracerons un rectangle au dessous de la chaîne de caractères :

              Rectangle(hdc, 20, 60, 120, 100);

Cette fonction reçoit comme paramètres le handle de contexte de périphérique et les coordonnées des points haut gauche et bas droit du rectangle. Windows pour dessiner ce rectangle utilise un crayon et un pinceau. Quand vous obtenez un handle de contexte de périphérique, il possède déjà un crayon et un pinceau. Mais vous pouvez aussi dessiner avec des crayons et des pinceaux que vous avez créés.

              HBRUSH hbRed, hbrOld;
              HPEN hp2px, hpOld;

              /*...   ...*/

              hp2px = CreatePen(PS_SOLID, 2, 0x00FF0000);
              hpOld = SelectObject(hdc,hp2px);

              hbRed = CreateSolidBrush(0x000000FF);
              hbrOld = SelectObject(hdc,hbRed);

              Rectangle(hdc, 160, 60, 260, 100);

              SelectObject(hdc,hbrOld);
              DeleteObject(hbRed);

              SelectObject(hdc,hpOld);
              DeleteObject(hp2px);

La création d'un crayon ce fait avec la fonction CreatePen qui reçoit comme paramètres une constante indiquant le type de trait (continu dans l'exemple), ensuite la largeur du trait (2 pixels) et enfin sa couleur (bleu). Après son appel, elle retourne un handle de crayon.
Le pinceau rouge est créé avec la fonction CreateSolidBrush qui reçoit comme paramètre une couleur. Mais pour pouvoir les utiliser avec un contexte de périphérique, il faut les sélectionner. C'est le rôle de la fonction SelectObject, qui reçoit le handle du contexte de périphérique sur lequel on veut utiliser l'objet (pinceau, crayon ...) et le handle de l'objet comme second paramètre. Le second rectangle est donc dessiné avec un contour tracé avec le crayon bleu d'une largeur de deux pixels et son intérieur peint avec le pinceau rouge.
Quand vous en avez terminé avec l'utilisation des objets que vous avez créé, il faut les détruire avec la fonction DeleteObject. De même avant de libérer le contexte de périphérique il faut toujours sélectionner ses objets d'origine avec SelectObject. Le handle de ces objets étant retourné par la fonction SelectObject.

Pour la forme nous dessinerons ensuite un cercle à l'aide le la fonction Ellipse et d'un pinceau à hachures diagonales croisés, puis un trait bleu à l'aide des fonctions MoveToEx qui positionne le point de départ et LineTo qui trace jusqu'au point d'arrivée quelle reçoit comme paramètre et qui devient le nouveau point de départ.
Nous n'avons vu que quelques fonctions de dessin, veuillez consulter l'aide API Win32 pour plus de détail.

              hbGreen = CreateHatchBrush(HS_DIAGCROSS, 0x0000BB00);
              SelectObject(hdc,hbGreen);
              DeleteObject(hbRed);

              Ellipse(hdc, 300, 20, 400, 120);

              MoveToEx(hdc, 20, 140, NULL);
              LineTo(hdc, 400, 140);

Je vous invite de même à consulter l'aide Win32 API pour voir toutes les possibilités que fournissent les crayons et les pinceaux.


Les polices de caractères :

Nous avons dessiné une chaîne de caractère sur la fenêtre, mais comme vous le savez Windows peut utiliser d'autres polices de caractères installées sur le système tel les polices "True Type".
Pour les utiliser le principe est semblable aux crayons ou pinceaux. Il faut créer l'objet police avec CreateFont ou CreateFontIndirect qui retournent un handle de police. Dans l'exemple nous utiliserons CreateFontIndirect car elle est plus simple à utiliser. CreateFontIndirect utilise une structure LOGFONT pour initialiser la police. Nous remplirons seulement deux de ses champs dans l'exemple pour qu'il reste simple. Les autres serons initialisé à zéro à l'aide de la fonction ZeroMemory :

              HFONT NewFont, OldFont;
              LOGFONT lf;

              /*...   ...*/

              ZeroMemory(&lf, sizeof(LOGFONT));
              lstrcpy(lf.lfFaceName,"Times New Roman");
              lf.lfHeight = 36;

              NewFont = CreateFontIndirect(&lf);
              OldFont = SelectObject(hdc,NewFont);

              SetTextColor(hdc, 0x000000FF);
              TextOut(hdc, 10, 180, st, lstrlen(st));

              SelectObject(hdc,OldFont);
              DeleteObject(NewFont);

Première opération, remplir les champs de la variable lf de type LOGFONT. Elle possède un champ lfFaceName : tableau de caractères où nous copions le nom de la police que nous désirons utiliser avec la fonction lstrcpy. Ce tableau a une taille de 32 caractères (y compris le zéro terminal). Nous mettons le champ lfHeight correspondant à la hauteur des caractères à 36. Nous positionnerons le champ lfItalic à true et le champ lfWeight à FW_BOLD pour écrire la chaîne de caractères en gras italique.
Tout comme pour les crayons ou pinceaux, il faut sélectionner les objets Fonts pour les utiliser et les détruire après utilisation, sans oublier de sélectionner la police d'origine avant de libérer le contexte de périphérique.
Pour plus de précisions sur les polices de caractères, veuillez consulter l'aide API Win32.

Code complet :

#include <windows.h>


LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
                                                LPSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG msg;
    WNDCLASS wc;

    wc.style = 0;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hinstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
    wc.lpszMenuName =  NULL;
    wc.lpszClassName = "MaWinClass";

    if(!RegisterClass(&wc)) return FALSE;

    hwnd = CreateWindow("MaWinClass", "Dessiner", WS_OVERLAPPEDWINDOW,
                                   CW_USEDEFAULT, CW_USEDEFAULT, 460, 300,
                                                   NULL, NULL, hinstance, NULL);
    if (!hwnd) return FALSE;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);


    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
/******************************************************************************/

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_PAINT :
            {
              HBRUSH hbRed, hbGreen, hbrOld;
              HPEN hp2px, hpOld;
              HFONT NewFont, OldFont;
              LOGFONT lf;

              char st[] = "Bienvenue sur Developpez.com" ;

              PAINTSTRUCT ps;
              HDC hdc = BeginPaint(hwnd, &ps);
              SetBkMode(hdc, TRANSPARENT);

              TextOut(hdc, 10, 20, st, lstrlen(st));

              Rectangle(hdc, 20, 60, 120, 100);

              hp2px = CreatePen(PS_SOLID, 2, 0x00FF0000);
              hpOld = SelectObject(hdc,hp2px);

              hbRed = CreateSolidBrush(0x000000FF);
              hbrOld = SelectObject(hdc,hbRed);

              Rectangle(hdc, 160, 60, 260, 100);

              hbGreen = CreateHatchBrush(HS_DIAGCROSS, 0x0000BB00);
              SelectObject(hdc,hbGreen);
              DeleteObject(hbRed);

              Ellipse(hdc, 300, 20, 400, 120);

              MoveToEx(hdc, 20, 140, NULL);
              LineTo(hdc, 400, 140);

              SelectObject(hdc,hbrOld);
              DeleteObject(hbGreen);

              SelectObject(hdc,hpOld);
              DeleteObject(hp2px);

              ZeroMemory(&lf, sizeof(LOGFONT));
              lstrcpy(lf.lfFaceName,"Times New Roman");
              lf.lfHeight = 36;
              lf.lfItalic = TRUE;
              lf.lfWeight = FW_BOLD;

              NewFont = CreateFontIndirect(&lf);
              OldFont = SelectObject(hdc,NewFont);

              SetTextColor(hdc, 0x000000FF);
              TextOut(hdc, 10, 180, st, lstrlen(st));

              SelectObject(hdc,OldFont);
              DeleteObject(NewFont);

              EndPaint(hwnd, &ps);
              return 0;
            }

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

A vos PC.

CGi

Avec la contribution de nico-pyright(c) pour la relecture.



Sommaire



C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?

  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.

Assembleur
  Assembleur sous Visual C++.

C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.

  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.

DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.

Java
  Applet java.





Copyright 2002-2016 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels.
Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document.
De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.

Contacter le responsable de la rubrique C