Recent

Author Topic: help with a custom drop down form  (Read 14197 times)

taazz

  • Hero Member
  • *****
  • Posts: 5364
help with a custom drop down form
« on: February 06, 2013, 04:32:24 am »
Hello everyone,

I'm looking for examples on creating a drop down form for the people with delphi background I'm trying to replicate the mastang peak TDropDownForm as close as possible except from the rolling effects. The main requirements are
1) all keyboard messages must be forwarded to the form opens it unless I override the method and handle some of them.
2) when visible the background form must keep on painting it self  as the active form and last focused control keeps getting the messages forwarded and if it is an edit it keeps showing the cursor.

In sort I want it to behave just like the drop down of a combo box with out the limitation of a list box in it. Any one has done anything similar?

Thank you in advance.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Luc

  • New Member
  • *
  • Posts: 35
Re: help with a custom drop down form
« Reply #1 on: May 11, 2013, 11:37:58 pm »
Hi Taaz,

I'm looking for the same kind of component in order to extend the classic combobox behavior. Sorry, no answer to your question yet... I was investigating the possibility to do it with a resizable panel (but panel shows only in parent form)  then with a custom form (but previous form/control looses focus). I was thinking of using a THintWindow but no success till now.

I hope to have better news soon. Did anyone else already solve this point ?

Regards
Luc


« Last Edit: May 11, 2013, 11:39:34 pm by Luc »
Win 10 (Running in Parallel VM - Mac OSX) - Lazarus 2.0.4 - i386-win32/win64

Blaazen

  • Hero Member
  • *****
  • Posts: 3034
  • POKE 54296,15
    • Eye-Candy Controls
