ATOUTFOX
COMMUNAUTÉ FRANCOPHONE DES PROFESSIONNELS FOXPRO
Visual FoxPro : le développement durable

Dessin d'un rectangle de sélection (focus rect)   



L'auteur

Robert Plagnard
France France
Membre Simple
# 0000000031
enregistré le 15/10/2004

http://www.ingelog.fr
PLAGNARD Robert
75015 PARIS
de la société IngéLog
Fiche personnelle


Note des membres
pas de note

Contributions > 05 - API et appels systèmes

Dessin d'un rectangle de sélection (focus rect)
# 0000000408
ajouté le 27/02/2007 18:53:55 et modifié le 03/03/2007
consulté 9077 fois
Niveau initié

Version(s) Foxpro :
VFP 9.0
VFP 8.0
VFP 7.0
VFP 6.0
VFP 5.0
VFP 3.0

Description

La fonction DrawFocusRect de l'API windows dessine un rectangle de sélection en XOR avec le fond d'un contexe de périphérique.

Un rectangle est une structure (au sens du C) comportant quatre entiers : (left, top, right, bottom). Malheureusement VFP ne connait pas les structures. C'est la raison pour laquelle j’utilise une string pour passer le rectangle à la fonction DrawFocusRect. Mais c'est finalement très simple avec la fonction Rect présentée.

"en XOR avec le fond" cela veut dire en "ou exclusif" avec le fond. L'intéret du "ou exclusif" est qu'il possède la propriété remarquable suivante : Quel que soit les entiers f et x on a toujours (f XOR x) XOR x = f.
En d'autres termes si on dessine deux fois la même chose (x) en XOR sur le fond (f) on restitue le fond d'origine.

Un contexte de périphérique (device context) est une surface sur laquelle on peut dessiner. Il est fourni par Windows. Pourquoi ce nom barbare? Et bien, c'est le même type d'objet que l'on utilise pour une partie d'écran ou une imprimante.

La fonction GetWindowDC de l'API window permet de demander à Windows une référence (handle) vers le contexte de périphérique d'une fenêtre identifiée par son hWnd. Or les objets descendant de form ont la propriété hWnd qui va bien. Mais quand on exécute hDC = GetWindowDC( thisform.hWnd ) on obtient une zone à dessiner qui comprend toute la fenêtre, y compris la barre de titre, les bordures, etc.. Pour pouvoir dessiner dans le même repère de coordonnées que FoxPro, il faut faire une petite translation pour se retrouver dans ce que l'on appelle la zone cliente de la fenêtre. C'est là que la fonction GetSystemMetrics intervient.

La fonction GetSystemMetrics donne des informations sur un certaines caractéristiques graphiques du genre "hauteur de la barre de titre", "hauteur d'un menu", "largeur de la bordure client", etc... Avec elle on peut retrouver les coordonnées de l'origine de la zone cliente dans le contexte de la forme. Il y a pas loin d’une petite centaine de valeurs récupérables. Je n'en utilise que 4.

Lancez le programme ci-dessous

A suivre ...

Code source :
*/* FocusRect.prg
*   Using DrawFocusRect API function
*   Run this prg
*   Robert Plagnard feb 25, 2007

* paramètre à passer à GetSysMetrics   pour obtenir
#define SM_CYCAPTION            4   && hauteur de la barre de titre
#define SM_CXSIZEFRAME         32   && largeur de la bordure verticale
#define SM_CYSIZEFRAME         33   && hauteur de la bordure horizontale
#define SM_CYMENU              15   && hauteur d’un menu

   declare integer DrawFocusRect    in win32api integerstring @
   declare integer GetWindowDC      in win32api integer
   declare integer ReleaseDC        in win32api integerinteger
   declare integer GetSystemMetrics in win32api integer

   public gf

   gf = CreateObject"CForm1" )

   gf.Show

define class CForm1 as Form

   caption = "Click on the form"

   hidden nXClientOrigin   && X Origin of client zone in window
   hidden nYClientOrigin   && Y Origin of client zone in window

   procedure Init( lMenu )
      this.nXClientOrigin = GetSystemMetrics( SM_CXSIZEFRAME )   && API calls
      this.nYClientOrigin = GetSystemMetrics( SM_CYSIZEFRAME )+;
                            GetSystemMetrics( SM_CYCAPTION   )
      if m.lMenu
         this.nYClientOrigin = this.nYClientOrigin + GetSystemMetrics( SM_CYMENU )
      endif
   endproc

   procedure MouseDown( nButton, nShift, nXCoord, nYCoord )
      local R      && Rectangle
      local hDC    && handle of device context
      R = Rect( m.nXCoord + this.nXClientOrigin      , ;
                m.nYCoord + this.nYClientOrigin      , ;
                m.nXCoord + this.nXClientOrigin + 30 + Int( 150*rand() ), ;
                m.nYCoord + this.nYClientOrigin + 20 + Int(  80*rand() ) )
      hdc = GetWindowDc( thisform.HWnd )   && API call
      DrawFocusRect(m.hdc,@R)              && API call*
      ReleaseDC( thisform.HWnd, m.hDC )
   endproc

enddefine

function Rectlefttoprightbottom ) as String
   return BinToC(m.left,'4RS')+BinToC(m.top'4RS')+BinToC(m.right'4RS')+BinToC(m.bottom'4RS')
endfunc

Commentaires
le 02/03/2007, Gregory Adam a écrit :
Robert,

Apres DrawFocusRect(), il serait bien de mettre
= ReleaseDC(thisform.HWnd, m.hdc)

&& declare integer ReleaseDC in user32 integer, integer

le 02/03/2007, FredA a écrit :
Bonjour.
En utilisant GetDC au lieu de GetWindowDC on a acces directement à la zone client de la fenêtre...

le 02/03/2007, Robert Plagnard a écrit :
Vous avez parfaitement raison tous les deux. Il faut absolument libérer le device context, et puis GetDC, c'est évident. Merci.
le 06/03/2007, Robert Plagnard a écrit :
Finalement, GetDC n'est pas si évident que ça, car ca ne marche pas dans tous les cas. En particulier si ShowWindow = 2 (top-level). Dans ce cas il y a 2 fenêtres. Ma solution avec GetWindowDC marche dans tous les cas. GetDC aussi mais là il faut utiliser la formule magique (ou lire la doc!) et mettre :
hDC = GetDC( sys( 2327, sys( 2325, sys( 2326, thisform.HWnd ))))
Et ce qui est beau, c'est que cette formule est correcte pour toutes les valeurs de ShowWIndow!

le 06/03/2007, FredA a écrit :
bravo

www.atoutfox.org - Site de la Communauté Francophone des Professionnels FoxPro - v3.4.0 - © 2004-2024.
Cette page est générée par un composant COM+ développé en Visual FoxPro 9.0-SP2-HF3