2009-07-25 8 views
1

Voici le code:Désactivation et activation de composants lors de l'exécution dans Delphi 2K9. étrange problème

procedure DisableContrlOL(const cArray : array of string; ReEnable : boolean = False); 
// can be called from VKP/RAW/Generation clicks 
var 
    AComponent: TComponent; 
    CompListDis, CompListEna : TStringList; 
begin 
    CompListDis := TStringList.Create; 
    CompListEna := TStringList.Create; 
    for i := Low(cArray) to High(cArray) do begin 
    AComponent := FindComponent(cArray[i]); 
    if Assigned(AComponent) then 
     if (AComponent is TControl) then begin 
     if TControl(AComponent).Enabled then 
      CompListEna.Add(TControl(AComponent).Name) 
     else 
      CompListDis.Add(TControl(AComponent).Name); 
     ShowMessage(TControl(AComponent).Name); 
     if ReEnable then begin // if reenabling needed, then all whi 
      if not TControl(AComponent).Enabled then 
      TControl(AComponent).Enabled := True; 
     end else if (TControl(AComponent).Enabled) then 
      TControl(AComponent).Enabled := False; 
     end; 
    end; 
end; 

Je pense pas plus d'explications sont nécessaires. ShowMessage affiche correctement le nom de chaque composant, mais rien n'est ajouté dans StringLists. Pourquoi? MISE À JOUR: Comme la question est allée assez sauvage, j'ai confirmé la réponse, ce qui m'a aidé un peu. Je comprends que j'ai écrit des choses pas très claires, mais je suis très limité, parce que ces lignes de code font partie du projet commercial, et mon passe-temps et le cœur. Le problème principal a été trouvé il y a déjà 6h, mais Rob voulait juste prolonger toute cette question: D Non, pas d'offense, mec, c'est OK. Je suis heureux de recevoir des messages si prêts et utiles. Merci encore.

+0

Je pense que votre problème pourrait être lié à 'runtime'. Peut-être que si vous vous limitiez à des événements moins mystiques, cela pourrait fonctionner. :-) – robsoft

+0

@robsoft: Correction du problème. –

+0

HX: vous n'avez toujours pas voté ** AUCUN ** des réponses qui ont été données. Je vais faire de l'upvoting, mais je me suis retenu parce que je veux que ce soit évident que ce n'est pas le cas. Comprenez-vous pourquoi les gens qui répondent à vos questions pourraient considérer cela comme impoli? Savez-vous comment voter? – Argalatyr

Répondre

4

Comment savez-vous que rien n'est ajouté aux listes? Vous les créez dans ce code et les seules références sont dans des variables locales. Les objets sont divulgués lorsque cette fonction revient, donc vous n'utilisez jamais les listes n'importe où.

Vous avez dit que vous avez du code pour "tests modulaires". Puisque ce code n'est pas là, je dois supposer que le code ne fait pas partie de cette fonction. Mais si vous avez un code externe censé vérifier le contenu des listes, les listes ne peuvent pas être uniquement des variables locales. Aucun autre code ne peut y accéder. Vous devez soit renvoyer ces listes, soit accepter des listes de l'extérieur que vous remplissez ensuite. Voici un exemple de ce dernier:

procedure DisableContrlOL(const cArray: array of string; 
          Reenable: Boolean 
          CompListDis, CompListEna: TStrings); 
// can be called from VKP/RAW/Generation clicks 
var 
    AComponent: TComponent; 
    AControl: TControl; 
    i: Integer; 
begin 
    for i := Low(cArray) to High(cArray) do begin 
    AComponent := FindComponent(cArray[i]); 
    if not Assigned(AComponent) or not (AComponent is TControl) then 
     continue; 

    AControl := TControl(AComponent); 
    if AControl.Enabled then 
     CompListEna.Add(AControl.Name) 
    else 
     CompListDis.Add(AControl.Name); 
    ShowMessage(AControl.Name); 

    AControl.Enabled := Reenable; 
    end; 
end; 

