SVP une explication sur TStringGrid [Résolu]

gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 8 mai 2007 à 10:36 - Dernière réponse : cs_Loda
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
- 9 mai 2007 à 12:47
Bonjour à tous,
J'aimerais une explication sur la fonction OnDrawCell.
Je pars sur le principe que DrawCell balaye toutes les cellules.
Je pars par exemple avec un TStringGrid à 3 colonnes.
Je veux que la cellule cliquée de la colonne 0 soit en clNavy pour le fond et clWhite pour le texte.

procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin  if (ACol 0) and (ARow 3) then
    begin
      SG1.Canvas.Brush.Color := clNavy;
      SG1.Canvas.FillRect(rect);
      SG1.Canvas.Font.Color := clWhite;
      SG1.Canvas.TextOut(Rect.Left,Rect.Top,SG1.Cells[1,Arow]);
    end;
end;

Celà fonctionne pas de problème...
Maintenant je veux en même temps que la cellule de la 4ème colonne soit jaune..

procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  Rct: TRect;
begin  if (ACol 0) and (ARow 3) then
    begin
      SG1.Canvas.Brush.Color := clNavy;
      SG1.Canvas.FillRect(rect);
      SG1.Canvas.Font.Color := clWhite;
      SG1.Canvas.TextOut(Rect.Left,Rect.Top,SG1.Cells[1,Arow]);
      Rct := SG1.CellRect(7, ARow);
      SG1.Canvas.Brush.Color := clYellow;
      SG1.Canvas.FillRect(Rct);
    end;
end;

Malheureusement la cellule de la 4ème colonne ne bouge pas.
Je récupère pourtant le Rectangle de cette cellule avec CellRect...
Merci de vos efforts
A+
Afficher la suite 

Votre réponse

16 réponses

Meilleure réponse
jelume
Messages postés
122
Date d'inscription
mardi 3 avril 2007
Dernière intervention
15 novembre 2007
- 8 mai 2007 à 11:49
3
Merci
ok

en fait, ton problème n'est pas si simple.
D'abord pour connaitre la cellule cliquée, il faut utiliser le paramètre state
if (ACol = 0) and (gdselected in State) then

Ensuite, au moment de redessiner la première cellule, tu redessines celle de la troisieme colonne.
Mais pourque ca fonctionne il faudrait faire un refresh de la grille.
Sauf qu'au moment, du refresh, le on DrawCell n'a plus les memes parametres.
Du coup, ca reprend les parametres par défaut, donc fond blanc.

Je ne vois pas de solution simple pour ton problème.

Mais certaines grilles gratuites font ça très bien. Tu devrais peut-être les utiliser .

J-L

Merci jelume 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 86 internautes ce mois-ci

Commenter la réponse de jelume
jelume
Messages postés
122
Date d'inscription
mardi 3 avril 2007
Dernière intervention
15 novembre 2007
- 8 mai 2007 à 11:01
0
Merci
bjr

Si ta grille a 3 colonnes, pourquoi chercher le rect de la colonne 7 ?

SG.CellRect(7, ARow);

J-L
Commenter la réponse de jelume
gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 8 mai 2007 à 11:30
0
Merci
Excuses-moi c'est une erreur de frappe c'est bien CellRect(3,ARow)
A+
Commenter la réponse de gebu34
gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 8 mai 2007 à 12:31
0
Merci
En fait tu as répondu en partie à ma question, car lorsque je transforme la cellule 0 et 3 le DrawCell repaint les cellules non sélectionnées de la grille. Si on fait un ralenti, je suis sur que pendant un cours instant on voit du jaune dans la cellule 3....
Je vais faire un tour sur le net pour chercher une grille adaptée..
Merci quand même..
A+
Commenter la réponse de gebu34
jelume
Messages postés
122
Date d'inscription
mardi 3 avril 2007
Dernière intervention
15 novembre 2007
- 8 mai 2007 à 12:51
0
Merci
http://www.hoerstemeier.com/grid.htm



