Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Ereignisse richtig verteilen (https://www.delphipraxis.net/156406-ereignisse-richtig-verteilen.html)

schöni 1. Dez 2010 08:02

Ereignisse richtig verteilen
 
Hallo,

wir sollen im Informatikunterricht in einem Lehrgang eine Ereignisverarbeitung programmieren, wie sie in jeder heutigen GUI enthalten ist. Dazu habe ich mir eine Klassenbibliothek gebaut aus:

TMyControl --- TMyDesktop
|
TMyWindow

und eine TMyApplication, abgeleitet von TCustomApplication.

Nun zeichne ich ein Fenster auf meinen Desktop, das von der Maus verschoben können werden soll und 2 Checboxen
enthalten soll.

Hier so weit der Quelltext der Methode DoRun von TMyApplication:

Delphi-Quellcode:
procedure TMyApplication.DoRun;

procedure Execute;
var
  Event: TMyEvent;
  XX,YY: Integer;
  KeyCode: Word;
begin
  while FEventQueue.Count > 0 do
  begin
    //Event := FEventQueue.Extract(FEventQueue.IndexOf(0));
    Event := TMyEvent(FEventQueue.Items[0]);
    case Event.EventType of
      EVENT_KEYBOARD:      //TGFXCustomControl(Event.EventData.Sender).
        begin
          KeyCode := Event.EventData.Code;
          if (KeyCode and 15)=27 then terminate;
          if Keypressed then Terminate;
       end;
      EVENT_MOUSE_DOWN:    //TGFXCustomControl(Event.EventData.Sender).
        begin
          XX := Event.EventData.Position.X;
          YY := Event.EventData.Position.Y;
          TMyCustomControl(Event.EventData.Sender).DoMouseDown(Event.EventData.Sender, Shift, XX, YY);
        TMyCustomControl(Event.EventData.Sender).Invalidate;
        TMyCustomControl(Event.EventData.Sender).Redraw;
       end;
      EVENT_MOUSE_MOVE:    //TGFXCustomControl(Event.EventData.Sender).
        begin
          XX := Event.EventData.Position.X;
          YY := Event.EventData.Position.Y;
          TMyCustomControl(Event.EventData.Sender).DoMouseMove(Event.EventData.Sender, Shift, XX, YY);
        TMyCustomControl(Event.EventData.Sender).Invalidate;
        TMyCustomControl(Event.EventData.Sender).Redraw;
        end;
      EVENT_MOUSE_UP:      //TGFXCustomControl(Event.EventData.Sender).
        begin
          XX := Event.EventData.Position.X;
          YY := Event.EventData.Position.Y;
          TMyCustomControl(Event.EventData.Sender).DoMouseUp(Event.EventData.Sender, Shift, XX, YY);    
        TMyCustomControl(Event.EventData.Sender).Invalidate;
        TMyCustomControl(Event.EventData.Sender).Redraw;
       end;
    end;
    FEventQueue.Extract(Event);
  end;
end;

begin
  FMyDesktop.Invalidate;
  FMyDesktop.Show;
  repeat
    Index := 0;    

   //Für alle auf dem Desktop der Applikation befindlichen Komponenten:

    FDesktop.GetNewEvents;
   FDesktop.DoKeyEvent(Self, Key, Shift);
   DoMouseEvent(Self, Shift, X, Y);

   //Und nun alle irgendwo eingefügten Komponenten
         
   if self.ComponentCount>0 then
   begin
     TMyCustomControl(Components[Index]).Redraw;
     if FMyDesktop.Components[Index] is TMyWindow then TMyWindow(Components[Index]).Show;
     for Index:=self.ComponentCount-1 downto 0 do    
          FMyDesktop.DispatchEvents(Self.Components[Index], Key, Shift, X, Y);
   end;
   Inc(Index);
   if Index >= self.ComponentCount then Index := 0;
   
   Execute;
   
  until Keypressed;
  Terminate;
end;

Hier noch mein Hauptprogramm:

Delphi-Quellcode:
type
  TMyForm = class(TMyWindow)
  private
    FCheckBox1,
    FCheckBox2: TMyCheckBox;
  public
    procedure FormCreate(Sender: TObject);
    constructor Create(AOwner: TComponent); override;
   procedure Show; override;    
  end;

var
  Win: TMyForm;

procedure TMyForm.FormCreate(Sender: TObject);
begin
  FCheckbox1 := TMyCheckBox.Create(self);
  FCheckbox1.Caption := 'CheckBox1';
  FCheckBox1.Left := 5;
  FCheckBox1.Top  := 18;
  FCheckBox1.Width := 30;
  FCheckBox1.Height:= 12;
  FCheckbox1.Parent := self;

  FCheckbox2 := TMyCheckBox.Create(self);  
  FCheckbox2.Caption := 'CheckBox2';
  FCheckBox2.Left := 5;
  FCheckBox2.Top  := 31;
  FCheckBox2.Width := 30;
  FCheckBox2.Height:= 12;
  FCheckbox2.Parent := self;
end;
 
constructor TMyForm.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  OnMouseDown := @DoMouseDown;
  OnMouseMove := @DoMouseMove;
  OnMouseUp  := @DoMouseUp;
  OnCreate   := @FormCreate;
end;
 
procedure TMyForm.Show;
var i: Integer;
begin
  inherited Show;
  for i:=0 to ComponentCount-1 do
  if (Components[i]<>nil) then if (Components[i] is TMyCheckBox) then TMyCheckBox(Components[i]).Show;
end;

begin
  //Application: TMyApplication; ist in meiner Unit definiert. Ich verwende hier nicht das Original.
  Application.Initialize;
  Application.CreateForm(TMyForm, Win);
  Application.Run;
end;
Ich habe in TMyWindow Checkboxen eingefügt, die jedoch nicht gezeichnet werden.

Wie kann ich die Ereignisse günstiger als oben auf meine Klassen verteilen und warum ist mein Entwurf möglicherweise nicht optimal?

bernd_schreiber 1. Dez 2010 16:20

AW: Ereignisse richtig verteilen
 
Hallo,

Ich würde alle Klassen, die Ereignisse empfangen sollen in einer separaten Liste registrieren. Dann würde ich diese Liste abfragen und jedem selektierten bzw fokussierten Objekt die Ereignisse senden.

Pseudocode:
Delphi-Quellcode:
begin
  RegisterClass(MyApplic);
  RegisterClass(MyWindow);
  RegisterClass(MyDesktop);

  for Index:=0 to Registered.Count-1 do
  begin
    if TMyControl(Registered[Index]).Selected then
    begin
      TMyControl(Registered[Index]).DoEvent1;
      TMyControl(Registered[Index]).DoEvent2;
      TMyControl(Registered[Index]).DoEventN;
      ...
      Registered.Remove(Index);
    end;
  end;
Anschließend können/müssen die bearbeiteten Ereignisse aud der Liste entfernt werden, damit sie nicht noch einmal abgearbeitet werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:53 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