[gelöst] Eigenes Event in Mainqueue hinzufügen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

[gelöst] Eigenes Event in Mainqueue hinzufügen

Beitrag von Michl »

Ein fröhliches Hallo in die Runde,

irgendwie steh ich gerade auf dem Schlauch.

Ich möchte gern ein eigene Komponente als Inplace-Editor in einem TDrawGrid verwenden. Das funktioniert alles soweit tadellos. Ändere ich jedoch die Formulargröße, so ändert sich die Zellengröße ebenfalls. Ich möchte gern diesen Editor ebenfalls in der Größe mit ändern. Gibt es eine Möglichkeit ein Event zur Zellgrößenänderung abzufangen (was ich nicht glaube) oder wie kann ich in der/die/das Queue vom Mainthread ein eigenes Event platzieren, dass erst nach der Größenänderung des Grids aufgerufen wird.

Ich stell mir das so vor:

Entweder (HitEdit ist mein Inplaceeditor):

Code: Alles auswählen

procedure TForm1.DrawGridDrawCell(Sender: TObject; aCol,
  aRow: Integer; aRect: TRect; aState: TGridDrawState);
begin
  if (aRow = DrawGrid.Row) and (aCol = DrawGrid.Col) and
     ((aRect.Left <> HitEdit.Left) or (aRect.Top <> HitEdit.Top) or
     (aRect.Right <> HitEdit.Left + HitEdit.Width) or
     (aRect.Bottom <> HitEdit.Top + HitEdit.Height)) then
    Synchronize(@DrawGridEditorChangeBounds);  //Das funktioniert ja nur in einem Thread nicht mit MainThread 
...
oder

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  DrawGrid.OnChangeBounds:=@DrawGridChangeBounds;
end;
 
procedure TForm1.DrawGridChangeBounds(Sender: TObject);
begin
  Synchronize(@DrawGridEditorChangeBounds);  //Einfach das Synchronize weg- und die Methode zum Einfügen eines Events am Ende der Main Queue hinzudenken
end; 
Wie könnte ich so ein Event am Ende der Main Queue (Grid muss erst gezeichnet werden, da bei OnChangeBounds die Zellgrößen noch nicht aktualisiert wurden) erstellen?

Danke

Michael
Zuletzt geändert von Michl am Sa 10. Jan 2015, 19:28, insgesamt 1-mal geändert.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von wp_xyz »

Schau dir mal den Quellcode der eingebauten Zell-Editoren an (TStringCellEditor, TButtonCellEditor, TCompositeCellEditor, etc., in Grids.pas). Wahrscheinlich wirst du da fündig.

Benutzeravatar
theo
Beiträge: 10873
Registriert: Mo 11. Sep 2006, 19:01

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von theo »

Verstehe vllt. nicht genau, aber meinst du sowas? http://wiki.freepascal.org/Asynchronous_Calls

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von marcov »

Ich habe ein einfache Klasse:

Code: Alles auswählen

 
      THelperObject = class
                                        constructor Create;virtual;
                        procedure execute; virtual;
                        procedure release; virtual;
                        procedure reset; virtual;
                   end;
 
Pro solcher Fall leite ich davon eine Klasse ab, und implementiere davon der Execute Methode und füge Kontext zu.

Zb
TDrawGridChangeMsg = class(THelperObject)
context : TForm1;
procedure execute; override;
end;

procedure TDrawGridChangeMsg.Execute
begin
context.DrawgridEditorChangeBounds;
end;
Dieses object sende ich dann nach der handle des Main Form mit Postmessage. Und Da rufe ich einfach msg.execute; msg.free an.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von Michl »

theo hat geschrieben:Verstehe vllt. nicht genau, aber meinst du sowas? http://wiki.freepascal.org/Asynchronous_Calls
Das war es, was ich gesucht hatte, hatte ich schon mal gelesen und nicht mehr gefunden. Eben probiert, funktioniert :D
wp_xyz hat geschrieben:Schau dir mal den Quellcode der eingebauten Zell-Editoren an (TStringCellEditor, TButtonCellEditor, TCompositeCellEditor, etc., in Grids.pas). Wahrscheinlich wirst du da fündig.
da hast Du Recht, evtl. kann ich mich da tatsächlich etwas reinlesen.

