AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

MultiCaster in Delphi

Ein Thema von stoxx · begonnen am 20. Aug 2007 · letzter Beitrag vom 21. Aug 2007
Antwort Antwort
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#1

MultiCaster in Delphi

  Alt 20. Aug 2007, 20:42
hier mal eine allgemeine Klasse für Multicast Events ...

ein etwas schlechteres Beispiel:
http://www.delphipraxis.net/internal...ct.php?t=93201



(im folgenden Link kann man sehen, wie man die Klasse TMulticaster verwenden kann)
(es müssen aber noch die Setter Proceduren von EventMouseDown und EventMouseUp in dem Beispiel geändert werden)

http://www.delphipraxis.net/internal...253&highlight=



Delphi-Quellcode:
unit xClasses;

interface

uses Windows, classes, sysutils, ExtCtrls;




type





//==============================================================================

  TMethodReference = procedure of object;

  TMethodReferenceList = class(TObject)
  private
    FOwner : Tobject;

 strict private
    procedure AddRef(aMethodReference: TMethodReference);
    procedure RemoveRef(aMethodReference: TMethodReference);
    procedure Clear;
 protected
     FList: TList;
  public
    procedure Add(const Method : TMethod);
    procedure Remove(const Method : TMethod);
    constructor Create(Owner : TObject);
    destructor Destroy; override;
    procedure RemoveAllForAnObject(anObject: TObject);
    procedure Delete(Index: Integer);

  end;

//==============================================================================


  TMulticaster = class(TMethodReferenceList)
  strict private
    function Get_Item(Index : Integer) : TMethod;
    function Get_Count : Integer;
  public
// procedure Broadcast(EventArgs: TEventArgs);
    property Items[Index: Integer]: TMethod read Get_Item; default;
    property Count : Integer read Get_Count;

  end; // TCustomMultiCaster

//==============================================================================
// DATA MultiCaster

type
    // Eintrag der Liste
    TMMData = record
        MethodReference : TMethodReference;
        UserData : TObject;
    end;
//==============================================================================
  TDataMulticaster = class(TObject)
  strict private

    FList: TList;
    function Get_Item(Index : Integer) : TMethod;
    function Get_UserData(Index : Integer) : TObject;
    function Get_Count : Integer;
    procedure Clear;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Add(Const Method : TMethod; User : TObject); // es kann ein Userdefiniertes Object hinterlegt werden
    procedure Remove(const Method : TMethod);
    procedure RemoveAllForAnObject(anObject: TObject);
    property Items[Index: Integer]: TMethod read Get_Item; default;
    property Userdaten[Index : Integer] : TObject read Get_USerData;
    property Count : Integer read Get_Count;
    procedure Delete(Index: Integer);
  end; // TCustomMultiCaster

//==============================================================================


implementation




////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// TMultiCaster
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// TMethodReferenceList

constructor TMethodReferenceList.Create(Owner : TObject);
begin
  inherited create;
  FList := TList.Create;
  FOwner := Owner;
end;

//////////////////////////////////////////////////////////////////////////////

destructor TMethodReferenceList.Destroy;
begin
  Clear;
  FList.Free;
  inherited;
end;

////////////////////////////////////////////////////////////////////////////////

procedure TMethodReferenceList.Clear;
var pMethodReference: ^TMethodReference;
begin
  while (FList.Count > 0) do
  begin
    pMethodReference := FList.Items[0];
    Dispose(pMethodReference);
    FList.Delete(0);
  end;
end;

// TMethodReferenceList/////////////////////////////////////////////////////////



procedure TMethodReferenceList.AddRef(aMethodReference: TMethodReference);
var pMethodReference: ^TMethodReference;
    i: integer;
begin
  // Look at each method in the collection to see if aMethodReference has
  // already been added.
  for i := 0 to (FList.Count - 1) do
  begin

    pMethodReference := FList.Items[i];
    // Don't do anything if the method reference has already been stored.
    if ( TMethod(pMethodReference^).Code = TMethod(aMethodReference).Code )
      and ( TMethod(pMethodReference^).Data = TMethod(aMethodReference).Data )
      then exit;
  end;

  New(pMethodReference);
  pMethodReference^ := aMethodReference;
  FList.Add(pMethodReference);
end;

// TMethodReferenceList/////////////////////////////////////////////////////////

procedure TMethodReferenceList.RemoveRef(aMethodReference: TMethodReference);
var pMethodReference: ^TMethodReference;
    i: integer;
begin

  for i := (FList.Count - 1) downto 0 do
  begin
    pMethodReference := FList.Items[i];

    if ( TMethod(pMethodReference^).Code = TMethod(aMethodReference).Code )
      and ( TMethod(pMethodReference^).Data = TMethod(aMethodReference).Data ) then
    begin
      Dispose(pMethodReference);
      FList.Delete(i);
      exit;
    end; // von if begin
  end; // von for
