Gestion d'une fenêtre
avec un redrawing automatique

En GFA-Basic sous Windows
Page crée le 17-01-2003


Page d'accueil

Comment gérer une fenêtre avec un redrawing automatique ?
Réponse :
Utiliser la commande CB pour signaler l'appel à une procédure de redraw .
Dans cette procédure de redraw on va lui demander simplement d'afficher un Bitmap .
Cette Bitmap pourra être modifiée dans n'importe quelle autre partie du programme avec la méthode selectobject .
NB : Il y a d'autres méthodes que je développerais bientôt sur cette page .


En concret :

On ouvre une fenêtre :
OPENW #1,0,0,200,200,0

Par la même occasion On peut la mettre au premier plan :
~BringWindowToTop(WIN(1))

On crée un bitmap de la taille de la fenêtre (on peut faire une bitmap plus grande aussi...mais c'est pour l'exemple) :
GET 0,0,200,200,ScrBmp%

Puis on signale à windows que pour rafraichir l'affichage il faudra utiliser une procédure (on peut l'appeler commen on veut) :
CB WIN(1),WM_PAINT,Refresh()

La procédure refresh qui à 4 paramètres, je sais pas pourquoi mais c'est comme ça, et dans laquelle on utilise BEGINPAINT et ENDPAINT . On peut se passer de BEGINPAINT et ENDPAINT mais l'affichage est alors un peu nazouillard :
PROCEDURE Refresh(h&,m&,w&,l%)
 LOCAL
ps$
 
BEGINPAINT h&,ps$
 
PUT 0,0,ScrBmp%
 
ENDPAINT h&,ps$
RETURN

Après si on veut afficher quelque chose on utilise 2 procédures : Avant_Aff et Apres_Aff
PROCEDURE Avant_Aff
 
DCDLG% = GetDC(_DC(1))
 
BufMemDc% = MEMDC(DCDLG%)
 ~SelectObject(
BufMemDc%,ScrBmp%)
 SETDC
BufMemDc%
RETURN
PROCEDURE
Apres_Aff
 
FREEDC BufMemDc%
 
SETDC _DC(1)
 PUT 0,0,
ScrBmp%
 
~ReleaseDC(_DC(1),DCDLG%)
RETURN

Exemple d'affichage d'un cercle avec une ligne au milieur :
Avant_Aff
CIRCLE 100,100,50
LINE 50,100,150,100
Apres_Aff

Et bien sûr on oubliera pas de faire un PEEKEVENT de temps en temps pour que ca dialogue avec windows !

Et maintenant voici 2 listings de démonstration !
Neige influencée par les mouvements de la souris
En GFA-Basic sous Windows
scrx% = _X / 1,scry% = _Y / 1
OPENW #1,0,0,
scrx%,scry%,&x1110000        ' Nouvelle fenëtre avec attribut Clore et Minimiser
TITLEW #1,"Ouah c'est rafraichissant !"
~BringWindowToTop(WIN(1))                 ' Fenëtre au premier plan
GET 0,0,scrx%,scry%,ScrBmp%               ' On crêe une bitmap de la taille de l'êcran
CB WIN(1),WM_PAINT,Refresh()              ' Windows rafraichira l'affichage en utilisant la procêdure Refresh()
NF% = 255                                 ' NF% = Nombre de flocons
DIM x(NF%),y(NF%),v(NF%)                  ' x() et y() sont les coordonnêes et v() la vitesse des flocons
flocons_init                              ' On dêfinit un tas de flocons
MOUSE mx%,my%,mk%                         ' On sauvegarde la position de la souris
v1 = TIMER                                ' On sauvegarde l'heure ou dêbute la boucle principale
DO
 PEEKEVENT                              
' Windows dialogue avec le programme
 
EXIT IF MENU(1) = 4                     ' Bouton Clore de la fenëtre -> On sort du programme
 
mx1% = mx%,my1% = my%                   ' On sauvegarde l'ancienne position de la souris
 
MOUSE mx%,my%,mk%                       ' Et on prend la nouvelle
 
IF mx% <> mx1% THEN  ndx = MIN(10,MAX(-10,mx% - mx1%))        ' Si position x change -> maj du mouvement gênêral en x
 
IF my% <> my1% THEN ndy = MIN(10,MAX(-10,my% - my1%))         ' Idem en y
 
ndx = ndx / 1.0001,ndy = ndy / 1.0001                         ' Transition en douceur
 
dx2 = dx2 + (ndx - dx2) / 1000,dy2 = dy2 + (ndy - dy2) / 1000 ' grãce au diffêrences divisêes
 
