IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Interface > Composants > Les grilles
        Comment personnaliser un ensemble de cellules sans modifier toute la grille dans un TStringGrid ?
        Comment écrire sur plusieurs lignes dans une cellule d'un TStringGrid?
        Comment gérer la roulette de la souris sur un TDBGrid ?
        Comment supprimer une ligne ou une colonne dans un TStringGrid ?
        Comment simuler une multiselection dans un TStringGrid ?
        Comment empêcher l'édition d'une cellule spécifique d'un TStringGrid ?
        Comment déplacer une ligne ou une colonne dans un TStringGrid ?
        Comment avoir des retours chariot dans une cellule d'un TStringGrid ?
        Comment mettre une image en fond d'un TStringGrid ?
        Comment centrer le texte d'un TStringGrid ?
        Comment écrire le texte d'une cellule d'un TStringGrid sur plusieurs lignes ?



Comment personnaliser un ensemble de cellules sans modifier toute la grille dans un TStringGrid ?
Créé le 01/09/2004[haut]
auteur : Alacazam
Surchargeons la méthode OnDrawCell : cette méthode est appelée pour chaque cellule devant être (re)dessinée.
Attention : Les attributs Col, Row, Rect et State concernent donc la cellule en train d'être dessinée, et non la cellule courante (que vous sélectionnez par exemple avec votre souris).

TColor CLTitre = clBtnFace, CLFond = clYellow, CLSelection = clRed; // Vos couleurs personnalisées.
AnsiString s = StringGrid1->Cells[ACol][ARow]; // Texte de la cellule.
if (ACol < StringGrid1->FixedCols || ARow < StringGrid1->FixedRows) { // Concerne les titres des lignes et des colonnes.
StringGrid1->Canvas->Brush->Color = CLTitre;
StringGrid1->Canvas->FillRect(Rect); // On dessine le fond de la cellule.
StringGrid1->Canvas->Font->Style = StringGrid1->Canvas->Font->Style << fsBold; // On met les titres en gras.
// On réaffiche le texte par dessus, car le FillRect l'a effacé.
StringGrid1->Canvas->TextRect(
      Rect,
      (Rect.Right + Rect.Left - StringGrid1->Canvas->TextWidth(s)) / 2,
      (Rect.Top + Rect.Bottom - StringGrid1->Canvas->TextHeight(s)) / 2,
      s);
// Le premier argument est le rectangle de rognage, les deux suivants permettent de centrer le texte dans la cellule.
}
else if (State.Contains(gdSelected)) { // Concerne la(les) cellule(s) sélectionnée(s).
StringGrid1->Canvas->Brush->Color = CLSelection;
StringGrid1->Canvas->FillRect(Rect);
StringGrid1->Canvas->Font->Color = clWhite; // Le texte est écrit en blanc.
StringGrid1->Canvas->TextRect(Rect, Rect.Left +1, Rect.Top + 1, s); // Ici texte justifié à gauche.
}
else {
StringGrid1->Canvas->Brush->Color = CLFond;
StringGrid1->Canvas->FillRect(Rect);
StringGrid1->Canvas->TextRect(Rect, Rect.Left +1, Rect.Top + 1, s);
}
N.B. Pour centrer un texte dans un rectangle, on égale les coordonnées du centre du rectangle et celles du centre du texte.


Comment écrire sur plusieurs lignes dans une cellule d'un TStringGrid?
Créé le 01/09/2004[haut]
auteur : Alacazam
Le but est donc tout simplement d'afficher le texte de votre cellule sur plusieurs lignes, s'il est trop long par exemple, ou simplement pour améliorer la présentation de vos données.
Le principe :
- Utiliser un TMemo invisible de la largeur de la case, et le laisser découper votre texte (propriété WordWrap à true).
- Récupérer les n lignes du TMemo une par une, et les afficher dans des rectangles n fois plus petits (en hauteur).

N.B. Si vous ne maitrisez pas trop le OnDrawCell ou l'utilisation du TCanvas de la grille, je vous conseille de lire d'abord faq Comment personnaliser un ensemble de cellules sans modifier toute la grille dans un TStringGrid ?.

#include <math.hpp>
// A placer dans l'évènement OnDrawCell de votre TStringGrid.
TMemo *Memo = new TMemo(this);
Memo->Visible = false;
Memo->Parent = this;
Memo->Lines->Text = StringGrid1->Cells[ACol][ARow];
Memo->Width = StringGrid1->ColWidths[ACol];
int Cell_Height = Rect.Bottom - Rect.Top, Ligne_Nbr = Memo->Lines->Count;