L'appelant de cette fonction devra fournir un descendant TStrings pour chaque liste. Ils peuvent être TStringList, ou ils peuvent être d'autres descendants, tels que TMemo.Lines, de sorte que vous pouvez directement observer leur contenu dans votre programme. (Ils ne peuvent pas être juste TStrings, cependant, puisque c'est une classe abstraite.)


Comme vous pouvez le voir, j'ai fait quelques autres modifications apportées à votre code. Tout votre code utilisant le paramètre Reenable peut être simplifié en une seule instruction. En effet, l'activation d'un contrôle déjà activé et la désactivation d'un contrôle déjà désactivé ne sont pas des opérations. En outre, Name est une propriété publique de TComponent. Vous n'avez pas besoin de taper cast à TControl avant de lire cette propriété, mais étant donné que vous lancez le typage si souvent ailleurs, il est logique d'introduire une nouvelle variable pour contenir la valeur TControl de type cast, et cela peut rendre votre code plus facile à lire. Un code plus facile à lire est un code plus facile à comprendre, ce qui facilite le débogage.

+0

Hmm, je vous remercie pour le conseil à propos de stringlist, Rob! A propos de ce paramètre réouvrable - nop, il y a une raison un peu différente. Il serait assez long d'expliquer que je devrais coppy une partie de la source des applications. Aussi, que des pourboires sur les composants. Je le savais, mais je n'étais pas sûr, parce que dans presque tous les exemples je trouve ce code ... –

+0

Je pense que vous avez oublié de répondre à ma question: * Comment ** savez-vous ** quelque chose ne va pas avec votre code? , votre affirmation selon laquelle "plus d'explications sont nécessaires" était fausse. –

+0

je le sais parce que quand je le fais avec des points d'arrêt, il n'y a pas d'éléments dans stringlist pllus quand je deviens avec dcus, thetre ne sont pas varable ou adresse mémoire ramassé et dans le code continu, si j'utilise le code dont j'ai besoin c'est juste pour le test modulaire), j'obtiens l'erreur hors-limite de liste d'exécution. C'est comme ça que je sais qu'il y a quelque chose qui ne va pas. –

0

Cela semble sûr que cela devrait fonctionner. C'est le genre de chose que le débogueur peut probablement aider avec plus que nous pouvons ici.

Essayez de briser la ligne problématique vers le bas en plusieurs lignes, comme ceci:

if TControl(AComponent).Enabled then 
    CompListEna.Add(TControl(AComponent).Name) 
    else CompListDis.Add(TControl(AComponent).Name); 

Reconstruire avec l'option « Utiliser Debug DCU » sur et placer un point d'arrêt sur la déclaration si. Ensuite, utilisez F7 pour tracer votre chemin à travers la logique et voir ce qui se passe.

+0

Nop, ne fonctionne pas. Rien du tout n'arrive à l'une des listes de chaînes. FindComponenet(); prend juste le nom des contrôles et c'est tout ... P.S. J'ai utilisé le dcu ... –

2

Soulignant que cela est en grande partie sur d'excellentes suggestions de Rob, il semble que vous pouvez simplifier le code:

procedure DisableContrlOL(const cArray : array of string; 
           ReEnable : boolean = False); 
var 
    AComponent: TComponent; 
begin 
    for i := Low(cArray) to High(cArray) do 
    begin 
    AComponent := FindComponent(cArray[i]); 
    if Assigned(AComponent) then 
     if (AComponent is TControl) then 
     begin 
     ShowMessage(TControl(AComponent).Name); 
     TControl(AComponent).Enabled := ReEnable; 
     end; 
    end; 
end; 

pas clairement ce que les stringlists étaient pour, étant donné que leur contenu ont été perdus lors de l'exécution a quitté la portée de cette procédure. Si vous voulez les retourner, vous devez les créer et les libérer dans le code appelant.

+0

Oui, merci, problème théoriquement trouvé et éliminé. Merci pour cela, mais les listes de chaînes étaient pour le tri - ce qui est activé au moment de l'exécution et ce qui n'est pas comopoent. Thasthow je pourrais déterminer par paramètre reenable chaque fois pour les activer ou désactiver. Cela n'a pas été couvert par ma question, car je pensais simplement qu'aucune valeur n'était enregistrée dans les listes de chaînes. Merci encore, désolé pour mon attitude déraisonnable. À ce stade, tout le monde a la bonne réponse. ;) –

+1

... et pourtant vous n'avez voté pour aucun d'eux! Vous devriez mettre à votre disposition les réponses (à toute question, pas seulement la vôtre) que vous trouvez utiles, et * Accepter * la meilleure réponse à vos propres questions. – Argalatyr

+2

Si vous créez et libérez les dans le code appelant, alors vous ne devriez pas les faire avec les paramètres 'var'. Voir ma réponse éditée pour un exemple. –