Ereignis Auswahl beim Doppelklicken in der Entwurfsphase

Rund um die LCL und andere Komponenten
Antworten
siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Ereignis Auswahl beim Doppelklicken in der Entwurfsphase

Beitrag von siro »

Einen schönen guten Abend,
ich habe mal eine generelle Frage zu Komponenten in der Entwurfsphase:

Wenn ich eine Komponente auf das Formular ziehe und dann doppelt drauf klicke,
wird automatisch ein OnXXXX Ereignis erzeugt.
Zum Beispiel beim Button OnClick
Beim Editfeld OnChange, obwohl es hier ja auch OnClick gibt.

Wer bestimmt eigentlich welches Ereigniss beim Doppelklick erzeugt wird ?
Kann ich das in meinen Komponenten irgendwie steuern ?

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

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

Re: Ereignis Auswahl beim Doppelklicken in der Entwurfsphase

Beitrag von Michl »

Das wird per DefaultComponentEditor bestimmt. Dabei wird das best mögliche Event genutzt, was für die Komponente zur Verfügung steht. Reihenfolge: OnCreate (default), OnClick, OnChange.

Siehe:
http://wiki.freepascal.org/How_To_Write_Lazarus_Component#Property_editors

oder \components\ideintf\componenteditors.pas ca. Zeile 132:

Code: Alles auswählen

  The default component editor (TDefaultEditor) implements Edit to searches the
  properties of the component and generates (or navigates to) the OnCreate,
  OnChanged, or OnClick event (whichever it finds first).

Oder per Code ( \components\ideintf\componenteditors.pas):

Code: Alles auswählen

procedure TDefaultComponentEditor.EditProperty(const Prop: TPropertyEditor;
  var Continue: Boolean);
...
begin
  if not Assigned(FFirst) and (Prop is TMethodPropertyEditor) then
    FFirst := Prop;
  PropName := Prop.GetName;
  BestName := '';
  if Assigned(FBest) then
    BestName := FBest.GetName;
  // event priority is hardcoded:
  // first priority has FBestEditEvent (default: OnCreate), then OnClick and OnChange is the last
  if CompareText(PropName, FBestEditEvent) = 0 then
    ReplaceBest
  else
  if CompareText(BestName, FBestEditEvent) <> 0 then
    if CompareText(PropName, 'ONCHANGE') = 0 then
      ReplaceBest
    else
    if CompareText(BestName, 'ONCHANGE') <> 0 then
      if CompareText(PropName, 'ONCLICK') = 0 then
        ReplaceBest;
end;   
Zuletzt geändert von Michl am Fr 15. Dez 2017, 13:12, insgesamt 1-mal geändert.

Code: Alles auswählen

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

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Ereignis Auswahl beim Doppelklicken in der Entwurfsphase

Beitrag von siro »

Oh supi Michl,
vielen Dank für die "reichenhaltigen" Informationen.

Dann gibt das jetzt langsam Sinn.
Bei meinen Componenten, die keinen OnChange bzw. OnClick haben,
nimmt der PropertyEditor das erste verfügbare Ereignis, hab ich grad ausprobiert,
wobei die Ereignissortierung wohl stets alphabetisch ist. (kann man das eigentlich ändern)

Es ist also direkt im PropertyEditor verankert.
Ich dachte man könnte es evtl. mit einem Schlüsselwort hinter der Methode (Eigenschaft) festlegen...
Einen separaten PropertyEditor wollte ich jetzt nicht schreiben, obwohl ich das in
Delphi 3 schon mal angefangen hatte.

Aber die Grundlage ist nun da und mein Verständnis dazu wächst.

Hab vielen Dank für deine Mühe
und ein schönes Wochenende.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

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

Re: Ereignis Auswahl beim Doppelklicken in der Entwurfsphase

Beitrag von Michl »

Ich hatte das eben nochmal getestet. Für eine eigene Komponente, wenn man wirklich nur einen anderen Default Event Handler haben will, genügt es, einen eigenen ComponentEditor zu erstellen und in dessen Contructor das BestEditEvent zu setzen. Diesen dann noch registrieren und fertig. Das ist sehr unkompliziert.

Zum Beispiel wird das so bei dem TTimerComponentEditor gemacht (siehe \components\ideintf\componenteditors.pas):

Code: Alles auswählen

  TTimerComponentEditor = class(TDefaultComponentEditor)
  public
    constructor Create(AComponent: TComponent;
      ADesigner: TComponentEditorDesigner); override;
  end;
...
constructor TTimerComponentEditor.Create(AComponent: TComponent;
  ADesigner: TComponentEditorDesigner);
begin
  inherited Create(AComponent, ADesigner);
  BestEditEvent := 'ONTIMER';
end
...
initialization
  RegisterComponentEditor(TCustomTimer, TTimerComponentEditor)


Eine weitere Möglichkeit wäre es, einen eigenen Komponenteditor zu erstellen (abgeleitet von TComponentEditor oder eines Abkömmlings). Dort kann man die Procedure Edit überschreiben und per CreateComponentEvent (Unit PropEdits) einen eigenen Default Event Handler erstellen lassen.

Siehe z.B. C:\32fpc304\LazTrunk\components\ideintf\actionseditor.pas (wobei hier der EventHandler per Doppelklick auf einen ListBox-Eintrag erstellt wird):

Code: Alles auswählen

procedure TActionListEditor.lstActionNameDblClick(Sender: TObject);
var
  CurAction: TContainedAction;
begin
  if lstActionName.GetIndexAtY(lstActionName.ScreenToClient(Mouse.CursorPos).Y) < 0
  then Exit;
  CurAction := GetSelectedAction;
  if CurAction = nil then Exit;
  // Add OnExecute for this action
  CreateComponentEvent(CurAction,'OnExecute');
end;

Code: Alles auswählen

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

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Ereignis Auswahl beim Doppelklicken in der Entwurfsphase

Beitrag von siro »

Das wär ja simpel,
probier ich gleich mal aus

Juppi, nach einigen Anlaufschwierigkeiten funktioniert es nun.

Er hat TDefaultComponentEditor nicht gefunden.
Ich muss in die Uses Anweisung noch
ComponentEditors mit aufnehmen...

Und in das Package musste ich noch
IDEIntf
hinzufügen

Jetzt wird bei mir bei einem Doppelclick OnMouseUp aufgerufen.
Ist zwar Blödsinn, aber es funktioniert.

Code: Alles auswählen

 
 
uses .....ComponentEditors, .........;
 
Type TLAZ_SiroSliderComponentEditor = class(TDefaultComponentEditor)
  public
    constructor Create(AComponent: TComponent;
      ADesigner: TComponentEditorDesigner); override;
end;       
 
constructor  TLAZ_SiroSliderComponentEditor.Create(AComponent: TComponent;
  ADesigner: TComponentEditorDesigner);
begin
  inherited Create(AComponent, ADesigner);
  BestEditEvent := 'OnMouseUp';
end;
 
 
procedure Register;
begin 
  RegisterComponents('Laz_Siro', [TSliderHor]);           // die eigentliche Komponente
  RegisterComponentEditor(TSliderHor,TLAZ_SiroSliderComponentEditor);   // der Editor
end;             
 


Da hast Du mir SEHR weitergeholfen. Nochmals vielen Dank Michl.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Antworten