Re: help with a custom drop down form
« Reply #2 on: May 12, 2013, 12:27:07 am »
AFAIK Lazarus has no cross-platform solution for this. (I don't know about single platform solution too). IMO the best you can do is something similar to Lazarus auto complete window (I mean CTRL+Space in Source Editor).
Lazarus 2.3.0 rmain-2_3-280-g5db1922e37 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/

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7508
  • Debugger - SynEdit - and more
    • wiki
Re: help with a custom drop down form
« Reply #3 on: May 12, 2013, 01:29:55 am »
You could look at the source editor hint (THintWindow).

I think it comes close to what you want.

Luc

  • New Member
  • *
  • Posts: 35
Re: help with a custom drop down form
« Reply #4 on: May 12, 2013, 09:18:32 am »
Thanks for your help.

THintWindow seems to be the best way. I did a small test and it works pretty well, even if I have to do some more changes in order to remove dependency with the parent form and allow Hintwindow resizing at runtime. I'll post a sample componant ASAP as a starting point.
Win 10 (Running in Parallel VM - Mac OSX) - Lazarus 2.0.4 - i386-win32/win64

Luc

  • New Member
  • *
  • Posts: 35
Re: help with a custom drop down form
« Reply #5 on: May 14, 2013, 07:50:01 pm »
Finally, here is a first attempt to extend the classic combobox. It is not working perfectly yet but it allows to add a resizable dropdown form to almost any control. I tried to find how the Lazarus team did the IDE Code Completion ToolTip  implementation but I didn't find the right code till now.

I use a THintWindow and a TTimer to get the mouse msg when resizing outside the application window and I added a StatusBar. I can neither make the THintWindow automatically handle resizing (without the TTimer trick) nor I can have the SizeGrip appear on the StatusBar (even when I set the THintWindow borderStyle to bsSizable).

I'm missing some points there. Waiting for any advice to keep on working.

Any comments are welcome.

TODO : Hide the Dropdown form when parent window is moved or resized.
 
Code: [Select]
{--------------------------------------------------------------------------------
  Description : TAdvxComboBox
  Luc DAVID - 2013
--------------------------------------------------------------------------------}

unit AdvxCombobox;
{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

uses
  LResources,
  {$IFDEF WINDOWS}
  Windows,
  {$ENDIF}
  SysUtils, Classes, Controls, Forms,
  ExtCtrls, StdCtrls, Graphics, ComCtrls,
  LCLType, LCLIntf, LCLProc, LMessages, Messages;

type


  { TAdvxSizeablePanel }

  TAdvxSizeablePanel = class(THintWindow)
  private
    FResizing: Boolean;
    FStatusBar: TStatusBar;
    FTopLeft: TPoint;
    FTimer: TTimer;
    procedure SetFResizing(AValue: Boolean);
    procedure DoOnTimer(Sender: TObject);
  protected
    procedure DoOnMouseEnter(Sender: TObject);
    procedure DoOnMouseLeave(Sender: TObject);
    procedure DoOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure DoOnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    property Resizing: Boolean read FResizing write SetFResizing;
  end;

  TAdvxDropDownPanel = class(TAdvxSizeablePanel)
  private
    FEditCtrl: TEdit;
  public
    property EditCtrl: TEdit read FEditCtrl write FEditCtrl;
  end;

  { TAdvxCustomComboBox }

  TAdvxCustomComboBox = class(TPanel)
   private
     FEditBox: TEdit;
     FDropDownBtn: TButton;
     FDropDownPanel: TAdvxDropDownPanel;
   protected
     procedure DoShowDropDownPanel(Sender: TObject);
     procedure DoHideDropDownPanel(Sender: TObject);
   public
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
     property DropDownPanel: TAdvxDropDownPanel read FDropDownPanel;
   end;

implementation

{ TAdvxSizeablePanel }

procedure TAdvxSizeablePanel.DoOnMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if FResizing then Exit;
  Resizing := (Screen.cursor = crSizeNWSE);
  Inherited;
end;

procedure TAdvxSizeablePanel.DoOnMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Resizing := False;
  inherited;
end;

constructor TAdvxSizeablePanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Color := clWindow;
  FStatusBar := TStatusBar.Create(Self);
  FStatusBar.Parent := Self;
  FStatusBar.OnMouseEnter:= DoOnMouseEnter;
  FStatusBar.OnMouseLeave:= DoOnMouseLeave;
  FStatusBar.OnMouseDown := DoOnMouseDown;
  FStatusBar.OnMouseUp   := DoOnMouseUp;
  FTimer := TTimer.Create(Self);
  FTimer.Enabled:=False;
  FTimer.Interval:=5;
  FTimer.OnTimer:= DoOnTimer;
end;

procedure TAdvxSizeablePanel.SetFResizing(AValue: Boolean);
begin
  if FResizing=AValue then Exit;
  FResizing:=AValue;
  FTimer.Enabled := FResizing;
end;

procedure TAdvxSizeablePanel.DoOnTimer(Sender: TObject);
var
p: TPoint;
begin
  p := Mouse.CursorPos;
  P := ScreenToControl(p);
  Width:= p.x+3;
  Height := p.y+3;
  invalidate;
  Application.ProcessMessages;
end;

procedure TAdvxSizeablePanel.DoOnMouseEnter(Sender: TObject);
begin
  Screen.cursor := crSizeNWSE;
end;

procedure TAdvxSizeablePanel.DoOnMouseLeave(Sender: TObject);
begin
  Screen.Cursor := crDefault;
end;

{ TAdvxCustomComboBox }

constructor TAdvxCustomComboBox.Create(AOwner: TComponent);
Const
w = 180;
h = 27;
begin
  inherited Create(AOwner);
  ParentColor:=False;
  Color := cl3DLight;
  FEditBox := TEdit.Create(Self);
  FDropDownBtn := TButton.Create(Self);
  FDropDownPanel := TAdvxDropDownPanel.Create(Self);


  Width := w;
  Height:= h;

  With FEditBox do
  begin
    Parent := Self;
    SetBounds(2,2, w-24,22);
    BorderStyle:= bsNone;
  end;


  With FDropDownBtn do
  begin
    Parent := Self;
    SetBounds(FEditBox.Left+FEditBox.Width + 1, 4,20,20);
    OnClick := DoShowDropDownPanel;
  end;

  With FDropDownPanel do
  begin
    EditCtrl := FEditBox;
    Visible:=False;
    Width := Self.Width+100;
    Height := 300;
    OnClick := DoHideDropDownPanel;
  end;

end;

destructor TAdvxCustomComboBox.Destroy;
begin
  inherited Destroy;
end;

procedure TAdvxCustomComboBox.DoShowDropDownPanel(Sender: TObject);
var
P: TPoint;
R: TRect;
F: TCustomForm;
begin
  if FDropDownPanel.Showing
     then FDropDownPanel.Hide
     else begin
          F := GetParentForm(Self);
          P.x := Left;
          P.y := Top + Height;
          P := F.ControlToScreen(P);
          R := Rect(p.x, p.y, p.x+FDropDownPanel.Width, p.y+FDropDownPanel.Height);
          FDropDownPanel.FTopLeft := P;
          FDropDownPanel.ActivateHint(R, '');
          FDropDownPanel.SetFocus;
          end;
end;

procedure TAdvxCustomComboBox.DoHideDropDownPanel(Sender: TObject);
begin
  if FDropDownPanel.Showing and Not FDropDownPanel.Resizing
     then FDropDownPanel.Hide
end;

initialization

end.


Note : On windows 8, Dropdown panel doesn't show up at the right screen position...
Win 10 (Running in Parallel VM - Mac OSX) - Lazarus 2.0.4 - i386-win32/win64

taazz

  • Hero Member
  • *****
  • Posts: 5364
Re: help with a custom drop down form
« Reply #6 on: May 14, 2013, 09:05:36 pm »
So far I have tackled the problem only on windows and I am confident that I can stop the underline form of showing that it lost focus. I haven't gone any fearther though since my extended combo boxes do not require resize or the edit control to have or show focus. they are mostly color selectors. I will try to create an extended lookup combo at some point wich will support multiple columns and resizing but I have to solve the same problem on qt and gtk before going any farther.

The next free time I get I will study the lazarus auto complete window because its closer to my goal than the hintwindow or at least I think so. In any event I'll post my results here too.

thank you for your component I'll study it the next week end.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

taazz

  • Hero Member
  • *****
  • Posts: 5364
Re: help with a custom drop down form
« Reply #7 on: July 02, 2013, 08:34:33 am »
I'm back working on that problem again and finally took a look on your code the road you took create more problems than it solves. I am in a good spot right now with my implementation I only need to

1) make the border resizable with out a title bar
2) add keyboard support some how.
3) Respond to the mouse wheel.
4) Test if it can accept components on top of it with out problems.