// Cette ligne  permet d'éviter le chevauchement des lignes si le texte est vraiment trop long pour la case.
Ligne_Nbr = Min(Ligne_Nbr, (Rect.Bottom - Rect.Top) / StringGrid1->Canvas->TextHeight(" ") + 1);

for (int i = 0 ; i < Ligne_Nbr ; i++) 
{
   TRect R = Rect;
   AnsiString Text_i = Memo->Lines->Strings[i];
   R.Top = Rect.Top + i * Cell_Height / Ligne_Nbr;
   R.Bottom = Rect.Top + (i + 1) * Cell_Height / Ligne_Nbr;
   // Texte justifié "centré"
   StringGrid1->Canvas->TextRect(
         R,
         (R.Right + R.Left - StringGrid1->Canvas->TextWidth(Text_i)) / 2,
 (R.Top + R.Bottom - StringGrid1->Canvas->TextHeight(Text_i)) / 2,
 Text_i);
}
delete Memo;
Signalons que si vous souhaitez forcer un retour à la ligne après un mot, vous n'avez qu'à le faire suivre de "\n", qui sera traité correctement par le TMemo.

lien : faq Comment personnaliser un ensemble de cellules sans modifier toute la grille dans un TStringGrid ?

Comment gérer la roulette de la souris sur un TDBGrid ?
Créé le 21/06/2006[haut]
auteur : Nono40
La roulette n'est pas gérée correctement par défaut dans le composant TDBGrid. Pour qu'elle soit prise en compte il faut suivre la méthode suivante, elle est basée sur la dérivation de la méthode WindowProc de la grille afin de gérer le message WM_MOUSEWHEEL.

Dans le header de la fiche, ajouter :

private:   // Déclarations de l'utilisateur
   TWndMethod OldWindowProc;
   void __fastcall DBGridNewWindowProc(TMessage &Msg);
Puis, dans le corps du gestionnaire d'évènements OnCreate (dans le .cpp) :

   OldWindowProc = DBGrid1->WindowProc;
   DBGrid1->WindowProc = DBGridNewWindowProc;
Enfin, dans le .cpp :

void __fastcall TForm1::DBGridNewWindowProc(TMessage &Msg)
{
   if (Msg.Msg == WM_MOUSEWHEEL)
   {
      if (DBGrid1->DataSource->DataSet->Active)
      {
         if (short(Msg.WParamHi) < 0)
         {
            DBGrid1->DataSource->DataSet->Next();
         }
         else
         {
            DBGrid1->DataSource->DataSet->Prior();
         }
      }
      return;
   }
   OldWindowProc(Msg);
}
Remarque : Le code ci-dessus suppose que DBGrid1->DataSource et DBGrid1->DataSource->DataSet soient assignés. Si on se trouve dans un contexte où l'on n'est pas sûr qu'ils le soient, il faut le vérifier.


Comment supprimer une ligne ou une colonne dans un TStringGrid ?
Mise à jour le 22/11/2010[haut]
auteurs : pottiez, blondelle, LadyWasky
Il suffit de rendre publiques les méthodes DeleteRow et DeleteColumn de la classe TCustomGrid dont hérite la classe TStringGrid à travers le transtypage de cette dernière en une classe dérivée déclarée dans la même unité :

class TPublicStringGrid: public TCustomGrid
{
    public:
        using TCustomGrid::DeleteRow;
        using TCustomGrid::DeleteColumn;
};
// supprime la ligne n°2 (donc la troisième ligne, la première étant la ligne n°0) :
((TPublicStringGrid*)StringGrid1)->DeleteRow(2);
// supprime la deuxième colonne colonne n°1), la première étant la colonne n°0) :
((TPublicStringGrid*)StringGrid1)->DeleteColumn(1);

Comment simuler une multiselection dans un TStringGrid ?
Créé le 06/12/2006[haut]
auteurs : Sunchaser, MiGoN
Pour simuler la sélection multiple dans cet objet, il faudra intercepter des évènements clavier et ainsi il faut que la propriété KeyPreview de la TForm contenant la grille soit à true.
Ensuite, il faut travailler sur les évènements suivants :

  • OnClick
  • OnDrawCell
  • OnKeyDown
  • OnKeyUp
  • OnMouseMove
  • OnCreate
  • OnClose
Dans le .h

