2016-04-28 3 views
1

In meiner Anwendung habe ich mehrere Formulare, die zur gleichen Zeit sichtbar sein können und alle zeigen Speicherplatz (Dateien, Festplattengröße usw.) in der gleichen Größe Einheiten. Alle von ihnen zeigen Speicherplatz in Bytes, KB, MB, GB oder TB. Ich habe auch ein separates Einstellungsformular, in dem der Benutzer die Anzeigegröße ändern kann, die er in den anderen Formen möchte. Sobald der Benutzer im Einstellungsformular auf OK klickt, möchte ich, dass alle anderen (offenen) Formulare sofort ihre Größeneinstellungen ändern.So senden Sie ein Ereignis an mehrere Formulare in Delphi

Jedes Formular verfügt über eine geschützte Prozedur SetViewSettings, die sich um den Job kümmert. Sie sind alle Abkömmlinge einer Vorfahrenform, die SetViewSettings als virtuell und abstrakt definiert. Die tatsächlich angezeigten Formulare überschreiben die SetViewSettings-Methode des Vorfahren. Bis jetzt keine Probleme.

Weil ich mag nicht jede einzelne Form nennen (FormX.SetViewSetttings, FormY.SetViewSettings, etc.), ich die folgende Lösung verwenden:

procedure TApplicationForms.SetUnits; 
var 
    I: Integer; 
begin 
    for I := 0 to Screen.FormCount - 1 do 
    if Screen.Forms[I] is TfrAncestorInfo then 
     with Screen.Forms[I] as TfrAncestorInfo do 
     acSetUnits.Execute; 
end; 

Dieses Verfahren aus dem SettingsForm aufgerufen wird als Der Benutzer klickt auf OK. TFrAncestorInfo ist ein Nachkomme von TForm und deklariert die SetViewSettings-Methode als virtuell und abstrakt. acSetUnits ist eine in TfrAncestorInfo deklarierte Aktion, die nur SetViewSettings aufruft. Das alles funktioniert gut, aber das Risiko liegt darin, eine neue Abkömmlingsform von TFrAncestorInfo zu erstellen, während Sie vergessen, die SetViewSettings-Methode zu überschreiben. In diesem Fall werden Sie auf eine 'Abstract Error'-Ausnahme stoßen.

Gibt es Alternativen zum Aufrufen der SetViewSettings-Methode in den Formularen, ohne alle untergeordneten Formulare einzeln aufzulisten (aufzurufen)? Ich kenne Nachrichten und Ereignisse, aber ich weiß nicht, wie man diese in einer Situation mit mehreren Formen benutzt. Allgemein: Wie kann ich eine Nachricht an alle TFrAncestorInfo-Abkömmlingsformulare direkt senden oder ein Ereignis generieren, ohne sie einzeln aufzulisten?

+0

Eine einfachere Lösung wäre, die 'acSetUnits.Execute' zu ​​Graben, und machen' SetViewUnits' nicht abstrakt, sondern entweder leer oder mit minimalem shared Code, z.B. 'FViewUnits: = Wert'. Ziehen Sie auch die 'acSetUnits.Execute' ab und rufen Sie' SetViewUnits (newUnits) 'direkt auf. –

Antwort

4

Eine Option (es gibt viele andere mögliche Optionen) wäre, eine benutzerdefinierte Nachricht an jedes Formular zu senden. Sie müssen sich keine Gedanken über das Überschreiben von virtuellen/abstrakten Elementen, Typprüfungen usw. machen. Nur die Formulare, die einen Nachrichtenhandler implementieren, reagieren auf die Nachricht, der Rest ignoriert sie einfach.

const 
    WM_SETTINGS_UPDATED = WM_APP + 1; 

procedure TApplicationForms.SetUnits; 
var 
    I: Integer; 
begin 
    for I := 0 to Screen.FormCount - 1 do 
    Screen.Forms[I].Perform(WM_SETTINGS_UPDATED, 0, 0); 
end; 

type 
    TSomeForm = class(TBaseForm) 
    private 
    procedure WMSettingsUpdated(var Message: TMessage); message WM_SETTINGS_UPDATED; 
    protected 
    procedure SetViewSettings; 
    end; 

procedure TSomeForm.WMSettingsUpdated(var Message: TMessage); 
begin 
    SetViewSettings; 
end; 

procedure TSomeForm.SetViewSettings; 
begin 
    //... 
end; 
+0

Das macht genau das, wonach ich gesucht habe. Die Lösung eliminiert auch die TAction, wie @Gerry vorgeschlagen hat. –

+0

Sie können auch eine TAction-Sendung verwenden. So funktioniert beispielsweise die Funktion 'TStatusBar.AutoHint'. Wenn die Eigenschaft 'TApplication.Hint' gesetzt ist (z. B. von einem Menüelement) und 'TApplication.OnHint' nicht zugewiesen ist, führt' TApplication' eine 'THintAction' aus, die in der gesamten App gesendet wird. 'TStatusBar' reagiert auf diese Übertragung durch Überschreiben der virtuellen' TComponent.ExecuteAction() 'Methode. So kann jede 'TStatusBar' auf einem Formular den gleichen' Hint' Wert anzeigen. Sie könnten eine benutzerdefinierte TAction senden, auf die alle Ihre interessierten Formulare reagieren können. –

+0

[System.Messaging] (http://docwiki.embarcadero.com/Libraries/en/System.Messaging) ist eine weitere Option, die auf allen Plattformen funktioniert und nicht auf Formulare beschränkt ist –