Here is what I have.

Code: [Select]
uses
  Classes, SysUtils, Forms, LMessages, LCLIntf, LCLType, types, Themes,
  Graphics, Controls, StdCtrls;

type
  { TEvsDropDownForm }

  TEvsDropDownForm = class(TCustomForm)
  private
    FEdit : TCustomEdit;
  protected
    //procedure wmActive(var Message :TLMessage); message LM_ACTIVATE;
    procedure MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : Integer); override;
    procedure Click; override;
    procedure Activate; override;
    procedure CreateParams(var Params : TCreateParams); override;
    procedure DoShow; override;
    procedure DoHide; override;
    procedure AppDeactivate(sender:TObject);
  public
    constructor Create(AOwner: TComponent; aPopupParent : TCustomForm; aEdit:TCustomEdit); reintroduce;
  end;

implementation

function PointInRect(const aPoint:TPoint; const aRect:TRect):Boolean;
begin
  Result := (aPoint.x >= aRect.Left) and (aPoint.Y <= aRect.Right) and (aPoint.y >= aRect.Top) and (aPoint.y <= aRect.Bottom);
end;

constructor TEvsDropDownForm.Create(AOwner : TComponent; aPopupParent : TCustomForm; aEdit : TCustomEdit);
begin
  inherited CreateNew(AOwner, 1);
  BorderStyle := bsNone;
  Parent := nil;
  FEdit := aEdit;
  PopupParent := aPopupParent;
  SetCapture(Handle);
end;

procedure TEvsDropDownForm.MouseDown(Button : TMouseButton;
  Shift : TShiftState; X, Y : Integer);
begin
  if not PointInRect(Classes.Point(X,Y), Classes.Rect(0,0,Width,Height)) then Hide;
  inherited MouseDown(Button, Shift, X, Y);
end;

procedure TEvsDropDownForm.Click;
begin
  inherited Click;
  ReleaseCapture;
  Hide;
end;

procedure TEvsDropDownForm.Activate;
begin
  inherited Activate;
  if Assigned(FEdit) then FEdit.SetFocus
  else if Assigned(PopupParent) then PopupParent.SetFocus;
  //SetCapture(Handle);
end;