Private:     
TStringGrid *pGrille;
TStringList *pListeIndex;
bool MultiSelect;
Dans le .cpp

void __fastcall TForm1::FormCreate(TObject *Sender)
{
MultiSelect = false;
// On met la valeur de cette variable à 'faux' afin que le comportement 
// par défaut de la grille soit 'normal' et qu'il faille appuyer sur la touche 
// 'ctrl' pour simuler la sélection multiple
}
//-----------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
// On libère la mémoire allouée à l'objet TStringList si il a été crée
    if(pListeIndex != NULL)
        delete pListeIndex;
}
Interception des évènements clavier

void __fastcall TForm1::StringGridKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
//Si la touche ctrl est enfoncée, on crée la liste pour stocker les index des lignes sélectionnées
if (Key == VK_CONTROL)
{
        MultiSelect = true;
// on teste l'existance ou non d'un objet 'StringList', ainsi on ne redéclare 
// pas inutilement des objets de ce type à chaque fois que la touche est pressée
        if (pListeIndex == NULL)
        {
                pListeIndex = new TStringList();
                // ainsi la liste est créée et elle sera persistante tant que le
                // bouton 'ctrl' est enfoncé. Cette liste va stocker les index des 
                // lignes sélectionnées en cliquant dans la stringgrid
        }
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGridKeyUp(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
// Si la touche ctrl est relachée, on vide la liste supposée contenir les index des lignes selectionnées
if (Key == VK_CONTROL)
{
        MultiSelect = false;
        if (!pListeIndex == NULL)
        {
                pListeIndex->Clear();
// la liste est vidée mais non détruite : l'objet de type 'TStringList' 
// sera libérée au moment du OnClose de la form
        }
}
}
Dessin des éléments dans la grille

void __fastcall TForm1::StringGridDrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
pGrille = (TStringGrid* )Sender;
if (!pListeIndex == NULL)
{
// Si l'index de la ligne dessinée correspond à une ligne sélectionnée, on 
// retrouve la valeur de son index dans la TStringList
        if (pListeIndex->IndexOf(ARow)!= - 1) 
        { 
        //elle est déssinée avec une couleur de fond et une fonte spécifique
        pGrille->Canvas->Brush->Color = clHighlight;
            pGrille->Canvas->Font->Color = clWhite;
            pGrille->Canvas->FillRect(Rect);
            pGrille->Canvas->TextRect(Rect, Rect.Left+2, Rect.Top+2, pGrille->Cells[ACol][ARow]);
        }
}
else
{
        pGrille->Canvas->Brush->Color = clWindow;
        pGrille->Canvas->Font->Color = clBlack;
}
}
NB : Cet évènement fonctionne quelle que soit la valeur de la propriété DefaultDraw de la grille.
Sélection d'une ligne

void __fastcall TForm1::StringGridClick(TObject *Sender)
{
pGrille = (TStringGrid* )Sender;
// on teste la valeur de 'MultiSelect' pour savoir si la touche 'ctrl' a été
// pressée
if (MultiSelect == true)
{
// on enregistre dans la TstringList l'index de la ligne selectionnée
pListeIndex->Add(pGrille->Row);
}
// on force la grille a se 'redessiner', afin de mettre a jour l'affichage
// en tenant compte des nouvelles valeurs ou des valeurs non stockées dans la TStringList
pGrille->Repaint();
}

void __fastcall TForm1::StringGridMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
pGrille = (TStringGrid* )Sender;
pGrille->SetFocus();
}
NB : Sans cet évènement, cette astuce pour simuler la multiselection ne fonctionne pas dès le premier click.


Comment empêcher l'édition d'une cellule spécifique d'un TStringGrid ?
Créé le 10/12/2007[haut]
auteur : pottiez

Pour empêcher l'édition des cellules du TStringGrid, il faut jouer sur la propriété option de celui-ci. En effet, dans les options du TStringGrid, on peut cocher l'option goEditing qui permet d'autoriser ou non l'édition du TStringGrid.
Il vous suffit alors de vérifier quelle est la cellule que l'utilisateur souhaite éditer, et autoriser ainsi cette édition ou non. Cela se fait grâce à l'évènement OnSelectCell().

Cela donne ce code (ici pour vérouiller la cellule de coordonné 1;1) :

if((ACol == 1) && (ARow == 1)){
  StringGrid1->Options >> goEditing; // ne pas rendre éditable
}else{
  StringGrid1->Options << goEditing; // rendre éditable
}