il parait que celle ci est pas mal.
Commenter la réponse de jelume
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 8 mai 2007 à 12:58
0
Merci
Mais tu peux très bien tout faire avec le TStringGrid ! D'ailleurs, dans ta source, tu le dis très bien: le TStringGrid sert à tout !

Juste un détail: dans le OnDrawCell, tu ne dois PAS redessiner d'autre cellules que celles précisée dans les paramètres d'appel de l'évènement. En plus, je crois bien que le Canvas est verrouillé pour ignorer tout ce qui dépasse...
Commenter la réponse de florenth
gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 8 mai 2007 à 13:23
0
Merci
Salut florenth,
c'est vrai que j'aime bien le StrigGrid car il est malaxable.
Petite question, quand tu clique sur une cellule, le canvas s'applique à toute la grille ou simplement à la cellule?
Pour interdire de redessiner les cellules peut-on se contenter d'un
if (gdselected in State) then
A+
Commenter la réponse de gebu34
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 8 mai 2007 à 13:39
0
Merci
Le Canvas est celui du StringGrid: il comprend toutes les cellules, les colonnes et lignes fixes, etc...

En fait, lorsque le TStringGrid a besoin de se redessiner, il appelle OnDrawCell autant de fois qu'il y a de cellules.

Si tu ne veux personnaliser le dessin que de la cellule sélectionnée, il faut que dans l'évenement, tu ne fasse ton dessin QUE si "(gdSelected in State) = True". Si tu veux mettre en rouge la cellule de la première colonne en fasse de la cellule sélectionnée, tu fais une condition supplémentaire pour dessiner la cellule telle que "(ACol 0) and (ARow SG1.Row) = True".

Tu obtiendras donc qqch du genre :
<hr size="2" width="100%" /> procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  if odSelected in State then
  begin
    { Dessin de la cellule sélectionnée }
  end;
  if (ACol 0) <gras>and (ARow</gras> SG1.Row) then
  begin
    { Dessin de la cellule de la première colonne en face de la cellule sélectionnée }
  end;
 
  { Et ainsi de suite pour tous les cas spéciaux que tu dois traiter ... }
end;
<hr size ="2" width="100%" />
Mais dans tous les cas, tu ne dessines que dans le Rect que l'on te donne...

A+
Flo

PS: n'hésites pas à compléter ta question et à poster un bout de code si tu sens que c'est mieux pour comprendre
Commenter la réponse de florenth
cs_Loda
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
- 8 mai 2007 à 13:43
0
Merci
salut,

Florenth a raison. Le onDrawCell est appelé pour UNE cellule et tu ne doit dessiner que cela !

si tu veux dessiner la cellule 4 en jaune fait ceci:

procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  Rct: TRect;
begin  if (ACol 0) and (ARow 3) then
    begin
     // on dessine une cellule
      SG1.Canvas.Brush.Color := clNavy;
      SG1.Canvas.FillRect(rect);
      SG1.Canvas.Font.Color := clWhite;
      SG1.Canvas.TextOut(Rect.Left,Rect.Top,SG1.Cells[1,Arow]);
    end

else
    if (ACol 0) and (ARow 4) then begin
  //on dessine une AUTRE cellule (lors d'au autre appel)
      SG1.Canvas.Brush.Color := clYellow;

      SG1.Canvas.FillRect(Rct);
 end;

end;

Comprend que:
- le DrawCelle est appelé pour chaque cellule LORSQUE NECESSAIRE .
(donc, si tu dessine de dehors de la cell passé en param, cela serra soit ignoré soit redessiner plus tard par dessus)
- c'est la même methode qui dessine toute les cellules.
- tu peux faire des trucs genre
if aRow mod 2 = 0 then
  MaCouleurDeFond := clGray
else
  MaCouleurDeFond := clWhite
  ou
 if state = Xxxx then MaCouleurDeFond := Yyyy

"le canvas s'applique à toute la grille ou simplement à la cellule?"
le canvas ne s'applique pas! Le canvas est la zone de dessin de (toute) ta grille.MAIS tu ne doit dessiner que dans les limites de "rect".