end;
//==============================================================================
// Add und Remove (öffentlich) für die Methoden
//==============================================================================

procedure TMethodReferenceList.Add(const Method: TMethod);
begin
self.AddRef(TMethodReference(Method));
end;
//==============================================================================
procedure TMethodReferenceList.Remove(const Method: TMethod);
begin
self.RemoveRef(TMethodReference(Method));
end;

//==============================================================================
procedure TMethodReferenceList.Delete(Index: Integer);
begin
  self.FList.Delete(Index);
end;

//==============================================================================

procedure TMethodReferenceList.RemoveAllForAnObject(anObject: TObject);
var pMethodReference: ^TMethodReference;
    i: integer;
begin

  for i := (FList.Count - 1) downto 0 do
  begin
    pMethodReference := FList.Items[i];
    // If any procedure or function reference is associated with the passed
    // object then de-allocate its memory and remove the reference from FList.
    if ( TMethod(pMethodReference^).Data = anObject ) then
    begin
      Dispose(pMethodReference);
      FList.Delete(i);
    end; // then begin
  end; // for
end;


//==============================================================================


//procedure TMulticaster.Broadcast(EventArgs: TEventArgs);
//var i: integer;
// pNotifyEventArgs: ^TNotifyEventArgs;
//
//begin
// try
// for i := 0 to (FList.Count - 1) do
// begin
// pNotifyEventargs := FList.Items[i];
// pNotifyEventArgs^(FOwner, EventArgs);
//
// end;
// finally
// if assigned(EventArgs) then EventArgs.Free;
// end; // try..finally
//end; // broadcast

//==============================================================================

function TMulticaster.Get_Count: Integer;
begin
  result := FList.Count;
end; // Get_Count

//==============================================================================

function TMulticaster.Get_Item(Index : Integer): TMethod;
begin
 result := TMEthod(FList[Index]^);
end;

//==============================================================================

// DATA !!! MultiCaster
{ TDataMulticaster }


constructor TDataMulticaster.Create;
begin
inherited create;
FList := TList.Create;

end;

//==============================================================================

destructor TDataMulticaster.Destroy;
begin
  clear;
  FList.Free;
  inherited;
end;

//==============================================================================

procedure TDataMulticaster.Clear;
var pMMData: ^TMMData;
begin
  while (FList.Count > 0) do
  begin
    pMMData := FList.Items[0];
    Dispose(pMMData);
    FList.Delete(0);
  end;

end;

//==============================================================================

procedure TDataMulticaster.Add(const Method: TMethod; User: TObject);
var pMMData: ^TMMData;
    i: integer;
begin
  // Look at each method in the collection to see if aMethodReference has
  // already been added.
  for i := 0 to (FList.Count - 1) do
  begin

    pMMData := FList.Items[i];

    if (TMethod(pMMData.MethodReference).Code = TMethod(Method).Code ) and
       (TMethod(pMMData.MethodReference).Data = TMethod(Method).Data ) and
       (pMMData.UserData = User) then begin
          exit;
       end; // if


  end; // for

  New(pMMData);
  pMMData.MethodReference := TMethodReference(Method);
  pMMData.UserData := User;
  FList.Add(pMMData);

end;

//==============================================================================


procedure TDataMulticaster.Remove(const Method: TMethod);
var pMMData: ^TMMData;
    i: integer;
begin

  for i := (FList.Count - 1) downto 0 do
  begin
    pMMData := FList.Items[i];

    if (TMethod(pMMData.MethodReference).Code = TMethod(Method).Code ) and
       (TMethod(pMMData.MethodReference).Data = TMethod(Method).Data ) then begin
            Dispose(pMMData);
            FList.Delete(i);
// exit;
       end; // if
  end; // for
end; // Remove
//==============================================================================
procedure TDataMulticaster.RemoveAllForAnObject(anObject: TObject);
var pMMData: ^TMMData;
    i: integer;
begin
  for i := (FList.Count - 1) downto 0 do
  begin
    pMMData := FList.Items[i];
    if ( TMethod(pMMData.MethodReference).Data = anObject ) then
    begin
      Dispose(pMMData);
      FList.Delete(i);
    end; // then begin
  end; // for
end;

//==============================================================================


procedure TDataMulticaster.Delete(Index: Integer);
var pMMData: ^TMMData;
begin
  if Index <= Flist.count - 1 then begin
      pMMData := FList[Index];
      dispose(pMMData);
      FList.Delete(Index);
  end; // if Index < FList.count

