Gdi et dessin

Messages postés
192
Date d'inscription
mercredi 26 décembre 2001
Statut
Membre
Dernière intervention
31 janvier 2007
- - Dernière réponse : cs_Arkko
Messages postés
192
Date d'inscription
mercredi 26 décembre 2001
Statut
Membre
Dernière intervention
31 janvier 2007
- 30 oct. 2003 à 03:12
Je dessine quelque chose sur mon dialog avec gdi (fonction Rectangle) et quand je la reduit et la remet ... le dessin s'efface ... mais le dessin est generer par l'utilisateur (ex. paint ) comment faire pour quil ne s'efface pas
merci
@+ arkko
Afficher la suite 

10 réponses

Messages postés
584
Date d'inscription
mardi 26 novembre 2002
Statut
Membre
Dernière intervention
29 mai 2015
0
Merci
Il s'efface toujours puisque tu ne le vois plus à l'écran!
En fait à chaque fois que la fenêtre réapparait elle émet WM_PAINT. C'est en captant cet événement que tu dois tout redessiné. Eventuellement tu peux enregistrer ton image dans un buffer à chaque fois que ta fenêtre est masquée et le remettre d'un coup quand elle réapparait (c'est plus ou moins ce qu'on appelle du double-buffering)
Commenter la réponse de garslouche
Messages postés
1138
Date d'inscription
mardi 10 juin 2003
Statut
Membre
Dernière intervention
25 janvier 2009
2
0
Merci
T'es sur que c'est ce que l'on appelle le double buffering ??

Ici il n'y a pas deux buffer, non ?

En win32, tu dois etre capable a tout instant de redessiner une partie de ta fenetre sur demande de Windows. Celui-ci t'envoie un message WM_PAINT a ta procedure :

switch(iMsg)
{
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;

hdc = BeginPaint(hwnd,&ps);
... // tes operations graphiques
// tu genres :
MoveToEx(hdc,0,0,NULL);
LineTo(hdc,50,50);
EndPaint(hwnd,&ps);
return 0;
}
}
Commenter la réponse de cs_JCDjcd
Messages postés
584
Date d'inscription
mardi 26 novembre 2002
Statut
Membre
Dernière intervention
29 mai 2015
0
Merci
D'abord j'ai écrit que c'était plus ou moins du double-buffering....et en plus il y a deux buffers : celui qui est utilisé pour affiché à l'écran et celui où l'on écrit virtuellement.
Commenter la réponse de garslouche
Messages postés
1138
Date d'inscription
mardi 10 juin 2003
Statut
Membre
Dernière intervention
25 janvier 2009
2
0
Merci
J'ai bien compris ce que tu as dis, mais je ne comprend pas : il n'y a qu'un buffer : celui dans lequel on ecrit <=> celui qui est afficher, non ?

On n'est pas en OpenGL, ou la effectivement il y a deux buffer.
Commenter la réponse de cs_JCDjcd
Messages postés
584
Date d'inscription
mardi 26 novembre 2002
Statut
Membre
Dernière intervention
29 mai 2015
0
Merci
La technique du double buffering n'est pas spécifique à OpenGL ! C'est juste un truc qui évite de voir les différentes parties d'un composant graphique se dessiner au fur et à mesure. Le principe c'est qu'au lieu de dessiner à l'écran car partie d'un dessin on le fait dans un écran virtuel (le buffer). Une fois qu'on a terminé de dessiner dans le buffer on remplace l'affichage de l'écran par le buffer d'un seul coup. Ainsi ça ne clignote pas quand on efface des trucs ou quand il y a des animations, ...
Commenter la réponse de garslouche
Messages postés
192
Date d'inscription
mercredi 26 décembre 2001
Statut
Membre
Dernière intervention
31 janvier 2007
0
Merci
Ouais mais mon programme c'Est un espece de paint (le user dessine) donc ds paint je ne peux pas vriament dessiner des rectangles :) la methode du buffering semble interessente .. pouvez vous me l'explique en profondeur avec du code si possible
merci
Commenter la réponse de cs_Arkko
Messages postés
1138
Date d'inscription
mardi 10 juin 2003
Statut
Membre
Dernière intervention
25 janvier 2009
2
0
Merci
//***********************************************
#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
//***********************************************

int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow
)
{
static char szAppName[] = "ExemplePourArkko";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;

wndclass.cbSize = sizeof (wndclass);
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);

RegisterClassEx(&wndclass);

hwnd = CreateWindow(
szAppName, // nom de la classe
szAppName, // titre de la fenetre
WS_OVERLAPPED | WS_SYSMENU, // style de la fenetre
CW_USEDEFAULT, // position initiale en x
CW_USEDEFAULT, // position initiale en y
512, // largeur initiale
512, // hauteur initiale
NULL, // handle de la fenetre mere
NULL, // handle du menu de la fenetre
hInstance, // handle de l'instance
NULL); // parametres de creation

ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);

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

LRESULT CALLBACK WndProc(
HWND hwnd,
UINT iMsg,
WPARAM wParam,
LPARAM lParam
)
{
static int cx,cy;
switch (iMsg)
{
case WM_CREATE:
{
return 0;
}
case WM_SIZE:
{
cx = LOWORD(lParam);
cy = HIWORD(lParam);
break;
}
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;

hdc = BeginPaint(hwnd,&ps);
Rectangle(hdc,cx/4,cy/4,3*cx/4,3*cy/4);
EndPaint(hwnd,&ps);
return 0;
}
case WM_DESTROY:
{
PostQuitMessage (0);
return 0;
}
}

return DefWindowProc(hwnd,iMsg,wParam,lParam);
}
Commenter la réponse de cs_JCDjcd
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
0
Merci
Si tu veux pouvoir redessiner à l'écran à tout momment ce que l'utilisateur à fait, il suffit de stocker son dessin dans un bitmap.

1) Au début d'un nouveau dessin, créer un DC et un bitmap en mémoire compatible avec le DC de la fenêtre (hWnd) où il sera affiché :
HDC hdc = GetDC(hWnd);
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, cx, cy);
HBITMAP hOldBmp = SelectObject(hMemDC, hMemBmp);

les variables hMemDC, hMemBmp et hOldBmp doivent être globale. hOldBmp servira pour restaurer l'état du GDI à la fin.

2) Ensuite, quand tu traite les opération de dessin de l'utilisateur, au lieu de dessiner dans le DC de ta fenêtre, utilise celui en mémoire (hMemDC), exactement de la même façon.

3) Quand la fenêtre aura besoin d'être dessinée, (message WM_PAINT), il suffit de recopier ton DC en mémoire :

HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);

BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0);

EndPaint(hWnd,&ps);

4) Enfin, à la fin de l'appli, il faut libérer le DC:
SelectObject(hMemDC, hOldBmp);
DeleteObject(hMemBmp);
DeleteDC();

Un conseille pour éviter un clignotement de l'écran lors des dessins :
- Ne pas effacer le fond de l'écran mais celui du bitmap en mémoire puis le recopier.
- Utiliser InvalidateRect(hWnd, NULL, FALSE);pour mettre à jour l'écran sans que le fond de l'écran soit effacer à haque fois.
Commenter la réponse de ymca2003
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
0
Merci
J'ai oublié un paramètre à la fonction BitBlt :

BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY);
Commenter la réponse de ymca2003
Messages postés
192
Date d'inscription
mercredi 26 décembre 2001
Statut
Membre
Dernière intervention
31 janvier 2007
0
Merci
merci :D
Commenter la réponse de cs_Arkko