Recent

Author Topic: Creating descendants of TComponent  (Read 477 times)

egsuh

  • Hero Member
  • *****
  • Posts: 625
Creating descendants of TComponent
« on: January 19, 2021, 02:44:07 am »
I'd like to create my custom treeview like following, adding some pre-defined actions so that I do not have to write the same codes (like DragDrop event handlers, etc.) multiple times.  Following codes compiles well, but I haven't applied yet (not executed yet).

Please comment on the following approach, and better ways, if any. 

Can I use TCustomTreeView instead?

Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.    { TaqTreeView }
  4.  
  5.    TaqTreeView = class(TTreeView)
  6.       procedure DragDrop(Sender, Source: TObject; X, Y: Integer);
  7.       procedure DragOver(Sender, Source: TObject; X, Y: Integer;
  8.           State: TDragState; var Accept: Boolean);
  9.    private
  10.       function MoveTreeNode(SNode: TTreeNode; TTV: TTreeView): TTreeNode;
  11.    public
  12.       constructor Create(AnOwner:TComponent);
  13.    end;
  14.  
  15. implementation
  16.  
  17. procedure TaqTreeView.DragOver(Sender, Source: TObject; X, Y: Integer;
  18.   State: TDragState; var Accept: Boolean);
  19. begin
  20.      // .....
  21.  
  22.       Accept := True;
  23. end;
  24.  
  25. procedure TaqTreeView.DragDrop(Sender, Source: TObject; X, Y: Integer);
  26. begin
  27.      //......
  28. end;
  29.  
  30. constructor TaqTreeView.Create(AnOwner: TComponent);
  31. begin
  32.    inherited Create(AnOwner);
  33.  
  34.    OnDragDrop:= DragDrop;
  35.    OnDragOver:= DragOver;
  36. end;

Blaazen

  • Hero Member
  • *****
  • Posts: 3028
  • POKE 54296,15
    • Eye-Candy Controls
Re: Creating descendants of TComponent
« Reply #1 on: January 19, 2021, 03:12:49 am »
The way you do it is wrong. Ancestors already have (virtual) methods DragDrop and DragOver. You implement them again and assign them to events.
You'd better override those methods (mark them override;) and call inherited; in their bodies.
Also, mark constructor with override; because it's virtual too.

Side note:
Assigning events in code should be (in {$mode objfpc}):
   OnDragDrop:=@DragDrop;
   OnDragOver:=@DragOver;
but do not use it here.
Lazarus 2.1.0 r64546 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

egsuh

  • Hero Member
  • *****
  • Posts: 625
Re: Creating descendants of TComponent
« Reply #2 on: January 19, 2021, 04:01:45 am »
@Blaazen

Thank you Blaazen, I wanted this kind of comments. But it says that it should be controlled by OnDragOver handler.

Quote
When an OnDragOver handler is installed, Accept is set to True and can be changed by the handler.

at

https://lazarus-ccr.sourceforge.io/docs//lcl/controls/tcontrol.dragover.html

Anyway I might have to override DragOver method.

Regarding @ before function name, I'm using {$mode Delphi} so I do not need @.

Blaazen

  • Hero Member
  • *****
  • Posts: 3028
  • POKE 54296,15
    • Eye-Candy Controls
Re: Creating descendants of TComponent
« Reply #3 on: January 19, 2021, 07:24:37 am »
Some drag method of LCL calls DragOver and DragOver calls OnDragOver (if there's any).
Code: Pascal  [Select][+][-]
  1. procedure TControl.DragOver(Source: TObject; X,Y : Integer; State: TDragState;
  2.   var Accept:Boolean);
  3. begin
  4.   {$IFDEF VerboseDrag}
  5.   DebugLn('TControl.DragOver ',Name,':',ClassName,' XY=',IntToStr(X),',',IntToStr(Y));
  6.   {$ENDIF}
  7.   Accept := Assigned(FOnDragOver);
  8.   if Accept then
  9.     FOnDragOver(Self,Source,X,Y,State,Accept);
  10. end;

So you declare
Code: Pascal  [Select][+][-]
  1. procedure DragOver(Sender, Source: TObject; X, Y: Integer;
  2.           State: TDragState; var Accept: Boolean); override;

and now it's up to you. You probably don't need to call inherited. You can manage calling of OnDragOver yourself or do not use it at all etc.
Code: Pascal  [Select][+][-]
  1. procedure TaqTreeView.DragOver(Sender, Source: TObject; X, Y: Integer;
  2.   State: TDragState; var Accept: Boolean);
  3. begin
  4.      // .....
  5.  
  6.       Accept := True;
  7. end;
Lazarus 2.1.0 r64546 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

egsuh

  • Hero Member
  • *****
  • Posts: 625
Re: Creating descendants of TComponent
« Reply #4 on: January 19, 2021, 08:45:51 am »
Thank you for sharing these codes. I looks like I don't have to assign anything to OnDragOver handler, as you said. This is good for me for convenience. 

PascalDragon

  • Hero Member
  • *****
  • Posts: 2748
  • Compiler Developer
Re: Creating descendants of TComponent
« Reply #5 on: January 19, 2021, 09:00:15 am »
Can I use TCustomTreeView instead?

The difference between TTreeView and TCustomTreeView is mainly that the former provides various properties as published. So if you want to control which properties are published and which are not (especially if you don't want some published that TTreeView declares as such), you better inherit from TCustomTreeView.

egsuh

  • Hero Member
  • *****
  • Posts: 625
Re: Creating descendants of TComponent
« Reply #6 on: January 19, 2021, 09:00:43 am »
But I cannot override TTreeview.DragOver. It says there are no method to override. There exists TControl.DragOver, but not TTreeview's one is not defined. So, I'll first check writing DragOver without assigning OnDragOver handler, and then will assign the event handler if fail.

Blaazen

  • Hero Member
  • *****
  • Posts: 3028
  • POKE 54296,15
    • Eye-Candy Controls
Re: Creating descendants of TComponent
« Reply #7 on: January 19, 2021, 11:25:37 am »
I just test and it works:
Code: Pascal  [Select][+][-]
  1. { TMyTreeView }
  2.  
  3.   TMyTreeView = class(TCustomTreeView)
  4.   protected
  5.     procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
  6.   end;
The list of parameters must be the same. Unit ComCtrls must be in uses. It works for TTreeView too.
Lazarus 2.1.0 r64546 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

 

TinyPortal © 2005-2018