end;

//==============================================================================

function TDataMulticaster.Get_Count: Integer;
begin
  result := FList.Count;
end;

//==============================================================================

function TDataMulticaster.Get_Item(Index: Integer): TMethod;
type
  pMMData = ^TMMData;
begin
 result := TMEthod( pMMData(FList[Index]).MethodReference);
end;


//==============================================================================


function TDataMulticaster.Get_UserData(Index: Integer): TObject;
type
  pMMData = ^TMMData;
begin
 result := pMMData(FList[Index]).UserData;
end;


end.
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
DMW

Registriert seit: 6. Sep 2006
Ort: Münster
269 Beiträge
 
Delphi XE Professional
 
#2

Re: MultiCaster in Delphi

  Alt 20. Aug 2007, 22:26
Da lobe ich mir C++Builder - dort ist es möglich, bereits vorhandene Events als Multicast-Events zu verwenden. Templates machen's möglich

Code:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <ucl/bcc/multicast.hpp>
#include <ucl/bcc/multicastspec.hpp>
#pragma hdrstop

#include "main_unit.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFrmMain *FrmMain;

//---------------------------------------------------------------------------
__fastcall TFrmMain::TFrmMain(TComponent* Owner) // Konstruktor
    : TForm(Owner)
{
        /*
         * ucl::bcc::asMulticast() erstellt das MulticastClosure-Objekt bei Bedarf.
         * die Objekte werden in der MulticastContainer-Klasse registriert und
         * gelöscht, wenn deren Destruktor aufgerufen wird.
         */

        // einen Event-Handler zu Button1->OnClick hinzufügen
    ucl::bcc::asMulticast (mcc, Button1->OnClick).push_back (this->AnotherEventHandler);

        // ein Closure explizit in ein Multicast-Closure umwandeln
    ucl::bcc::asMulticast (mcc, Button2->OnClick);

        // Referenz auf MultiCast-Objekt zurückgeben
    ucl::bcc::MulticastClosure1 <void, TObject*, ucl::bcc::ccFastcall>& mc
        = ucl::bcc::asMulticast (mcc, Button3->OnClick);

        // einen Event-Handler hinzufügen
    mc.push_front (this->Button1Click);

        // MulticastClosure-Objekte definieren eine Containerschnittstelle
    ucl::bcc::MulticastClosure1 <void, TObject*>::iterator i = mc.begin ();
    mc.insert (++i, this->Button2Click);

        // diese Anweisungen sind äquivalent:
    //mc (this);              // direkter Aufruf des MulticastClosure-Objekts
    //Button3->OnClick (this); // Aufruf des Events, dem das Objekt gehört
}

//---------------------------------------------------------------------------

void __fastcall TFrmMain::Button1Click(TObject */*Sender*/)
{
    MmoOutput->Lines->Add (AnsiString (__FUNC__) + " called.");
}
void __fastcall TFrmMain::Button2Click(TObject *Sender)
{
    MmoOutput->Lines->Add (AnsiString (__FUNC__) + " called.");
    if (Sender == Button2)
    {
        ucl::bcc::MulticastClosure1 <void, TObject*, ucl::bcc::ccFastcall>& mc
            = ucl::bcc::asMulticast (mcc, Button2->OnClick);

            // hier eine weitere Anwendung der Containerschnittstelle
        if (mc.contains (this->FooBar))
            mc.remove (this->FooBar);
        else
            mc.push_back (this->FooBar);
    }
}
void __fastcall TFrmMain::Button3Click(TObject */*Sender*/)
{
    MmoOutput->Lines->Add (AnsiString (__FUNC__) + " called.");
}

void __fastcall TFrmMain::AnotherEventHandler(TObject */*Sender*/)
{
    MmoOutput->Lines->Add (AnsiString (__FUNC__) + " called.");
}
void __fastcall TFrmMain::FooBar(TObject */*Sender*/)
{
    MmoOutput->Lines->Add (AnsiString (__FUNC__) + " called.");
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::BtnSwap13Click(TObject */*Sender*/)
{
    ucl::bcc::asMulticast (mcc, Button1->OnClick)
        .swap (ucl::bcc::asMulticast (mcc, Button3->OnClick));  
}
//---------------------------------------------------------------------------
Library und Demoprojekt hier:
http://www.audacia-software.de/de/win/ucl/index.htm
Moritz
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#3

Re: MultiCaster in Delphi

  Alt 21. Aug 2007, 21:35
Zitat von DMW:
Da lobe ich mir C++Builder - dort ist es möglich, bereits vorhandene Events als Multicast-Events zu verwenden. Templates machen's möglich
Angeber !
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
Antwort Antwort

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 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