cs_pouicky
Messages postés19Date d'inscriptionlundi 26 avril 2004StatutMembreDernière intervention 4 août 2010
-
19 déc. 2005 à 22:22
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 2022
-
22 déc. 2005 à 01:23
j'ai un probleme d'entrée dans l'evenement onChange d'un TEdit instancié
par un TPersoDBGrid, l'ensemble devant devenir un composant unique. Voici la source édulcorée et commentée:
//Déclarations dans la même unité des deux osus-composants:
interface
var
nomDeChamp:string;
DataSet: TDataSet;
//Le TDataset doit servir à la fois pour le TPersoEDIT et le TPersoDBGRID
//il est initialisé dans la méthode selectTitre() du TPersoDBGRid;
type //composant TEDIT
//Derivé de TEDIT: sous-classe créée pour gérer les évenements
TPersoEdit=class(TEdit)
protected
procedure WMMouseWheel(var Msg: TWMMOUSEWHEEL); message WM_MOUSEWHEEL;//sert à rendre le focus à la DBGrid et fonctionne.
procedure Change(); override;
//Derivé de TDBGrid, base du composant et parent du TPersoEdit
TPersoDBGrid = class(TDBGrid)
private
{ Déclarations privées }
eRecherche:TPersoEdit;
procedure selectTitre(Column: TColumn);
procedure triColonne(Column:TColumn);
protected //visible pour les seuls descendants de la TPersoDBGrid
{ Déclarations protégées }
procedure CellClick(Column: TColumn);override;//et pas overload car la methode surchargée est virtuelle
procedure TitleClick(Column:TColumn);override;
procedure DrawColumnCell(const Rect:TRect;DataCol:Integer;Column:TColumn;State:TGridDrawState);override;
procedure WMMouseWheel(var Msg: TWMMOUSEWHEEL); message WM_MOUSEWHEEL;
public //visible pour toutes les classes
//popMenuPerso:TPopupMenu; //à programmer
constructor Create(Owner:TComponent);override;
destructor Destroy();override;
published
//...non recopié
end;
//-------------------------------------------------------------
//Les procédure et méthodes en jeu à mon sens:
constructor TPersoDBGrid.Create(Owner:TComponent);
begin
eRecherche:=TPersoEdit.Create(Self);//chaque ligne est parcourue au debogage
with eRecherche do
begin
Parent:=self;
Ctl3D:=False;
Text:='';
Visible:=false;
end;
end;
//apres cette ligne, le débogueur on passe à "application.run" du projet
//ensuite on entre dans TPersoEdit.Change pour la premiere et derniere fois
procedure TPersoDBGrid.TitleClick(Column:TColumn);
begin
//execution des fonctions attachées au tri
selectTitre(Column);//voir fonctions en bas de page
eRecherche.Visible:=True;
eRecherche.SetFocus;
triColonne(Column); //voir fonctions en bas de page
//execution de l'évènement du développeur si il est assigné
if Assigned(onTitleCLick) then onTitleclick(Column);
end;
procedure TPersoDBGrid.DrawColumnCell(const Rect:TRect;DataCol:Integer;Column:TColumn;State:TGridDrawState);
begin
//si l'etat "selectionné" est trouvé dans le TGridDrawState pour une cellule
If gdSelected In State Then
Begin
//...récupération des dimensions de largeur pour tailler le TPersoEdit non recopié
//...colorisation des cellules non recopié
selectTitre(Column);
//select titre effectue la colorisation de l'entête,
//récupére le champ actif, et
//initialise le dataset utilsé aussi dans le TPersoEdit.onChange.
End;
//...autres opérations de coloriages non recopiées
DefaultDrawColumnCell(rect,datacol,column,state);
end;
//la methode selectTitre où est initialisé le TDATASET
procedure TPersoDBGrid.selectTitre(Column: TColumn);
var i:integer;
begin
//...adaptation du TEdit nommé eRecherche à la colonne (non recopié)
//affectation du champ courant dans sa variable globale
nomDeChamp:=Column.FieldName;
//gestion de l'index de selection
SelectedIndex:=Column.Index;
//...Gestion des couleurs des titres non recopiée
end;
//!!!!!C'est ici que le code n'est pas parcouru, sauf à l'instanciation du composant.(vu avec f8 et point d'arret)!!!!
procedure TPersoEdit.Change;
begin
if DataSet=nil then exit;
inherited Change;
DataSet.Locate(nomDeChamp,Text,[loCaseInsensitive,loPartialKey]);
end;
//...procedure register non recopiée
J'ai une piste sans idée de solution :
serait-ce la fiche qui emet le message onchange au TEdit et pas son parent TPersoDBGrid? comment gérer cela (intercepter les messages keyPress?-->)
cs_pouicky
Messages postés19Date d'inscriptionlundi 26 avril 2004StatutMembreDernière intervention 4 août 2010 21 déc. 2005 à 22:18
ça y est j'ai trouvé
c'était bien ça, l'histoire du message qui n'était pas transmis du PersoDBGrid au TPersoEdit.
ça marche (mais c'est à épurer sûrement) en faisant ceci:
je defini une methode de message sur le message WMChar dans le TEDit
procedure WMChar (var Msg:TWMCHAR);message WM_CHAR; je défini une methode de message sur le message WMChar dans le DBGrid.
procedure WMChar (var Msg:TWMCHAR);message WM_CHAR;
la mehode TCBgrid.WMChar a pour fonction d'appeler celle du Tedit en lui passant son parmetre Msg:
procedure TPersoDBGrid.WMChar(var Msg: TWMChar);
begin
eRecherche.WMChar(Msg);
end;
Et sur la methode TEditWMChar j'effectue le traitement
procedure TPersoEdit.WMChar(var Msg: TWMChar);
begin
if Msg.CharCode = ord(#13) then //execution sur la touche return
Begin
if DataSet=nil then exit;
//il faudra gérer le type de données ou convertir en string??
DataSet.Locate(nomDeChamp,Text,[loCaseInsensitive,loPartialKey]);
end
else
inherited;
end;
Je suis assez content de mon intuition à vrai dire
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 20 déc. 2005 à 12:13
Salut,
Regarde ceci, j'ai fait un petit essai de code avec un evenement onChange déclarer dans le OnCreate de la Form ( pour toi il faudrat le mettre dans le constructor TPersoDBGrid.Create(Owner:TComponent)) ce qui est le plus important pour toi je l'ai mis en rouge.
l'exemple suivant modifie le label1 quand le texte de l'Edit1 est modifier
type
TForm1 = class (TForm)
Label1: TLabel;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure EditChanged (Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
TEdit(Edit1).OnChange : = EditChanged;
end;
procedure TForm1.EditChanged(Sender: TObject);
begin
Label1.Caption := Edit1.Text;
end ;
end.
Voilà donc ce qu'il fait faire dans ton cas pour que ça fonctionne :
//Derivé de TDBGrid, base du composant et parent du TPersoEdit
TPersoDBGrid = class(TDBGrid)
private { Déclarations privées }
eRecherche:TPersoEdit;
procedure EditChanged(Sender : TObject); //à déclarer comme ceci
procedure selectTitre(Column: TColumn);
procedure triColonne(Column:TColumn);
protected //visible pour les seuls descendants de la TPersoDBGrid
{ Déclarations protégées }
...
...
...
public //visible pour toutes les classes
//popMenuPerso:TPopupMenu; //à programmer
constructor Create(Owner:TComponent);override;
destructor Destroy();override;
published //...non recopié
end;
//-------------------------------------------------------------
//Les procédure et méthodes en jeu à mon sens:
constructor TPersoDBGrid.Create(Owner:TComponent);
begin eRecherche:= TPersoEdit.Create(Self);//chaque ligne est parcourue au debogage
with eRecherche do begin Parent: =self;
Ctl3D:= False;
Text:='';
Visible:=false;
end ;
TEdit(eRecherche).OnChange : = EditChanged;// ici onl'affecte à eRecherche(Edit)
end;
//et la procedure en elle même tu remarqueras que tout est déclarer sous TPersoDBGrid
procedure TPersoDBGrid.EditChanged(Sender: TObject);
begin
if DataSet=nil then exit;
inherited Change;
DataSet.Locate(nomDeChamp,Text,[loCaseInsensitive,loPartialKey]);
end;
ceci fonctionne avec certitude, je l'utilise asser souvant pour redéfinir le onChange d'un composant.
En ce qui concerne la deuxièmme question tu peux soit le faire manellement (ce que je fait si il n'y a que quelques lignes) où si c'est plus long il existe un editeur de code qui est libre qui s'appel ConTEXT et tu peux le trouver à www.context.cx et celui ci est très pratique (à mon avis) puisque tu peux éditer ton code (supporte plusieurs langages) et en suite directement le mettre dans le presse-papier au format rtf et ensuite il ne reste plus qu'à faire coller.
Bon c'est ma methode il y a peut être plus simple mais bon cette éditeur vaut bien un coup d'oeil (il est bien sur possible de le mettre en français)
cs_pouicky
Messages postés19Date d'inscriptionlundi 26 avril 2004StatutMembreDernière intervention 4 août 2010 21 déc. 2005 à 01:33
J'ai l'impression que mon probleme releve de la gestion des évènements windows,, theme abordé au lien suivant que je potasserai moins fatigué (il se fait tard, finalement)
cs_pouicky
Messages postés19Date d'inscriptionlundi 26 avril 2004StatutMembreDernière intervention 4 août 2010 21 déc. 2005 à 01:59
oups, Le post précédent n'est pas passé.
Mêmes symptômes qu'avant: un seul passage dans EditChanged au lancement de l'application test de ce composant. Voici l'essentiel du test...en couleurs ;)
type
// sous-classe créée pour modifier le comportement du tedit
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 21 déc. 2005 à 19:36
ça y est
à la place de :
with eRecherche do
begin
Parent:= self;
Ctl3D:=False;
Text:='';
Visible:=false;
end ;
TEdit(eRecherche).OnChange: =EditChanged;
end;
Tu mets ceci :
TPersoEdit= class (TEdit)
private procedure EditChanged(Sender:TObject); // à déclaré sous PersoEdit en private
protected
with eRecherche do begin Parent: =self;
Ctl3D:=False;
Text:='';
OnExit := EditChanged;
Visible:=True;
end;
Et là ça fonctionne très bien tu tapes un texte et quand tu quitte le PersoEdit là il le prend à chaque fois. Alors pourquoi ça ne fonctionne pas avec on change je ne sais pas ? Toujours est-il que j'ai fait des testes avec juste un TPersoEdit et là ça fonctionne tout le temps et dès que je l'intègre à ton Composant ça ne fonctionne plus ?????
Après je me demande si l'utilisation de OnChange était judicieuse puisqu'il aurait déclanché l'évènement à chaque fois qu'une touche était pressée ?
cs_pouicky
Messages postés19Date d'inscriptionlundi 26 avril 2004StatutMembreDernière intervention 4 août 2010 21 déc. 2005 à 21:42
Merci de ton aide et de cette nouvelle info qui me conforte dans ce que je pense:
Je crois que les messages windows atteignent directement l'évenement onChange d'un composant via la fiche qui le contient. Et là, c'est PersoDBGrid le composant qui reçoit les messages windows il ne doit pas faire le relai par sa nature (c'est sûrement de l'à peu pres, mais je vais faire quelques tests en changeant le parent de TPERSOEDIT pour voir).
Merci pour ce test eclaircissant même si je souhaite volontairement faire la recherche dans le champ à chaque touche clavier dans la zone de texte. (d'où l'utilisation des fonctionnalités ado de tri et de recherche sans requete sql supplementaire).