Si vous voulez vérouiller plusieurs cellules, je vous propose d'utiliser un vecteur et de vérifier chaque valeur du vecteur grâce à un boucle

int vectCoordonnee[5][2] = {{1,1},{2,5},{3,1},{1,4},{1,2}} ;
int i ;
StringGrid1->Options << goEditing; // rendre éditable
for(i=0;i<5;i++){
  if((ACol == vectCoordonnee[i][0]) && (ARow == vectCoordonnee[i][1])){
    StringGrid1->Options >> goEditing; // ne pas rendre éditable
  }
}

Comment déplacer une ligne ou une colonne dans un TStringGrid ?
Créé le 22/11/2010[haut]
auteurs : blondelle, Pedro, LadyWasky
Il suffit de rendre publiques les méthodes MoveRow et MoveColumn de la classe TCustomGrid dont hérite la classe TStringGrid à travers le transtypage de cette dernière en une classe dérivée déclarée dans la même unité :

void __fastcall TForm1::Button1Click(TObject *Sender)
{
class TPublicStringGrid: public TCustomGrid
{
    public:
        using TCustomGrid::MoveRow;
        using TCustomGrid::MoveColumn;
};
// Déplace la première ligne (Row=0) vers la seconde (Row=1)
((TPublicStringGrid*)StringGrid1)->MoveRow(0,1);
//Déplace la première colonne (Col=0) vers la seconde (Col=1)
((TPublicStringGrid*)StringGrid1)->MoveColumn(0,1);
}
Il est a noter que si les cellules vers lesquelles on déplace avec MoveRow ou MoveColumn ne sont pas vides, les valeurs seront permutées avec celles que l'on veut déplacer.


Comment avoir des retours chariot dans une cellule d'un TStringGrid ?
Créé le 22/11/2010[haut]
auteurs : blondelle, rbag
Pour cela, il faut activer l'option goAlwaysShowEditor et ajouter le code suivant dans l'événement OnKeyDown :

void __fastcall TForm1::StringGrid1KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
 if(Key == VK_RETURN)
 {
    StringGrid1->Cells[StringGrid1->Col][StringGrid1->Row] = StringGrid1->Cells[StringGrid1->Col][StringGrid1->Row] + sLineBreak;
 }
}
et dans l'événement OnDrawCell :

void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
// Sélection de la couleur de fond
    if(State.Contains(gdFixed))
    {
      StringGrid1->Canvas->Brush->Color = clBtnFace;
    }
    else if(State.Contains(gdSelected))
    {
      StringGrid1->Canvas->Brush->Color = clNavy;
    }
    else
    {
      StringGrid1->Canvas->Brush->Color = clWhite;
    }
// Dessin du fond
    StringGrid1->Canvas->FillRect(Rect);
// Sélection de la couleur de texte
    if(State.Contains(gdSelected))
    {
      SetTextColor(Canvas->Handle, clWhite);
    }
    else
    {
      SetTextColor(Canvas->Handle, clBlack);
    }
// Dessin du texte en utilisant la fonction API
    DrawText(StringGrid1->Canvas->Handle, (StringGrid1->Cells[ACol][ARow]).c_str(), -1, &Rect, DT_NOPREFIX | DT_WORDBREAK );
}

Comment mettre une image en fond d'un TStringGrid ?
Créé le 22/11/2010[haut]
auteurs : blondelle, Nono40
Voici le code à appliquer pour mettre une image en fond des cellules blanches d'un TStringGrid. L'image est contenue dans un Bitmap, mais elle peut aussi être contenue dans un TImage. Cette procédure gère le déplacement du fond de l'image si l'utilisateur se sert des barres de défilement :

