Création de graphiques avec les api windows

Description

Les exemples de tracés de courbes ne sont pas très fréquents en assembleur, aussi peut être que ce code pourra aider les débutants. La création de la dialogbox a été reprise d'une source de Bombela (et d'autres), j'y ai rajouté quelques fonctions graphiques à commencer par la création d'un hdc.
Les fonctions incluses comprennent:
-création du hdc
-création de brosses, de traits
-création de rectangles
-création d'axes, de courbes
-affichage d'une légende

Le programme utilise quelques instructions en virgule flottante (ce qui était nouveau pour moi)dont des conversions

Source / Exemple :


;nasmw -fobj courbe.asm			pour compiler avec Nasm
;alink -oPE courbe.obj			pour linker avec alink (pas de lib necessaire ici)

;déclaration des api à importer

EXTERN ExitProcess
import ExitProcess kernel32.dll
EXTERN CreateWindowExA
import CreateWindowExA user32.dll
extern GetModuleHandleA
import GetModuleHandleA kernel32.dll
extern GetCommandLineA
import GetCommandLineA kernel32.dll
EXTERN RegisterClassExA
import RegisterClassExA user32.dll
EXTERN ShowWindow
import ShowWindow user32.dll
EXTERN LoadIconA
import LoadIconA user32.dll
EXTERN LoadCursorA
import LoadCursorA user32.dll
EXTERN DefWindowProcA
import DefWindowProcA user32.dll
EXTERN PostQuitMessage
import PostQuitMessage user32.dll
EXTERN TranslateMessage
import TranslateMessage user32.dll
EXTERN DispatchMessageA
import DispatchMessageA user32.dll
EXTERN GetMessageA
import GetMessageA user32.dll
EXTERN PostMessageA
import PostMessageA user32.dll
EXTERN BeginPaint
import BeginPaint user32.dll
EXTERN CreateFontIndirectA
import CreateFontIndirectA gdi32.dll
EXTERN DeleteObject
import DeleteObject gdi32.dll
EXTERN Rectangle
import Rectangle gdi32.dll
EXTERN SetPixel
import SetPixel gdi32.dll
EXTERN CreateSolidBrush
import CreateSolidBrush gdi32.dll
EXTERN CreatePen
import CreatePen gdi32.dll
EXTERN SelectObject
import SelectObject gdi32.dll
EXTERN DeleteObject
import DeleteObject gdi32.dll
EXTERN MoveToEx
import MoveToEx gdi32.dll
EXTERN LineTo
import LineTo gdi32.dll
EXTERN SetTextColor
import SetTextColor gdi32.dll
EXTERN TextOutA
import TextOutA gdi32.dll

;définition des constantes utilisées

%define NULL			0 
%define SW_SHOW			5
%define CS_HREDRAW		2
%define CS_VREDRAW		1
%define IDC_ARROW		0x00007F00
%define COLOR_BTNFACE		0x0000000F
%define WS_TILEDWINDOW		0x00CF0000
%define WS_EX_LEFT		0
%define WM_CREATE		0x00000001
%define WM_DESTROY		0x00000002
%define TRUE			0x00000001
%define WM_SETFONT		0x00000030 
%define WM_QUIT			0x00000012
%define WM_SETFONT		0x00000030 
%define WM_SETFONT		0x00000030
%define BS_SOLID		0
%define PS_SOLID		0
%define WM_PAINT		0x0000000F
%define	IDI_WINLOGO             0x00007F05
%define	IDC_HAND		0x00007F89
%define	COLOR_ACTIVECAPTION	0x00000002

;définition des structures

struc WNDCLASSEX
   	.cbSize			resd 1
   	.style			resd 1
   	.lpfnWndProc		resd 1
   	.cbClsExtra		resd 1
   	.cbWndExtra		resd 1
   	.hInstance		resd 1
   	.hIcon			resd 1
   	.hCursor		resd 1
   	.hbrBackground		resd 1
   	.lpszMenuName		resd 1
   	.lpszClassName		resd 1
   	.hIconSm		resd 1
ENDSTRUC
  
struc MSG
   	.hwnd			resd 1
   	.message		resd 1
   	.wParam			resd 1
   	.lParam			resd 1
   	.time			resd 1
   	.pt			resd 1
ENDSTRUC

struc PAINTSTRUCT
   	.hdc			resd 1
   	.fErase			resd 1
   	.rcPaint.left		resd 1
   	.rcPaint.top		resd 1
   	.rcPaint.right		resd 1
   	.rcPaint.bottom		resd 1
   	.fRestore		resd 1
   	.fIncUpdate		resd 1
   	.rgbReserved		resb 32
ENDSTRUC 

struc POINT
   	.x			resd 1
   	.y			resd 1
ENDSTRUC

;il est possible de s'affranchir de ces déclarations en incluant les librairies ad-hoc