dx = dx + (dx2 - dx) / 100,dy = dy + (dy2 - dy) / 100         '
 
IF TIMER - v1 > 10                      ' Tout les 1 centiémes de secondes
   
v1 = TIMER                            '
   
Avant_Aff                             ' Affichage en arriére plan avec DC compatible sur bitmap ScrBmp%
   
RGBCOLOR 0                            ' Couleur : noir
   
DEFFILL 0                             ' Si omis le pbox n'est pas rempli avec la couleur noir
   
PBOX 0,0,scrx%,scry%                  ' Affichage d'une boite pleine de couleur noire
   
flocons_moving                        ' Calcul des nouvelles coordonnêes et affichage des flocons
   
Apres_Aff                             ' On repasse en _DC(1) et on affiche le bitmap
 
ENDIF
LOOP
FREEBMP
ScrBmp%                           ' On Elimine le bitmap de la mêmoire (important)
CLOSEW #1
PROCEDURE
flocons_init
 
LOCAL p%
 
FOR p% = 1 TO NF%
   x
(p%) = RND * scrx%,y(p%) = RND * scry%
   v
(p%) = 0.1 + 1 - SIN((p% / NF%) * PI)
 NEXT
p%
RETURN
PROCEDURE
flocons_moving
 LOCAL p%
 a
= a + 0.005 + (a > 2 * PI) * 2 * PI
 FOR
p% = 1 TO NF%
   y
(p%) = y(p%) + v(p%) + dy * v(p%)
   
x(p%) = x(p%) + SIN(a + p%) * v(p%) + dx * v(p%)
   IF
x(p%) > scrx%
     x
(p%) = x(p%) - scrx%
   
ELSE IF x(p%) < 0
     
x(p%) = x(p%) + scrx%
   
ENDIF
   IF
y(p%) < 0 THEN y(p%) = y(p%) + scry%
   
IF y(p%) > scry%
     x
(p%) = RND * scrx%,y(p%) = 0
     
v(p%) = 0.1 + 1 - SIN((p% / NF%) * PI)
   ENDIF
   RGBCOLOR RGB(
p%,p%,p%)
   PCIRCLE
x(p%),y(p%),v(p%) * 3
 NEXT
p%
RETURN
PROCEDURE
Refresh(h&,m&,w&,l%)
 LOCAL
x%,ps$
 
BEGINPAINT h&,ps$
 
PUT x%,0,ScrBmp%
 
ENDPAINT h&,ps$
RETURN
PROCEDURE
Avant_Aff
 
DCDLG% = GetDC(_DC(1))
 
BufMemDc% = MEMDC(DCDLG%)
 ~SelectObject(
BufMemDc%,ScrBmp%)
 SETDC
BufMemDc%
RETURN
PROCEDURE
Apres_Aff
 
FREEDC BufMemDc%
 
SETDC _DC(1)
 PUT 0,0,
ScrBmp%
 
~ReleaseDC(_DC(1),DCDLG%)
RETURN

Exemple tout bidon mais ca permet de comprendre.
OPENW #1,_X/2-100,_Y/2-100,200,200,&x1110000
TITLEW #1,
"C'est ti pas beau un cercle ?"
~BringWindowToTop(WIN(1))
GET 0,0,200,200,
ScrBmp%
CB WIN(1),WM_PAINT,Refresh()
v1=TIMER
DO
 PEEKEVENT
 EXIT IF MENU(1)=4
 IF TIMER-
v1>150 ' tout les 15 10émes de seconde on affiche un truc
   
Avant_Aff
   
RGBCOLOR RGB(RND*255,RND*255,RND*255)
   CIRCLE RND*200,RND*200,10+RND*50
   
Apres_Aff
   
v1=TIMER
 ENDIF
LOOP
FREEBMP
ScrBmp%
CLOSEW #1
PROCEDURE
Refresh(h&,m&,w&,l%)
 LOCAL
x%,ps$
 
BEGINPAINT h&,ps$
 
PUT x%,0,ScrBmp%
 
ENDPAINT h&,ps$
RETURN
PROCEDURE
Avant_Aff
 
DCDLG% = GetDC(_DC(1))
 
BufMemDc% = MEMDC(DCDLG%)
 ~SelectObject(
BufMemDc%,ScrBmp%)
 SETDC
BufMemDc%
RETURN
PROCEDURE
Apres_Aff
 
FREEDC BufMemDc%
 
SETDC _DC(1)
 PUT 0,0,
ScrBmp%
 
~ReleaseDC(_DC(1),DCDLG%)
RETURN