@marcov: ich verstehe das Vorgehen. Ich muss das aber erstmal ausprobieren, da das so nicht dem entspricht, wie ich das üblicherweise machen würde, keine Ahnung, wo da dann Hase im Pfeffer liegt. Aber ich will ja auch was dazulernen. Danke für den Ratschlag!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von marcov »

Michl hat geschrieben: @marcov: ich verstehe das Vorgehen. Ich muss das aber erstmal ausprobieren, da das so nicht dem entspricht, wie ich das üblicherweise machen würde, keine Ahnung, wo da dann Hase im Pfeffer liegt. Aber ich will ja auch was dazulernen. Danke für den Ratschlag!
Das Idee dahinten war meistens das man nur einen Messagehandler brauch zu implementieren nutzt, daneben sollte es auch Delphi Kompatibel bleiben. Das erste ist nützlich wenn man zb Komponenten Designtime auf den Form setzt, oder Teile eines Framework will einbinden durch nur Units an USES hin zu fügen.
Zuletzt geändert von marcov am Sa 10. Jan 2015, 00:44, insgesamt 1-mal geändert.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von Michl »

Ich habe nun eine Weile gespielt und diverse Tests gemacht. Für mein aktuelles Problem ist für mich die brauchbarste Lösung der Umbau vom
wp_xyz hat geschrieben:TCompositeCellEditor
Da ist, bis auf ein paar wenige Dinge, quasi schon alles für meine Komponente vorbereitet. Vielen Dank für den Hinweis!!! :D :D :D

Ich habe neben Application.QueueAsyncCall (theos Link) auch noch PostMessage(Handle, MY_MESSAGE, 1, 0); ausprobiert, was genauso funktioniert. Allerdings hole ich mir mit so einem Vorgehen neue Probleme ins Haus, die ich zuvor so nicht erkannt hatte und denen ich mit dem obigen Umbau aus dem Weg gehe.

@marcov: Ich habe auch das Vorgehen von Dir probiert, es funktioniert zwar, ich weiss jedoch nicht, ob Dich so richtig verstanden habe (speziell die PostMessage und das Empfangen)?!:

Code: Alles auswählen

type
  THelperObject = class
    constructor Create; virtual;
    procedure execute;  virtual;
    procedure release;  virtual;
    procedure reset;    virtual;
  end;
...
 
type
  TForm1 = class;
 
  TDrawGridChangeMsg = class(THelperObject)
    context: TForm1;
    procedure execute; override;
  end;
 
const
  EBOUNDSMSG = WM_USER + 1;
 
type
 
  TForm1 = class(TForm)
...
  private
    DrawGridChangeMsg: TDrawGridChangeMsg;
    procedure DrawGridEditorSetBounds(var Msg: TMessage); message EBOUNDSMSG;
  end;
 
...
 
procedure TDrawGridChangeMsg.execute;
begin
  context.DrawgridEditorChangeBounds;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  DrawGridChangeMsg:=TDrawGridChangeMsg.Create;
  DrawGridChangeMsg.Context:=Self;
...
end;
 
procedure TForm1.DrawGridEditorChangeBounds;
begin
  HitEdit.SetBounds(DrawGrid.CellRect(DrawGrid.Col, DrawGrid.Row));
end;
 
procedure TForm1.DrawGridChangeBounds(Sender: TObject);
begin
  PostMessage(Handle, EBOUNDSMSG, 0, LParam(DrawGridChangeMsg));
end;
 
procedure TForm1.DrawGridEditorSetBounds(var Msg: TMessage);
begin
  THelperObject(Msg.lParam).execute;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von marcov »

Ja, nur ein THelperObject(Msg.lParam).free nach der .Execute.

Strikt genommen soll man auch die Rückgabe von Postmessage prüfen. (der Queue kann voll sein, zb wenn die Mainthread nicht reagiert)

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Eigenes Event in Mainqueue hinzufügen

Beitrag von Michl »

Habe ich verstanden. Danke nochmal!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Antworten