Windows-Messages sinnvoll verteilen
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Gemeinde,
in einen alten, von mir betreuten Programm wird sehr viel mit PostMessage gearbeitet, um von Unterformularen oder Threads irgendetwas an das Hauptformular zu schicken/signalisieren. Da gibt es an ein paar Stellen im Quelltext Notifizierungslisten (normales TList) oder es werden TWinControl-Objekte oder deren Handles per langer Constructor-Kette an den richtigen Ort gereicht, um die PostMessage mit einen Windowhandle zu versorgen. An einer Stelle gibt es auch eine böse globale Variable, wo die Instanz des Hauptformulars gespeichert wird. :evil: Alles in allen sehr unschön, durcheinander und irgendwie unnötig. Viele Programmteile bzw. Units müssen sich kennen, obwohl sie es eigentlich nicht müssten. Ich spiele seit einiger Zeit mit dem Gedanken den folgenden globalen Verteil-Mechanismus zu implementieren und würde mich über Kritik und Anregungen freuen!
Delphi-Quellcode:
Hier noch kleines Beispielprojekt (mit XE3 erstellt), was sinnbefreite Beispiele der Anwendung zeigt.
interface
uses Messages, System.Generics.Collections, Winapi.Windows, Vcl.Controls, System.SyncObjs; type IMessageDistributor = interface procedure Subscribe(const Msg : UINT; const Listener : TWinControl); overload; procedure Subscribe(const Msgs : array of UINT; const Listener : TWinControl); overload; procedure Unsubscribe(const Msg : UINT; const Listener : TWinControl); overload; procedure Unsubscribe(const Msgs : array of UINT; const Listener : TWinControl); overload; function PostMessageToSubscribers(const Msg : UINT; const WParameter : WPARAM = 0; const LParameter : LPARAM = 0) : Boolean; end; TMessageDistributor = class(TInterfacedObject, IMessageDistributor) strict private type TListenerList = TList<TWinControl>; strict private FMessageToListenerMapping : TDictionary<UINT, TListenerList>; FCritcalSection : TCriticalSection; public constructor Create; destructor Destroy; override; procedure Subscribe(const Msg : UINT; const Listener : TWinControl); overload; procedure Subscribe(const Msgs : array of UINT; const Listener : TWinControl); overload; procedure Unsubscribe(const Msg : UINT; const Listener : TWinControl); overload; procedure Unsubscribe(const Msgs : array of UINT; const Listener : TWinControl); overload; function PostMessageToSubscribers(const Msg : UINT; const WParameter : WPARAM = 0; const LParameter : LPARAM = 0) : Boolean; end; function MessageDistributor : IMessageDistributor; implementation var _MessageDistributor : IMessageDistributor; function MessageDistributor : IMessageDistributor; begin if not Assigned(_MessageDistributor) then begin _MessageDistributor := TMessageDistributor.Create; end; Result := _MessageDistributor; end; { TMessageDistributor } constructor TMessageDistributor.Create; begin FCritcalSection := TCriticalSection.Create; FMessageToListenerMapping := TObjectDictionary<UINT, TListenerList>.Create([doOwnsValues]); end; destructor TMessageDistributor.Destroy; begin FMessageToListenerMapping.Free; FCritcalSection.Free; inherited; end; function TMessageDistributor.PostMessageToSubscribers(const Msg : UINT; const WParameter : WPARAM = 0; const LParameter : LPARAM = 0) : Boolean; var Listeners : TListenerList; Listener : TWinControl; begin Result := False; FCritcalSection.Enter; try if FMessageToListenerMapping.TryGetValue(Msg, Listeners) then begin for Listener in Listeners do begin if Assigned(Listener) then begin Result := PostMessage(Listener.Handle, Msg, WParameter, LParameter); end; end; end; finally FCritcalSection.Leave; end; end; procedure TMessageDistributor.Subscribe(const Msgs : array of UINT; const Listener : TWinControl); var I : Integer; begin for I := Low(Msgs) to High(Msgs) do begin Subscribe(Msgs[I], Listener); end; end; procedure TMessageDistributor.Unsubscribe(const Msgs : array of UINT; const Listener : TWinControl); var I : Integer; begin for I := Low(Msgs) to High(Msgs) do begin Unsubscribe(Msgs[I], Listener); end; end; procedure TMessageDistributor.Subscribe(const Msg : UINT; const Listener : TWinControl); var Listeners : TListenerList; begin if FMessageToListenerMapping.TryGetValue(Msg, Listeners) then begin if Assigned(Listeners) then begin if not Listeners.Contains(Listener) then Listeners.Add(Listener); end; end else begin Listeners := TListenerList.Create; Listeners.Add(Listener); FMessageToListenerMapping.Add(Msg, Listeners); end; end; procedure TMessageDistributor.Unsubscribe(const Msg : UINT; const Listener : TWinControl); var Listeners : TListenerList; begin if FMessageToListenerMapping.TryGetValue(Msg, Listeners) then begin if Assigned(Listeners) then begin Listeners.Remove(Listener); end; end; end; |
AW: Windows-Messages sinnvoll verteilen
Weiß nicht ob es passt, aber vielleicht gibt es ein paar Anregungen: Event-Driven, Asynchronous Development with Delphi and the LKSL
|
AW: Windows-Messages sinnvoll verteilen
Warum willst du dich überhaupt auf Windows-Messages und auch die Verwendung von
Delphi-Quellcode:
festlegen?
PostMessage
Nimm doch einfach
Delphi-Quellcode:
und schon geht das auch auf jeder Plattform.
TThread.Queue
|
AW: Windows-Messages sinnvoll verteilen
Zitat:
Von daher ist die "Einschränkung" auf Windows-Messages in dem Sinne keine. Zitat:
Häufig senden sich in meinem Anwendungsfall aber auch Unterformulare untereinander oder zum Hauptformular Benachrichtigungen. Wie würde man das mit TThread.Queue lösen? Des Weiteren besteht ja schon die Botschaftsbehandlung durch entsprechende Message-Handler in den Formularen, so dass ich "nur" relativ schmerzlos das anmelden und senden der Botschaften in diesem Ansatz anpassen müsste. Ich wollte mit dem Posten des Quelltextes nur sicher gehen, dass ich nicht irgendetwas Elementares übersehen habe. Unter der Prämisse, dass es halt nur auf Windows läuft, was hältst du denn von diesem Lösungsansatz zum Entkoppeln der einzelnen Units untereinander? |
AW: Windows-Messages sinnvoll verteilen
Zitat:
Habe mir ein Lesezeichen gesetzt und werde das am Wochenende mal ausführlicher studieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz