Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 2013
-
19 août 2008 à 14:20
WhiteHippo
Messages postés1154Date d'inscriptionsamedi 14 août 2004StatutMembreDernière intervention 5 avril 2012
-
23 août 2008 à 11:05
Salut tout le monde.
J'ai un bug dans l'IDE de delphi, et je sais pas si ca peut se resoudre.
Je m'explique:
J'ai un composant, qui a comme propriete published un objet Obj.
l'affectation d'une autre propriété de ce composant va detruire ou remplacer cet objet Obj.
donc, dans l'inspecteur d'objets, quand je selectionne mon composant, j'ai :
Comp.prop1
+Comp.Obj
Comp.prop2
si je change Comp.prop2, ca va detruire Comp.Obj et le remplacer par une autre instance (pas forcement la meme classe)
Je n'ai aucun probleme si Comp.Obj n'est pas deroulé dans l'inspecteur. Par contre, si je l'expand, mon inspecteur d'objets ressemble à :
Comp.prop1
-Comp.Obj
Obj.propX
Obj.propY
Comp.prop2
et des que je modifie prop2 pour remplacer l'instance de mon Obj, j'ai un plantage (AV de Delphi).
Est-ce que je m'y prend mal?
Y a t'il moyen de collapser l'editeur par le code avant de remplacer l'instance?
Espèce de petit coquin ... toi, tu nous dis pas tout
1)C'est un composant que tu fais ? (je suis sur que oui )
2)Il y a t'il un lien entre Obj et propriété 2 ?
3)Est ce un composant visuel ?
4)Pourrait tu nous passer le coder stp ?
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 19 août 2008 à 18:57
1) "J'ai un composant, qui ..." -> oui c'est un composant
2)oui, SetProp2 fait un free de obj puis un create.
3)le compo oui, mais peu importe, l'important est qu'il soit modifiable dans l'inspecteur d'objet
4)rhooo franky t'essaye de voler mon code de ma proprieté intelectuelle a
moi. Et ca je dis non, c'est top secret, c'est pour vendre a l'armee
americaine et je crois pas qu'ils apprecieront que tu entre en
possession du code (a moins que tu ne dispose d'un vaccin anti-napalm )
Voici le bébé. le code du compo n'a pas grand interet, c'est le code de l'objet (precedament obj) qui est interessant. Je pense que ca pourra servir a d'autres, c'est un compo d'affichage d'infos. Un truc qui doit etre un design pattern decoration je crois. Il publie une fonction d'affichage, implementée differament selon le compo afficheur. Bref, voila le code:
function TIGHintLink.GetHintValue: string;
begin
if not Assigned(Control) then
Exit; //<<<<<<<<<< Exit >>>>>>>>>>
Result := TFakeControl(Control).Caption;
end;
procedure TIGHintLink.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (AComponent FControl) and (Operation opRemove) then
begin
FControl := nil;
end;
//TODO : Self.Free;
end;
procedure TIGHintLink.SetHintValue(const Value: string);
begin
if not Assigned(Control) then
Exit; //<<<<<<<<<< Exit >>>>>>>>>>
TFakeControl(Control).Caption := Value;
end;
{ TIGHLStatusBar }
constructor TIGHLStatusBar.Create(AOwner: TComponent; AControl: TControl);
begin
if not (AControl is TStatusBar) then
AControl := nil;
inherited Create(AOwner, AControl);
FPanelIndex := 0;
end;
function TIGHLStatusBar.GetHintValue: string;
begin
if not Assigned(Control) then
Exit; //<<<<<<<<<< Exit >>>>>>>>>>
if StatusBar.SimplePanel then
Result := StatusBar.SimpleText
else if (FPanelIndex >= 0) and (FPanelIndex < StatusBar.Panels.Count) then
Result := StatusBar.Panels[FPanelIndex].Text
else
Result := '';
end;
procedure TIGHLStatusBar.SetHintValue(const Value: string);
begin
if not Assigned(Control) then
Exit; //<<<<<<<<<< Exit >>>>>>>>>>
if StatusBar.SimplePanel then
StatusBar.SimpleText := Value
else if (FPanelIndex >= 0) and (FPanelIndex < StatusBar.Panels.Count) then
StatusBar.Panels[FPanelIndex].Text := Value;
end;
function TIGHLStatusBar.StatusBar: TStatusBar;
begin
Result := TStatusBar(Control);
end;
procedure TMonCompo .SetHintView(const Value: TControl);
begin
if Assigned(FHintLink) then
FreeAndNil(FHintLink);
if not Assigned(Value) then
Exit; //<<<<<<<<<< Exit >>>>>>>>>>
if Value is TStatusBar then
FHintLink := TIGHLStatusBar.Create(self, Value)
else
FHintLink := TIGHintLink.Create(self, Value);
end;
function TMonCompo .GetHintView: TControl;
begin
if Assigned(FHintLink) then
begin
Result := FHintLink.Control;
end
else
begin
Result := nil;
end;
end;
function TIGHintLink.GetHintValue: string;
begin
Result:='';
if Assigned(Control) then
Result := TFakeControl(Control).Caption;
end;
procedure TIGHintLink.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited; if (AComponent FControl) and (Operation opRemove) then
FControl := nil;
//TODO : Self.Free;
end;
procedure TIGHintLink.SetHintValue(const Value: string);
begin
if Assigned(Control) then
TFakeControl(Control).Caption := Value;
end;
{ TIGHLStatusBar }
constructor TIGHLStatusBar.Create(AOwner: TComponent; AControl: TControl);
begin
if not (AControl is TStatusBar) then
AControl := nil;
inherited Create(AOwner, AControl);
FPanelIndex := 0;
end;
function TIGHLStatusBar.GetHintValue: string;
begin
Result:='';
if Assigned(Control) then
Begin
If StatusBar.SimplePanel then Result := StatusBar.SimpleText;
if (FPanelIndex >= 0) and (FPanelIndex < StatusBar.Panels.Count) then
Result := StatusBar.Panels[FPanelIndex].Text;
End;
end;
procedure TIGHLStatusBar.SetHintValue(const Value: string);
begin
if Assigned(Control) then
Begin
if StatusBar.SimplePanel then StatusBar.SimpleText := Value;
if (FPanelIndex >= 0) and (FPanelIndex < StatusBar.Panels.Count) then
StatusBar.Panels[FPanelIndex].Text := Value;
End;
end;
function TIGHLStatusBar.StatusBar: TStatusBar;
begin
Result := TStatusBar(Control);
end;
procedure TMonCompo .SetHintView(const Value: TControl);
begin
if Assigned(FHintLink) then
FreeAndNil(FHintLink);
if Assigned(Value) then
Begin
if Value is TStatusBar then FHintLink := TIGHLStatusBar.Create(self, Value)
else FHintLink := TIGHintLink.Create(self, Value);
End;
end;
function TMonCompo .GetHintView: TControl;
begin
Result:=Nil;
if Assigned(FHintLink) then Result := FHintLink.Control;
end;
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 19 août 2008 à 23:39
Question: Dans le OnCreate de ton composant a tu crée FHintLink ?
Réponse : Non, il est créé quand on affecte une valeur a la property HintView
le principe est que tu choisi un composant X sur la même fiche que le compo, et c'est X qui affichera les informations de mon compo.
un exemple serait de faire un composant hérite de TImage, surcharger la méthode MouseMove dans le genre :
procedure TMonImage.MouseMove(..., X, Y);
begin
if Assigned(Self.HintLink) then
Self.HintLink.HintValue := IntToStr(X) + ',' + IntToStr(Y);
end;
Tu pose la TMonImage, tu affecte sa propriété HintView à la StatusBar1 de la même form, et les infos s'affichent sur la statusbar. L'intérêt est que quel que soit le composant que tu choisis, il peut afficher le texte.
Le plantage a lieu uniquement quand la propriété HintLink est expanded (petit "-" a cote du nom de propriété).
NB : je suis sous D7
En ce qui concerne le code que tu as mis, la différence est que mes getters peuvent ne pas renvoyer de valeur. Effectivement, j'ai rajouté les Exit un peu machinalement après avoir codé tout ça, sans trop vérifier. Je vais tester ça mercredi.
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 20 août 2008 à 09:25
bon j'ai fait le test avec le result toujours affecté: aucun changement.
Par contre, j'ai reussi a preciser le plantage :
j'affecte StatusBar1 à HintView -> Creation d'une instance de TIGHLStatusBar
j'expand HintLink -> je vois bien la propriete PanelIndex (propre a cette heritier de TIGHintLink)
j'affecte Panel1 à HintView -> Creation d'une instance de TIGHintLink
-> AV $0000000 parce que l'inspecteur d'objet contient une ligne 'PanelIndex' qui n'est pas disponible pour l'instance en cours de HintLink.
Ce qui ne plante pas :
- si le HintLink est collapsé
- si je passe d'un hintlink A à un hintlink B, si B a au moins les meme proprietes que A
je ne pense pas que ca puisse se resoudre. Ca doit etre un "bug" de l'IDE (mais bon c'est peut etre bizare de changer d'instance comme ca a la volée).
WhiteHippo
Messages postés1154Date d'inscriptionsamedi 14 août 2004StatutMembreDernière intervention 5 avril 20122 22 août 2008 à 21:09
Bonsoir,
Je ne pense pas que cela soit un bug de l'IDE; c'est certainement un problème de "récursivité" dans la destruction des composants. Quelquechose me chagrine dans ton code, c'est l'absence d'appel de RemoveFreeNotification.
Je te donne une piste à creuser (non testée, car entièrement faite en live en fonction du code ci-dessus ;) :
constructor TIGHintLink.Create(AOwner: TComponent; AControl: TControl);
begin
inherited Create(AOwner);
FControl := AControl;
// FreeNotification seulement si AControl<>NIL
if Assigned( FControl ) then
FControl.FreeNotification(self);
end;
procedure TMonCompo .SetHintView(const Value: TControl);
begin
// Si même composant, rien à faire
if ( Value = FHintLink ) then Exit ;
// Pas de suppression si c'est déjà le cas
if Assigned(FHintLink) and ( not (csDestroying in FHintLink.ComponentState ) ) then
begin
FHintLink.RemoveFreeNotification(self);
FreeAndNil(FHintLink);
end ;
if Assigned(Value) then
Begin
if Value is TStatusBar
then FHintLink := TIGHLStatusBar.Create(self, Value)
else FHintLink := TIGHintLink.Create(self, Value);
End;
end;
Cordialement. <hr />"L'imagination est plus importante que le savoir." Albert Einstein
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 23 août 2008 à 00:57
constructor TIGHintLink.Create(AOwner: TComponent; AControl: TControl);
begin
inherited Create(AOwner);
FControl := AControl;
// FreeNotification seulement si AControl<>NIL : effectivement, il le faut. Ceci dit, je ne l'appelle pas avec
AControl=
nil. L'ide le fait peut-être !
if Assigned( FControl ) then
FControl.FreeNotification(self);
end;
procedure TMonCompo .SetHintView(const Value: TControl);
begin
// Si même composant, rien à faire
if ( Value = FHintLink.Control ) then Exit ; // je suppose la faute d'attention ;)
// Pas de suppression si c'est déjà le cas
pour le csDestroying, pourquoi pas. Par contre, pourquoi le RemoveFreeNotification ?
j'ai regardé le fonctionnement de FreeNotification un jour. Ce que je me souviens c'est:
procedure A.FreeNotification(B)
begin
if listeANotifier.indexOf(B) = -1 then
begin
listeANotifier.Add(B)
B.freeNotification(A)
end;
end;
procedure A.Destroy
begin
for B in listeANotifier do
B.Notification(A, opRemove)
end;
le fait de pas faire RemoveFreeNotification va faire :
freeAndNil(FhintLink)
-> FHintLink.notifierLesBonsCompos
->
self(
TMonCompo
).Notification
-> Self.removeFreeNotification(FHintLink) //grace au inherited de Notification
if Assigned(FHintLink) and ( not (csDestroying in FHintLink.ComponentState ) ) then
begin
FHintLink.RemoveFreeNotification(self);
FreeAndNil(FHintLink);
end ;
if Assigned(Value) then
Begin
if Value is TStatusBar
then FHintLink := TIGHLStatusBar.Create(self, Value)
else FHintLink := TIGHintLink.Create(self, Value);
End;
end;
je crois que c'est un bug, car comme je l'ai dit :
Ce qui plante, et ce qui ne plante pas:
- si le HintLink est collapsé (dans tous les cas)
- si je passe d'un hintlink A à un hintlink B, si B a au moins les meme proprietes que A
- si je passe d'un hintlink A à un hintlink B, si B n'a pas toutes les proprietes de A
Vous pensez pas?
Je crois que l'ide, quand on expand, lit les property published, et ajout une ligne a la list view. Des qu'il y a un changement, elle reafraichi la valeur de chaque ligne (et donc plante sur celles qui ne sont plus presentes). Il faudra que je teste avec un hitlink expanded, et de mettre le hintview à nil. je pense qu'il devrait planter.
Vous avez deja vu un tel type de comportement qui fonctionnait?
Pensez vous que ma methode de conception soit bizare ?
WhiteHippo
Messages postés1154Date d'inscriptionsamedi 14 août 2004StatutMembreDernière intervention 5 avril 20122 23 août 2008 à 11:05
Si le HintLink est collapsé, l'inspecteur d'objet ne parcourt pas tous les objets contenus et donc il est normal de ne pas planter.
Si il ne l'est pas (collapsé), est que l'inspecteur plante, c'est qu'il scrute un objet (et donc un pointeur) incohérent. J'ai eu un phénomène similaire il y quelques années lors du développement d'un composant qui créait automatiquement un autre composant. Celui-ci était lié à des composants dynamiques et était détruit dès que ceux-ci n'existaient plus.
Je jette un oeil pour retrouver le code du composant en question. Mais si je me souviens bien, le moyen employé pour débugguer ce composant a été de créer un fichier log afin de suivre l'ensemble des méthodes (leur début, leur fin) et la création et destruction des composants.
P.S. Je ne pourrais pas le donner ici (code propriétaire pour un client)
Cordialement. <hr />"L'imagination est plus importante que le savoir." Albert Einstein