Entrer dans l'évenement Onchange dans un sous-composant [Résolu]

cs_pouicky 30 Messages postés lundi 26 avril 2004Date d'inscription 4 août 2010 Dernière intervention - 19 déc. 2005 à 22:22 - Dernière réponse : Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention
- 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


uses
SysUtils, Classes, StdCtrls, Controls, Grids,
DBGrids,Types,ADODB,Graphics,DB,Messages;


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;

end;
//-------------------------------------------------------------


//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?-->)
Afficher la suite 

10 réponses

Répondre au sujet
cs_pouicky 30 Messages postés lundi 26 avril 2004Date d'inscription 4 août 2010 Dernière intervention - 21 déc. 2005 à 22:18
+3
Utile
ç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



<HR>
rame, rame, rameurs, ramez....
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_pouicky
cs_pouicky 30 Messages postés lundi 26 avril 2004Date d'inscription 4 août 2010 Dernière intervention - 19 déc. 2005 à 22:28
0
Utile
Autre question : peut-on insérer des sources delphi avec la colorisation dans les forums?
Commenter la réponse de cs_pouicky
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 20 déc. 2005 à 12:13
0
Utile
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)

@+
Commenter la réponse de Cirec
cs_pouicky 30 Messages postés lundi 26 avril 2004Date d'inscription 4 août 2010 Dernière intervention - 21 déc. 2005 à 01:33
0
Utile
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)

http://www.univ-tours.fr/discala/livres/basesinfo8.pdf

Cet article qui se veut "de base" mais est excellent et me semble tres pointu pour ce qui nos interesse là.

Si quelqu'un a une astuce simple je suis toujours preneur. ;)
Commenter la réponse de cs_pouicky
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 21 déc. 2005 à 01:36
0
Utile
ce que je t'ai mis fonctionne essaye le



@+
Cirec
Commenter la réponse de Cirec
cs_pouicky 30 Messages postés lundi 26 avril 2004Date d'inscription 4 août 2010 Dernière intervention - 21 déc. 2005 à 01:59
0
Utile
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


TPersoEdit= class (TEdit)


private


protected


procedure WMMouseWheel(var Msg: TWMMOUSEWHEEL);message WM_MOUSEWHEEL;


public


published


end;


TPersoDBGrid =class(TDBGrid)


private //visible pour la seule TPersoDBGrid


{ Déclarations privées }


eRecherche:TPersoEdit;


procedure EditChanged(Sender:TObject);//déclaré sous PersoDBGrId


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;


//WMMouseWheel réagira aux messages de type roulette


procedure WMMouseWheel(var Msg: TWMMOUSEWHEEL);message WM_MOUSEWHEEL;


public//visible pour toutes les classes


constructor Create(Owner:TComponent);override;


destructor Destroy();override;


published//comme public mais visible en plus à la conception graphique


property ...


end;


procedureRegister;


implementation


var


nomDeChamp:string;


DataSet: TDataSet;


leftCellule,rightCellule:Integer;


constructor TPersoDBGrid.Create(Owner:TComponent);


begin


inherited Create(Owner);//Constructeur herité


//colorisations par défaut


//Instanciation d'une zone de saisie


eRecherche: = TPersoEdit.Create(Self);


with eRecherche do


begin


Parent: = self;


Ctl3D:= False;


Text:='';


Visible:=false;


end ;


TEdit(eRecherche).OnChange: =EditChanged;


end;


destructor TpersoDBGrid.Destroy;


begin


eRecherche.Free;


Dataset.Free;


inherited Destroy;


end;


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.CellClick(Column: TColumn);


begin


with eRecherche do


begin


Text: = '';


visible:= False;


Parent.SetFocus;


end ;


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érer la position de la cellule selectionnée


leftCellule: =rect.Left;


rightCellule:= rect.Right;


//coloriser si les cellules concernées




//lancer la fonction de colorisation de l'entête et récupération du champ actif:
selectTitre(Column);


End


Else//pour les cellules non sélectionnées


Begin


//cas des lignes à index pairs et impairs :coloriages




End;
//appliquer l'operation de redessin


DefaultDrawColumnCell(rect,datacol,column,state);


end;


//gestion de la molettesur la grille si elle a le focus


procedure TPersoDBGrid.WMMouseWheel(var Msg: TWMMOUSEWHEEL);


begin


//...
end;


Exit;


end;


procedure TPersoEdit.WMMouseWheel(var Msg: TWMMOUSEWHEEL);


begin


self.Parent.SetFocus;


end;


procedure TPersoDBGrid.EditChanged(Sender:TObject);//déclaré sous PersoDBGrid


begin


if DataSet =nil then exit;


DataSet.Locate(nomDeChamp,eRecherche.Text,[loCaseInsensitive,loPartialKey]);


end;





procedure TPersoDBGrid.triColonne(Column:TColumn);


begin


//...
end;


procedure TPersoDBGrid.selectTitre(Column: TColumn);


var i:integer;


begin


//adaptation du TEdit nommé eRecherche à la colonne


with eRecherche do


begin


Left:= leftCellule;


width:=rightCellule-leftCellule;


Top:=0;


height:=-Column.Title.Font.Height;


Text:=Column.Title.Caption;


SelStart:=0;


SelLength:=30;


end ;


nomDeChamp: =Column.FieldName;


//gestion de l'index de selection


//Gestion des couleurs des titres


end;


procedureRegister;


begin


RegisterComponents('Personnels',[TPersoDBGrid]);


end;


end.



<HR>
rame, rame, rameurs, ramez....
Commenter la réponse de cs_pouicky
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 21 déc. 2005 à 02:34
0
Utile
pouicky,
regarde tes messages privés
Commenter la réponse de Cirec
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 21 déc. 2005 à 19:36
0
Utile
ç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 ?



@+
Cirec
Commenter la réponse de Cirec
cs_pouicky 30 Messages postés lundi 26 avril 2004Date d'inscription 4 août 2010 Dernière intervention - 21 déc. 2005 à 21:42
0
Utile
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).
Commenter la réponse de cs_pouicky
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 22 déc. 2005 à 01:23
0
Utile
ok ,
merci pour l'info, j'attend le résultat final avec impatience
Bonne prog



@+
Cirec
Commenter la réponse de Cirec

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.