SECTION CODE USE32 CLASS=CODE
  
..start:

	push dword NULL
	call [GetModuleHandleA]
	mov dword [Instance], eax

	Call [GetCommandLineA]
	mov dword [CommandLine], eax

	push dword SW_SHOW
	push dword eax
	push dword NULL
	push dword [Instance]
	call WinMain

	push dword eax
	call [ExitProcess]

;************************************************
;*	             winMain			*
;************************************************
%define hInstance 	ebp+8
%define hPrevInstance	ebp+12
%define lpCmdLine	ebp+16
%define nCmdShow	ebp+20

WinMain:
	enter 48,0					;reserve 48 octets pour la structure WNDCLASSEX
	mov [ebp-48],byte 48				;cbsize
	mov [ebp-44],dword CS_HREDRAW | CS_VREDRAW	;style
	mov [ebp-40],dword WinProc			;Winproc	
	mov [ebp-36],byte 0				;cbClsExtra
	mov [ebp-32],byte 0				;cbWndExtra
	mov eax,dword [Instance]			;hInstance
	mov [ebp-28],eax
	push dword IDI_WINLOGO
	push dword NULL
	call [LoadIconA]
	mov [ebp-24],eax				;hIcon
	mov [ebp-4],eax					;hIconSm
	push dword IDC_HAND
	push dword NULL
	call [LoadCursorA]
	mov [ebp-20],eax				;hCursor
	mov [ebp-16],dword COLOR_ACTIVECAPTION		;hbrBackground
	mov [ebp-12],dword NULL				;lpszMenuName
	mov [ebp-8],dword ClassName			;lpszClassName
	push esp					;pointeur sur la structure WNDCLASSEX (dans la pile)
	call [RegisterClassExA]

	cmp eax,0
	jne .RegisterOk

	mov eax, 1
	jmp Fin

.RegisterOk
	mov dword [Atom], eax
	push dword NULL
	mov eax, dword [hInstance]
	push dword eax
	push dword NULL
	push dword NULL
	push dword 768				; Hauteur fenêtre
	push dword 1024				; Largeur fenêtre
	push dword 0 				; Haut
	push dword 0 				; Gauche
	push dword WS_TILEDWINDOW
	push dword WindowName
	push dword ClassName
	push dword WS_EX_LEFT
	call [CreateWindowExA]

	cmp eax , 0
	jne .CreateWindowOk

	mov eax, 2
	jmp Fin

.CreateWindowOk

	mov dword [WindowHandle], eax

	push dword SW_SHOW
	push dword [WindowHandle]
	call [ShowWindow]

.BoucleMessages

	push dword 0
	push dword 0
	push dword [WindowHandle]
	push dword Msg
	call [GetMessageA]

	cmp eax, WM_QUIT
	je .FinBoucle 

	cmp eax, -1
	jne .GetMEssageOk

	mov eax, 3
	jmp Fin

.GetMEssageOk

	push dword Msg
	call [TranslateMessage]
	push dword Msg
	call [DispatchMessageA]
	jmp .BoucleMessages

.FinBoucle
	mov eax, dword [Msg+MSG.wParam]

Fin:
	leave
	ret 16

;*********************************************
;*	        WindowProc		     *
;*********************************************
%define hwnd	ebp+8
%define uMsg	ebp+12
%define wParam	ebp+16
%define lParam	ebp+20

WinProc:

	enter 0,0
	mov eax,[uMsg]
	cmp eax,WM_CREATE
	je near .Create  
	cmp eax,WM_DESTROY
	je near .Destroy
	cmp eax,WM_PAINT
	je .Paint

.Defaut
	push dword [lParam]
	push dword [wParam] 
	push dword [uMsg]]
	push dword [hwnd]
	call [DefWindowProcA]

.Fin
	leave
	ret 16

.Create ;**************************************
	push dword FontStandard
	call [CreateFontIndirectA]
	mov dword [hFontStandard], eax

	jmp .Fin

.Destroy ;*************************************
	push dword [hFontStandard]
	call [DeleteObject] 
	jmp .Fin