procedure TEvsDropDownForm.CreateParams(var Params : TCreateParams);
begin
  Params.Style := (Params.Style or WS_POPUP or WS_THICKFRAME) and not WS_DLGFRAME;// ;
  inherited CreateParams(Params);
  //Params.Style := 2257518592;
  //Params.ExStyle := 65536;
  //showmessage
end;

procedure TEvsDropDownForm.DoShow;
begin
  inherited DoShow;
  SetCapture(Handle);
  Application.AddOnDeactivateHandler(@AppDeactivate, False);
end;

procedure TEvsDropDownForm.DoHide;
begin
  inherited DoHide;
  Application.RemoveOnDeactivateHandler(@DoHide);
  ReleaseCapture;
end;

procedure TEvsDropDownForm.AppDeactivate(sender : TObject);
begin
  Hide;
end;

By the way the createParams has no effect at this point I think it is safe to remove it I'm using it to test the no title with borders implementation but what ever I do I can't seem to hit the spot. the numbers in comments are the ones I need to make work it already works with the existing params in delphi.
« Last Edit: July 02, 2013, 09:08:00 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Blaazen

  • Hero Member
  • *****
  • Posts: 3034
  • POKE 54296,15
    • Eye-Candy Controls
Re: help with a custom drop down form
« Reply #8 on: July 02, 2013, 11:53:00 am »
Hello, a quick look on the code, I see a function "PointInRect". Lazarus already has a function "PtInRect" for the same job, it is in "LCLIntf" (which you already have in uses).
Lazarus 2.3.0 rmain-2_3-280-g5db1922e37 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/

taazz

  • Hero Member
  • *****
  • Posts: 5364
Re: help with a custom drop down form
« Reply #9 on: July 02, 2013, 12:51:05 pm »
:) thanks for the tip I haven't got used to the teams abbreviations when I was looking for one didn't think of abbreviating point to pt and it was faster to write it that searching the disk for one which would have failed. Oh well lesson learned.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

DtC17

  • New Member
  • *
  • Posts: 13
Re: help with a custom drop down form
« Reply #10 on: July 08, 2013, 01:45:45 am »
I believe I have what you want. It's called a TBigCombo / TBigList.
These reside in a fairly large library of mine -- I shall send them to you (the complete Lazarus package) if you would be so kind to provide me with your e-mail address.

jamestien

  • New Member
  • *
  • Posts: 35
Re: help with a custom drop down form
« Reply #11 on: October 04, 2021, 05:12:01 am »
I believe I have what you want. It's called a TBigCombo / TBigList.
These reside in a fairly large library of mine -- I shall send them to you (the complete Lazarus package) if you would be so kind to provide me with your e-mail address.

Hello DtC17, this topic is already over 8 years old and I hope you can still see this reply. Would you please send me the TBigCombo/TBigList package to my email? Thank you in advance.
Lazarus 2.0.12/2.2.0RC1 (Win10, Xubuntu, Pop!Os)

jamestien

  • New Member
  • *
  • Posts: 35
Re: help with a custom drop down form
« Reply #12 on: October 04, 2021, 05:21:02 am »
The custom dropdown form in ComboBox is created with THintWindow, I have found the code & demo online during search, but it is in C# code.
I'm not so familiar with C# and .NET ECO system, anybody care to translate it to Lazarus/Delphi and share it here?
Lazarus 2.0.12/2.2.0RC1 (Win10, Xubuntu, Pop!Os)

Gald

  • Jr. Member
  • **
  • Posts: 63
Re: help with a custom drop down form
« Reply #13 on: October 06, 2021, 06:42:31 am »
Anybody care to translate it to Lazarus/Delphi and share it here?

If someone does this, it will probably be a workaround using TPanels.
Are you ok with that? It will appear ugly.
And I have no idea how to resize TPanel with this Sizegrip in your related image.

jamestien

  • New Member
  • *
  • Posts: 35
Re: help with a custom drop down form
« Reply #14 on: October 07, 2021, 06:26:27 am »
Anybody care to translate it to Lazarus/Delphi and share it here?

If someone does this, it will probably be a workaround using TPanels.
Are you ok with that? It will appear ugly.
And I have no idea how to resize TPanel with this Sizegrip in your related image.

The C# source code does it all, just wish somebody who with good understanding of C# would be able to ported it to Pascal code.
Lazarus 2.0.12/2.2.0RC1 (Win10, Xubuntu, Pop!Os)

 

TinyPortal © 2005-2018