2009-07-25 5 views
1

Hier Code:Komponente, die zur Laufzeit in Delphi 2K9 deaktiviert und aktiviert wird. Sonderbares Problem

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; 

Ich denke nicht mehr Erklärungen benötigt. Die ShowMessage zeigt korrekt den Namen jeder Komponente an, aber in StringLists wird nichts hinzugefügt. Warum?

UPDATE: Als Frage ist ziemlich wild gegangen, ich habe Antwort bestätigt, die mir ein bisschen geholfen hat.

Ich verstehe, dass ich Dinge ziemlich unklar geschrieben habe, aber ich bin sehr begrenzt, weil diese Codezeilen Teil des kommerziellen Projekts sind, und mein Hobby und Herzsache. Das Hauptproblem wurde bereits vor 6 Stunden gefunden, aber Rob wollte nur diese ganze Frage ausweiten: D Nein, nichts für ungut, Kumpel, es ist OK. Ich freue mich, so willige und hilfreiche Beiträge zu erhalten. Danke noch einmal.

+0

Ich denke, dein Problem könnte mit 'Runetime' zu tun haben. Vielleicht, wenn du dich auf weniger mystische Ereignisse beschränkte, könnte es funktionieren. :-) – robsoft

+0

@robsoft: Es wurde behoben. –

+0

HX: Sie haben noch immer ** ANY ** der Antworten nicht abgestimmt. Ich werde etwas Upvoting machen, habe mich aber zurückgehalten, weil ich es offen sagen will, dass du es nicht getan hast. Verstehst du, warum die Leute, die deine Fragen beantworten, dies als unhöflich betrachten? Weißt du, wie man abstimmt? – Argalatyr

Antwort

4

Woher wissen Sie, dass den Listen nichts hinzugefügt wird? Sie erstellen sie in diesem Code und die einzigen Verweise auf sie sind in lokalen Variablen. Wenn diese Funktion zurückkehrt, sind die Objekte durchgesickert, so dass Sie die Listen nie irgendwo verwenden.

Sie haben gesagt, Sie haben Code für "modulare Tests". Da dieser Code nicht hier ist, muss ich davon ausgehen, dass der Code nicht Teil dieser Funktion ist. Wenn Sie jedoch externen Code haben, der den Inhalt der Listen überprüfen soll, dann dürfen die Listen nicht nur lokale Variablen sein. Kein anderer Code kann auf sie zugreifen. Sie müssen diese Listen entweder zurückgeben oder Listen von außerhalb übernehmen, die Sie dann ausfüllen. Hier ist ein Beispiel für letzteres:

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; 

Der Aufrufer dieser Funktion einen TStrings Nachkommen für jede Liste angeben müssen. Sie könnten TStringList sein, oder sie könnten andere Nachkommen sein, wie TMemo.Lines, so dass Sie ihren Inhalt direkt in Ihrem Programm beobachten können. (Sie können nicht nur TStrings, obwohl sein, denn das ist eine abstrakte Klasse.)


Wie Sie sehen können, habe ich, um Ihren Code ein paar andere Änderungen vorgenommen. Der gesamte Code, der den Parameter Reenable verwendet, kann zu einer einzelnen Anweisung vereinfacht werden. Das liegt daran, dass das Aktivieren eines bereits aktivierten Steuerelements und das Deaktivieren eines Steuerelements, das bereits deaktiviert ist, keine Operationen sind.

Außerdem ist Name eine öffentliche Eigenschaft von TComponent. Sie müssen vor dem Lesen dieser Eigenschaft nicht auf TControl tippen, aber da Sie so oft anderswo tippen, war es sinnvoll, eine neue Variable einzuführen, die den typisierten Wert TControl enthält Code leichter zu lesen. Leichter zu lesender Code ist leichter zu verstehender Code und erleichtert das Debuggen.

+0

Hmm, danke für den Tipp über die Stringlist, Rob! Über diesen reaktivierbaren Parameter - nop, tyhere ist ein etwas anderer Grund. Es wäre ziemlich lang zu erklären, dass ich einen Teil der Apps-Quelle kopieren müsste. Auch Tipps zum Thema Komponenten. Ich wusste das, aber ich war mir nicht sicher, weil ich in fast jedem Beispiel diesen Code finde ... –

+0

Ich glaube, du hast vergessen, meine Frage zu beantworten: * Wie weißt du **, dass etwas mit deinem Code nicht stimmt? Ihre Behauptung, dass "keine Erklärungen mehr nötig sind", war falsch. –

+0

ich weiß es, weil wenn ich es mit Haltepunkten Schritt, gibt es keine Elemente in Stringlist Pllus, wenn ich mit dcus devre, thetre sind keine Variable oder Speicheradresse abgeholt und in der kontinuierlichen Code, wenn ich den Code, den ich brauche (derzeit es ist nur für modulare Tests), bekomme ich Runtime-Liste Out-of-Bounds Fehler. So weiß ich, dass etwas nicht stimmt. –

0

Das sieht sicher so aus, als müsste es funktionieren. Dies ist die Art von Sache, bei der der Debugger wahrscheinlich mit mehr helfen kann als wir hier können.

Versuchen Sie, die problematische Zeile nach unten in mehrere Zeilen umbrochen, etwa so:

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

Rebuild mit der „Use Debug DCU“ Option auf, und legen Sie einen Haltepunkt auf der wenn Aussage. Dann benutze F7, um deinen Weg durch die Logik zu verfolgen und zu sehen, was vor sich geht.

+0

Nop, funktioniert nicht. Nichts passiert mit irgendwelchen Stringlists. FindComponenet(); nimmt nur den Namen der Steuerung und das ist alles ... P.S. Ich benutzte dcu's ... –

2

, dass diese betonend basiert weitgehend auf Robs ausgezeichnete Vorschläge, es sieht aus, als ob Sie den Code vereinfachen könnte:

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; 

nicht klar, was die Stringlisten waren für, da deren Inhalt verloren gingen, wenn die Ausführung links Umfang dieses Verfahrens. Wenn Sie sie zurückgeben möchten, sollten Sie sie im aufrufenden Code erstellen und freigeben.

+0

Ja, danke, Problem theoretisch gefunden und beseitigt. Vielen Dank dafür, aber Stringlisten waren für das Sortieren - das ist in der Zeit der Ausführung aktiviert und welche comopoent ist nicht. Thasthow konnte ich durch reenable Parameter immer feststellen, ob sie aktiviert oder deaktiviert werden. Dies wurde nicht von meiner Frage abgedeckt, weil ich dachte, dass überhaupt kein Wert in Stringlisten gespeichert wurde. Danke nochmal, Entschuldigung für meine unangemessene Einstellung. An dieser Stelle hat jeder die richtige Antwort. ;) –

+1

... und du hast noch keinen von ihnen gewählt! Sie sollten Antworten (auf jede Frage, nicht nur Ihre eigenen), die Sie hilfreich finden, nach oben abstimmen und * Akzeptieren * die beste Antwort auf Ihre eigenen Fragen. – Argalatyr

+2

Wenn Sie sie im aufrufenden Code erstellen und freigeben, sollten Sie sie nicht zu 'var' -Parametern machen. Sehen Sie meine bearbeitete Antwort für ein Beispiel. –