.Paint ;début de la partie graphique______________________________________________________________________________________

	push dword mystruc
	push dword [WindowHandle]
	call [BeginPaint]			;créé un handle de contexte (hdc)
	mov [mystruc+PAINTSTRUCT.hdc],eax

	push dword [couleurbrosse]		;définit la nouvelle couleur de la brosse
	call [CreateSolidBrush]
	mov [hbrosse],eax			;sauvegarde le handle correspondant

	push eax
	push dword [mystruc+PAINTSTRUCT.hdc]
	call [SelectObject]			;selectionne la nouvelle brosse, retourne le handle de l'ancienne
	mov [hbrosseanc],eax

	push dword 684
	push dword 812
	push dword 84
	push dword 100
	push dword [mystruc+PAINTSTRUCT.hdc]
	call [Rectangle]			;dessine un rectangle avec la couleur de remplissage de la brosse (rouge)
 
	push dword[hbrosseanc]
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [SelectObject]			;revient à l'ancienne brosse

	push dword[hbrosse]
	call [DeleteObject]			;suprime la brosse devenue inutile

	push dword 128
	push dword 150
	push dword 640
	push dword 756
	push dword [mystruc+PAINTSTRUCT.hdc]
	call [Rectangle]			;dessine un autre rectangle (couleur par défaut - blanc)

	push dword 0
	push dword 3
	push dword PS_SOLID
	call [CreatePen]			;définit un nouveau trait (pour les axes)
	mov [hpen],eax

	push eax
	push dword [mystruc+PAINTSTRUCT.hdc]
	call [SelectObject]			;sélectionne ce dernier, retourne le handle de l'ancien
	mov [hpenanc],eax

;	axe des abscisses
	push dword NULL
	push dword 384
	push dword 150
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [MoveToEx]				;définit le point de départ de la ligne à tracer
	push dword 384
	push dword 756
	push dword[mystruc+PAINTSTRUCT.hdc]	;définit le point d'arrivée de la ligne
	call [LineTo]

;	axe des ordonnées
	push dword NULL
	push dword 640
	push dword 200
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [MoveToEx]				;définit le point de départ de la ligne à tracer
	push dword 128
	push dword 200
	push dword[mystruc+PAINTSTRUCT.hdc]	;définit le point d'arrivée de la ligne
	call [LineTo]
	
	push dword [couleurpen]
	push dword [largeurpen]
	push dword PS_SOLID
	call [CreatePen]			;définit un nouveau trait (bleu)
	mov [hpen],eax
	 
	push eax
	push dword [mystruc+PAINTSTRUCT.hdc]
	call [SelectObject]			;sélectionne ce dernier, retourne le handle de l'ancien
	mov [hpenanc],eax
	
;	tracé de la courbe
	
	push dword NULL
	mov eax,384
	mov [y],eax
	push eax
	mov eax,200
	mov [x],eax
	push eax
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [MoveToEx]				;définit le point de départ de la ligne à tracer
	mov ecx,512

boucle	push ecx				;à sauvegarder car utilisé par windows
	inc dword [x]
	fild dword[x]				;convertit la valeur entière en flottant
	fsub dword[xo]				;calcule à partir de l'origine (soustraction flottante)
	fmul dword [pi]
	fdiv dword[f]
	fsin
	fmul dword[g]				;fonction=g*sin(pi*(x-xo)/f)
	fchs
	fadd dword [yo]				;inverse le sens et décale (origine écran en haut)
	fistp dword[y]				;reconvertit en entier (et vide la pile)
	push dword [y]
	push dword [x]
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [LineTo]				;définit le point d'arrivée de la ligne
	pop ecx
	loop boucle

;	légende
	push dword 0x00808000
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [SetTextColor]			;définit la couleur du texte	

	push dword 8				;nombre de caractères du texte
	push dword texte
	push dword 200
	push dword 600
	push dword[mystruc+PAINTSTRUCT.hdc]
	call [TextOutA]				;affiche le texte en x=600 y=200
	leave
	ret 16
;fin de la partie graphique_____________________________________________________
  

; Procedures et fonctions secondaires
;_______________________________________________

 ;Procedure qui assigne une font standard à un contrôle
 ; Param : Handle du contrôle dans eax

SetFontStandard:
	push dword TRUE
	push dword [hFontStandard]
	push dword WM_SETFONT
	push dword eax
	call [PostMessageA]
	ret

;_______________________________________________
  
SECTION DATA USE32 CLASS=DATA

Atom		resd 1
WindowHandle    resd 1
Msg		resd 6

Instance	resd 1
CommandLine	resd 1  

FontStandard    dd 10
                resd 6
                db "MS sans Serif",0
                
hFontStandard   resd 1
ClassName	db "WindowClass01",0
WindowName	db "Exemple de graphisme", 0

mystruc		resd 16
couleurbrosse	dd 0x000000ff		;rouge
hbrosse		resd 1
hbrosseanc	resd 1
couleurpen	dd 0x00ff0000		;bleu
largeurpen	dd 1
hpen		resd 1
hpenanc		resd 1

pi		dd 3.1415926535		;nota il est possible d'utiliser l'instruction fldpi qui charge cette constante
f		dd 256.			;le point signifie virgule flottante
g		dd 200.

x		resd 1
y		resd 1
texte		db "y=sin(x)"
var		resd 1
xo		dd 200.
yo		dd 384.

Conclusion :


Ce type de code pourra être étoffé pour intégrer les possibilités de la DialogBox (saisies au clavier etc).

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.