5 Stimmen

Vergleich eines Zeigers mit dem Wert einer Funktion in Delphi

Wie kann ich die Wert einer Variablen, die einen Zeiger auf eine Funktion mit einer Funktionsadresse enthält?

Ich bearbeite gerade einen Code, der in Delphi 2007 nicht funktioniert. Die Erklärung ist:

var
  EditorFrameWindow: Function: HWnd Of Object = Nil;

In einer Formularaktivierung, habe ich:

procedure TEditForm.FormActivate(Sender: TObject);
begin
  EditorFrameWindow := GetFrameWindow;
end;

Und im Formular Deaktivierung habe ich:

procedure TEditForm.FormDeactivate(Sender: TObject);
begin
  if EditorFrameWindow = GetFrameWindow then
    EditorFrameWindow := nil;
end;

Was also passiert, ist, dass das Formular zweimal deaktiviert wird, und es schlägt fehl, da nichts anderes aktiviert wurde. FormDeactivate wird aufgerufen, es passt, und das globale EditorFrameWindow wird auf (null,null) gesetzt (laut Debugger). Dann wird es erneut aufgerufen, und die in der Variablen gespeicherte Funktion wird aufgerufen, aber natürlich ist keine gespeichert, also springt es durch nil und erzeugt eine Ausnahme.

Was sollte ich tun, um dies zu verhindern? (Das Framework wurde auf ein Registerkartensystem umgestellt, so dass sich die Bedienung wahrscheinlich geändert hat).

15voto

mghie Punkte 31618

Würde

procedure TEditForm.FormDeactivate(Sender: TObject);
begin
  if Assigned(EditorFrameWindow) and (EditorFrameWindow = GetFrameWindow) then
    EditorFrameWindow := nil;
end;

zufällig arbeiten?

Bearbeiten:

Sie vergleichen nicht die Adressen von Funktionen, sondern die Ergebnisse dieser Funktionen. Auch wenn der oben korrigierte Code keine Ausnahme mehr auslösen kann, kann es also sein, dass er nicht das tut, was Sie wollen. Eine andere Funktion, die das gleiche Ergebnis liefert, würde auch den Event-Handler zurücksetzen.

Um wirklich zu prüfen, ob die Variable auf einen bestimmten Event-Handler gesetzt ist, müssen Sie beide Elemente in der TMethod Rekord. Etwa so:

procedure TEditForm.FormDeactivate(Sender: TObject);
begin
  if (TMethod(EditorFrameWindow).Code = @TForm1.GetFrameWindow)
    and (TMethod(EditorFrameWindow).Data = Self)
  then
    EditorFrameWindow := nil;
end;

12voto

Rob Kennedy Punkte 158781

Es gibt zwei Möglichkeiten für den Vergleich von Methodenzeigern. Methodenzeiger bestehen aus zwei Zeigern, einem Codezeiger und einem Objektzeiger. Die Delphi-eigene Methode zum Vergleich von Methodenzeigern vergleicht nur die Codezeiger und sieht folgendermaßen aus:

if @EditorWindowMethod = @TEditForm.GetFrameWindow then
  EditorWindowMethod := nil;

Sie prüft, ob der Codezeiger in der Datei EditorWindowMethod mit der Anfangsadresse der Datei GetFrameWindow Methode in TEditForm . Es wird nicht geprüft, ob die Objektverweis sur EditorWindowMethod ist dasselbe wie Self . Wenn Sie sicherstellen wollen, dass die Objektreferenzen ebenfalls gleich sind, müssen Sie den Methodenzeiger in seine Bestandteile zerlegen, indem Sie die TMethod Aufzeichnung, die Mghie's Antwort demonstriert. (Und Sie werden wahrscheinlich hacer Sie sollten die Objektverweise vergleichen, da es sich so anhört, als hätten Sie mehrere Bearbeitungsformulare. Sie haben alle das gleiche GetFrameWindow Codezeiger, aber sie haben unterschiedliche Objektreferenzen).

Der Grund für die @ im Code soll dem Compiler mitteilen, dass Sie auf die Methodenzeiger verweisen wollen. Ohne diese Angabe wird der Compiler versuchen, die aufrufen die Methodenzeiger, und das war es, was Sie in Schwierigkeiten gebracht hat. Das erste Mal, als das Fenster deaktiviert wurde, haben Sie genannt. EditorWindowMethod und vergleicht das resultierende Fensterhandle mit dem Rückgabewert von aufrufen GetFrameWindow . Sie haben natürlich übereingestimmt, also haben Sie die Zuordnung aufgehoben. EditorWindowMethod . Als das Formular das nächste Mal deaktiviert wurde, versuchten Sie, die EditorWindowMethod wieder, aber es war ein Null-Zeiger.

Sie sollten in Erwägung ziehen, sich aus der Abhängigkeit von Aktivierungs- und Deaktivierungsmeldungen zu lösen. Prüfen Sie stattdessen einfach, ob das Formular aktiv ist in GetFrameWindow .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X