SVP une explication sur TStringGrid

Résolu
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009 - 8 mai 2007 à 10:36
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre 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+

16 réponses

jelume Messages postés 120 Date d'inscription mardi 3 avril 2007 Statut Membre Dernière intervention 15 novembre 2007 1
8 mai 2007 à 11:49
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
3
jelume Messages postés 120 Date d'inscription mardi 3 avril 2007 Statut Membre Dernière intervention 15 novembre 2007 1
8 mai 2007 à 11:01
bjr

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

SG.CellRect(7, ARow);

J-L
0
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009
8 mai 2007 à 11:30
Excuses-moi c'est une erreur de frappe c'est bien CellRect(3,ARow)
A+
0
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009
8 mai 2007 à 12:31
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+
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jelume Messages postés 120 Date d'inscription mardi 3 avril 2007 Statut Membre Dernière intervention 15 novembre 2007 1
8 mai 2007 à 12:51
http://www.hoerstemeier.com/grid.htm



il parait que celle ci est pas mal.
0
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 2
8 mai 2007 à 12:58
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...
0
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009
8 mai 2007 à 13:23
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+
0
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 2
8 mai 2007 à 13:39
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
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
8 mai 2007 à 13:43
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.
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
8 mai 2007 à 13:45
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.
0
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 2
8 mai 2007 à 14:25
Au moins, avec tout ça, il est incollable sur le TStringGrid !!!
0
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009
8 mai 2007 à 17:27
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+
0
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009
8 mai 2007 à 20:53
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+
0
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 2
8 mai 2007 à 21:02
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
0
gebu34 Messages postés 118 Date d'inscription samedi 9 décembre 2006 Statut Membre Dernière intervention 17 novembre 2009
9 mai 2007 à 11:20
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+
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
9 mai 2007 à 12:47
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.
0
Rejoignez-nous