Pour resoudre un problème similaire (cad avoir un dessin custom pour chaque cell), j'ai utiliser un tableau de TCellProperties avec les info specifique a chaque cell (personal state, changement de couleur temporisé, ev. ajout de bmp, ....). Puis tu lit le tableau pour connaitre la couleur de fond, la couleur de la police, ....
Rappelons que tu peux associer un Tobject a chaque cellule.

A+

Loda
<hr size ="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda
cs_Loda
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
- 8 mai 2007 à 13:45
0
Merci
on s'est croisé !

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 8 mai 2007 à 14:25
0
Merci
Au moins, avec tout ça, il est incollable sur le TStringGrid !!!
Commenter la réponse de florenth
gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 8 mai 2007 à 17:27
0
Merci
Merci à tous pour toutes ces explications...
Je me mets au clavier pour appliquer tout ça.....
Si je trouve un truc de ouf, promis j'en fais part...
Quand même TStringGrid est un compo terrifiant....
Allez A+
Commenter la réponse de gebu34
gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 8 mai 2007 à 20:53
0
Merci
J'en remets une couche, car j'aime bien comprendre....
Si je clique sur une cellule de la colonne 0 elle passe en clNavy, donc tout baigne. Maintenant si je clique sur une autre colonne, la cellule précédemment cliqué s'efface et passe à l'état normal (comme les autres), donc à chaque Click, la grille entière se redessine, Yes or Not ? (sauf celles qui sont définis dans DrawCell )
A+
Commenter la réponse de gebu34
florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 8 mai 2007 à 21:02
0
Merci
Alors, pour te répondre, je suis allé voir dans le code source de la VCL.
Donc, d'après l'unité Grids.pas, lignes 2869-2870, seules deux cellules sont redessinées lorsque tu cliques sur une cellule:
- Celle qui était sélectionnée (s'il y en avait).
- Celle qui vient d'être sélectionnée (s'il y en a).

Tout une histoire d'optimisation...
Mais tu peux forcer la mise en appelant TStringGrid.Invalidate pour tout redessiner si les besoins se font sentir...

En tout cas, le mécanisme est très très complexe...
Mais peu importe, tout est faisable !

++
Flo
Commenter la réponse de florenth
gebu34
Messages postés
119
Date d'inscription
samedi 9 décembre 2006
Dernière intervention
17 novembre 2009
- 9 mai 2007 à 11:20
0
Merci
C'est très interressant ce que tu dis, car effectivement il intervient sur l'avant dernière cellule cliquée pour la repasser à l'état normal. Ce qui revient à dire que dans la procedure DrawCell, tu ne peux intervenir QUE sur la cellule cliquée (au moyen de Rect) sauf si tu invoque Invalidate à chaque action ou Click. Pour chaque appel de cellule, If ACol=0 and ARow=1 then , seul le Rect est urilisé, l'appel de CellRect(3,1) ne sert à rien puisque de toute façon c'est dessiner dans Rect. Il faut un appel If then pour chaque cellule dessinée, et Invalidate dans SelectCell. Celà fonctionne et en cliquant sur une autre cellule, alors les cellules dessinées s'efface. (mais pour le dernier point je n'ai pas tout compris et je rejoins le "très  très complexe" de florenth). En conclusion, toujours sans rajouter de compo, on peut encore personnaliser TStringGrid, mais je pense qu'à force il va falloir faire soit un tuto, soit des procs standard......
Allez A+
Commenter la réponse de gebu34
cs_Loda
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
- 9 mai 2007 à 12:47
0
Merci
re,

" on peut encore personnaliser TStringGrid, mais je pense qu'à force il va falloir faire soit un tuto, soit des procs standard"

fait un compo perso ! dérive le de TstringGrid ou un parent plus haut. a toi de voir. Puis crée ta grid dynamiquement (comme ça t'as pas a installer un packet/compo)

bon code,

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda

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.