gebu34
Messages postés118Date d'inscriptionsamedi 9 décembre 2006StatutMembreDernière intervention17 novembre 2009
-
8 mai 2007 à 10:36
cs_Loda
Messages postés814Date d'inscriptionvendredi 3 novembre 2000StatutMembreDernière intervention30 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+
jelume
Messages postés120Date d'inscriptionmardi 3 avril 2007StatutMembreDernière intervention15 novembre 20071 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 .
gebu34
Messages postés118Date d'inscriptionsamedi 9 décembre 2006StatutMembreDernière intervention17 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+
Vous n’avez pas trouvé la réponse que vous recherchez ?
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20082 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...
gebu34
Messages postés118Date d'inscriptionsamedi 9 décembre 2006StatutMembreDernière intervention17 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+
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20082 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
cs_Loda
Messages postés814Date d'inscriptionvendredi 3 novembre 2000StatutMembreDernière intervention30 juillet 20093 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.
gebu34
Messages postés118Date d'inscriptionsamedi 9 décembre 2006StatutMembreDernière intervention17 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+
gebu34
Messages postés118Date d'inscriptionsamedi 9 décembre 2006StatutMembreDernière intervention17 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+
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20082 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 !
gebu34
Messages postés118Date d'inscriptionsamedi 9 décembre 2006StatutMembreDernière intervention17 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+
cs_Loda
Messages postés814Date d'inscriptionvendredi 3 novembre 2000StatutMembreDernière intervention30 juillet 20093 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.