void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
    int i, j, X, Y;
    TRect R;
    if(State.Contains(gdFixed))
	{
		// Les cellules fixes sont toujours dessinées en gris
		StringGrid1->Canvas->Brush->Color = clBtnFace;
		StringGrid1->Canvas->Brush->Style = bsSolid;
		StringGrid1->Canvas->FillRect(Rect);
	}
	else if(State.Contains(gdSelected))
	{
		// Les cellules sélectionnées sont en bleu
		StringGrid1->Canvas->Brush->Color = clNavy;
		StringGrid1->Canvas->Brush->Style = bsSolid;
		StringGrid1->Canvas->FillRect(Rect);
	}
	else
	{
		// Recherche de la zone image à copier pour tenir compte des décalages
		// de la grille en fonction des barres de défilement.
		X = 0;
		for(i = StringGrid1->FixedCols + 1; i <= ACol; i++) (X++, StringGrid1->ColWidths [i]);
		{
			Y = 0;
			for(i = StringGrid1->FixedRows + 1; i <= ARow; i++) (Y++, StringGrid1->RowHeights[i]);
			{
				R.Left = X;
				R.Right = X + Rect.Right - Rect.Left;
				R.Top = Y;
				R.Bottom = Y + Rect.Bottom - Rect.Top;
				// Dessin d'une partie de l'image
				Image1->Visible = false;
				Image1->Picture->Bitmap->LoadFromFile("C:\\Documents and Settings\\toto\\Mes documents\\Mes images\\Massiv10\\Massiv10\\Bitmaps\\Arrow\\arcarrow1.bmp");
				// "C:\\Documents and Settings\\toto\\Mes documents\\Mes images\\Massiv10\\Massiv10\\Bitmaps\\Arrow\\arcarrow1.bmp"
				StringGrid1->Canvas->CopyRect(Rect, Image1->Picture->Bitmap->Canvas, R);
				StringGrid1->Canvas->Brush->Style = bsClear;
			}
		}
	}
	// Sélection de la couleur de texte
	if(State.Contains(gdSelected))
	{
		SetTextColor(StringGrid1->Canvas->Handle, clWhite);
	}
	else
	{
		SetTextColor(StringGrid1->Canvas->Handle, clBlack);
	}
	// Dessin du texte en utilisant la fonction API
	DrawText(StringGrid1->Canvas->Handle, (StringGrid1->Cells[ACol][ARow]).c_str(), -1, &Rect, DT_NOPREFIX );
}
MonBitMap est un objet de type TBitMap qui doit avoir été chargé avec l'image. L'image doit être suffisamment grande pour couvrir le fond du TStringGrid.


Comment centrer le texte d'un TStringGrid ?
Créé le 22/11/2010[haut]
auteurs : blondelle, Nono40
Le code suivant permet de centrer le texte dans les cellules d'un TStringGrid. Le centrage est à la fois vertical et horizontal. Le dessin est ici effectué avec l'API de Windows car la fonction TextOut du canevas des composants ne permet pas directement le centrage.

void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
	// sélection de la couleur de fond
	if(State.Contains(gdFixed))
	{
		StringGrid1->Canvas->Brush->Color = clBtnFace;
	}
	else if(State.Contains(gdSelected))
	{
		StringGrid1->Canvas->Brush->Color = clNavy;
	}
	else
	{
		StringGrid1->Canvas->Brush->Color = clWhite;
	}
	// Dessin du fond
	StringGrid1->Canvas->FillRect(Rect);
	// Sélection de la couleur de texte
    if(State.Contains(gdSelected))
    {
    	StringGrid1->Font->Color = clWhite;
    }
    else
    {
    	StringGrid1->Font->Color = clBlack;
    }
	// Dessin du texte en utilisant la fonction API
	DrawText(StringGrid1->Canvas->Handle, (StringGrid1->Cells[ACol][ARow]).c_str(), -1, &Rect, DT_CENTER | DT_NOPREFIX | DT_VCENTER | DT_SINGLELINE  );
}

Comment écrire le texte d'une cellule d'un TStringGrid sur plusieurs lignes ?
Créé le 22/11/2010[haut]
auteurs : blondelle, Nono40
Le code suivant permet d'écrire le texte d'une cellule d'un TStringGrid sur plusieurs lignes.

void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
	// sélection de la couleur de fond
	if(State.Contains(gdFixed))
	{
		StringGrid1->Canvas->Brush->Color = clBtnFace;
	}
	else if(State.Contains(gdSelected))
	{
		StringGrid1->Canvas->Brush->Color = clNavy;
	}
	else
	{
		StringGrid1->Canvas->Brush->Color = clWhite;
	}
	// Dessin du fond
	StringGrid1->Canvas->FillRect(Rect);
	// Sélection de la couleur de texte
    if(State.Contains(gdSelected))
    {
    	SetTextColor(StringGrid1->Canvas->Handle, clWhite);
    }
    else
    {
    	SetTextColor(StringGrid1->Canvas->Handle, clBlack);
    }
	// Dessin du texte en utilisant la fonction API
	DrawText(StringGrid1->Canvas->Handle, (StringGrid1->Cells[ACol][ARow]).c_str(), -1, &Rect, DT_CENTER | DT_NOPREFIX | DT_WORDBREAK);
}


Consultez les autres F.A.Q.


Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2009 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.