| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075 |
- // SPDX-License-Identifier: LGPL-3.0-linking-exception
- unit BCComboBox;
- {$mode delphi}
- interface
- uses
- {$ifdef WINDOWS}Windows,{$endif} Classes, SysUtils, LResources, Forms, Controls, ExtCtrls, Graphics, Dialogs, BCButton,
- StdCtrls, BCTypes, BCBaseCtrls, BGRABitmap, BGRABitmapTypes, LMessages, LCLType;
- type
- { TBCComboBox }
- TBCComboBox = class(TBCStyleCustomControl)
- private
- FButton: TBCButton;
- FCanvasScaleMode: TBCCanvasScaleMode;
- FDropDownBorderSize: integer;
- FDropDownCount: integer;
- FDropDownColor: TColor;
- FDropDownFontColor: TColor;
- FDropDownFontHighlight: TColor;
- FDropDownHighlight: TColor;
- FDropDownOnSameForm: boolean;
- FFocusBorderColor: TColor;
- FFocusBorderOpacity: byte;
- FItems: TStringList;
- FItemIndex: integer;
- FForm: TForm;
- FPanel: TPanel;
- FDropDownHideDate: TDateTime;
- FHoverItem: integer;
- FItemHeight: integer;
- FListBox: TListBox;
- FItemPadding: integer;
- FDropDownBorderColor: TColor;
- FOnDrawItem: TDrawItemEvent;
- FOnDrawSelectedItem: TOnAfterRenderBCButton;
- FOnChange: TNotifyEvent;
- FOnDropDown: TNotifyEvent;
- FDrawingDropDown: boolean;
- FTimerCheckFormHide: TTimer;
- FQueryDropDownHide: boolean;
- procedure ButtonClick(Sender: TObject);
- procedure FormDeactivate(Sender: TObject);
- procedure PanelExit(Sender: TObject);
- procedure FormHide(Sender: TObject);
- function GetArrowFlip: boolean;
- function GetComboCanvas: TCanvas;
- function GetArrowSize: integer;
- function GetArrowWidth: integer;
- function GetButtonHint: TTranslateString;
- function GetButtonShowHint: Boolean;
- function GetGlobalOpacity: byte;
- function GetItemText: string;
- function GetDropDownColor: TColor;
- function GetItemIndex: integer;
- function GetItems: TStrings;
- function GetMemoryUsage: TBCButtonMemoryUsage;
- function GetOnDrawSelectedItem: TOnAfterRenderBCButton;
- function GetRounding: TBCRounding;
- function GetStateClicked: TBCButtonState;
- function GetStateHover: TBCButtonState;
- function GetStateNormal: TBCButtonState;
- function GetStaticButton: boolean;
- procedure ListBoxKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
- procedure ListBoxMouseUp({%H-}Sender: TObject; {%H-}Button: TMouseButton;
- {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
- procedure ListBoxMouseLeave(Sender: TObject);
- procedure ListBoxMouseMove(Sender: TObject; {%H-}Shift: TShiftState; X,
- Y: Integer);
- procedure ListBoxSelectionChange(Sender: TObject; {%H-}User: boolean);
- procedure ListBoxDrawItem(Control: TWinControl; Index: Integer;
- ARect: TRect; State: TOwnerDrawState);
- procedure OnAfterRenderButton(Sender: TObject; const ABGRA: TBGRABitmap;
- AState: TBCButtonState; ARect: TRect);
- procedure OnTimerCheckFormHide(Sender: TObject);
- procedure SetArrowFlip(AValue: boolean);
- procedure SetArrowSize(AValue: integer);
- procedure SetArrowWidth(AValue: integer);
- procedure SetButtonHint(const AValue: TTranslateString);
- procedure SetButtonShowHint(AValue: Boolean);
- procedure SetCanvasScaleMode(AValue: TBCCanvasScaleMode);
- procedure SetDropDownColor(AValue: TColor);
- procedure SetGlobalOpacity(AValue: byte);
- procedure SetItemIndex(AValue: integer);
- procedure SetItems(AValue: TStrings);
- procedure SetMemoryUsage(AValue: TBCButtonMemoryUsage);
- procedure SetOnDrawSelectedItem(AValue: TOnAfterRenderBCButton);
- procedure SetRounding(AValue: TBCRounding);
- procedure SetStateClicked(AValue: TBCButtonState);
- procedure SetStateHover(AValue: TBCButtonState);
- procedure SetStateNormal(AValue: TBCButtonState);
- procedure SetStaticButton(AValue: boolean);
- function GetOnButtonMouseDown: TMouseEvent;
- function GetOnButtonMouseEnter: TNotifyEvent;
- function GetOnButtonMouseLeave: TNotifyEvent;
- function GetOnButtonMouseMove: TMouseMoveEvent;
- function GetOnButtonMouseUp: TMouseEvent;
- function GetOnButtonMouseWheel: TMouseWheelEvent;
- function GetOnButtonMouseWheelDown: TMouseWheelUpDownEvent;
- function GetOnButtonMouseWheelUp: TMouseWheelUpDownEvent;
- procedure SetOnButtonMouseDown(AValue: TMouseEvent);
- procedure SetOnButtonMouseEnter(AValue: TNotifyEvent);
- procedure SetOnButtonMouseLeave(AValue: TNotifyEvent);
- procedure SetOnButtonMouseMove(AValue: TMouseMoveEvent);
- procedure SetOnButtonMouseUp(AValue: TMouseEvent);
- procedure SetOnButtonMouseWheel(AValue: TMouseWheelEvent);
- procedure SetOnButtonMouseWheelDown(AValue: TMouseWheelUpDownEvent);
- procedure SetOnButtonMouseWheelUp(AValue: TMouseWheelUpDownEvent);
- protected
- function GetStyleExtension: String; override;
- procedure WMSetFocus(var {%H-}Message: {$IFDEF FPC}TLMSetFocus{$ELSE}TWMSetFocus{$ENDIF}); message {$IFDEF FPC}LM_SETFOCUS{$ELSE}WM_SETFOCUS{$ENDIF};
- procedure WMKillFocus(var Message: {$IFDEF FPC}TLMKillFocus{$ELSE}TWMKillFocus{$ENDIF}); message {$IFDEF FPC}LM_KILLFOCUS{$ELSE}WM_KILLFOCUS{$ENDIF};
- procedure UpdateFocus(AFocused: boolean);
- procedure KeyDown(var Key: Word; {%H-}Shift: TShiftState); override;
- procedure UTF8KeyPress(var UTF8Key: TUTF8Char); override;
- procedure CreateDropDown;
- procedure FreeDropDown;
- function CloseDropDown: boolean;
- procedure PrepareListBoxForDropDown;
- procedure AutosizeListBox;
- procedure AdaptDropDownContainerSize;
- function GetListBox: TListBox;
- procedure UpdateButtonCanvasScaleMode;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- { Assign the properties from Source to this instance }
- procedure Assign(Source: TPersistent); override;
- procedure Clear;
- property HoverItem: integer read FHoverItem;
- property Button: TBCButton read FButton write FButton;
- property ListBox: TListBox read GetListBox;
- property Text: string read GetItemText;
- published
- property Align;
- property Anchors;
- property BorderSpacing;
- property Canvas: TCanvas read GetComboCanvas;
- property CanvasScaleMode: TBCCanvasScaleMode read FCanvasScaleMode write SetCanvasScaleMode default csmAuto;
- property Hint: TTranslateString read GetButtonHint write SetButtonHint;
- property Items: TStrings read GetItems write SetItems;
- property ItemIndex: integer read GetItemIndex write SetItemIndex;
- property ItemHeight: integer read FItemHeight write FItemHeight default 0;
- property ArrowSize: integer read GetArrowSize write SetArrowSize;
- property ArrowWidth: integer read GetArrowWidth write SetArrowWidth;
- property ArrowFlip: boolean read GetArrowFlip write SetArrowFlip default false;
- property FocusBorderColor: TColor read FFocusBorderColor write FFocusBorderColor default clBlack;
- property FocusBorderOpacity: byte read FFocusBorderOpacity write FFocusBorderOpacity default 0;
- property DropDownBorderColor: TColor read FDropDownBorderColor write FDropDownBorderColor default clWindowText;
- property DropDownBorderSize: integer read FDropDownBorderSize write FDropDownBorderSize default 1;
- property DropDownColor: TColor read GetDropDownColor write SetDropDownColor default clWindow;
- property DropDownFontColor: TColor read FDropDownFontColor write FDropDownFontColor default clWindowText;
- property DropDownCount: integer read FDropDownCount write FDropDownCount default 8;
- property DropDownHighlight: TColor read FDropDownHighlight write FDropDownHighlight default clHighlight;
- property DropDownFontHighlight: TColor read FDropDownFontHighlight write FDropDownFontHighlight default clHighlightText;
- property DropDownOnSameForm: boolean read FDropDownOnSameForm write FDropDownOnSameForm default False;
- property GlobalOpacity: byte read GetGlobalOpacity write SetGlobalOpacity;
- property MemoryUsage: TBCButtonMemoryUsage read GetMemoryUsage write SetMemoryUsage;
- property Rounding: TBCRounding read GetRounding write SetRounding;
- property ShowHint: Boolean read GetButtonShowHint write SetButtonShowHint default False;
- property StateClicked: TBCButtonState read GetStateClicked write SetStateClicked;
- property StateHover: TBCButtonState read GetStateHover write SetStateHover;
- property StateNormal: TBCButtonState read GetStateNormal write SetStateNormal;
- property StaticButton: boolean read GetStaticButton write SetStaticButton;
- property OnDropDown: TNotifyEvent read FOnDropDown write FOnDropDown;
- property OnDrawItem: TDrawItemEvent read FOnDrawItem write FOnDrawItem;
- property OnDrawSelectedItem: TOnAfterRenderBCButton read GetOnDrawSelectedItem write SetOnDrawSelectedItem;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnMouseDown: TMouseEvent read GetOnButtonMouseDown write SetOnButtonMouseDown;
- property OnMouseMove: TMouseMoveEvent read GetOnButtonMouseMove write SetOnButtonMouseMove;
- property OnMouseUp: TMouseEvent read GetOnButtonMouseUp write SetOnButtonMouseUp;
- property OnMouseEnter: TNotifyEvent read GetOnButtonMouseEnter write SetOnButtonMouseEnter;
- property OnMouseLeave: TNotifyEvent read GetOnButtonMouseLeave write SetOnButtonMouseLeave;
- property OnMouseWheel: TMouseWheelEvent read GetOnButtonMouseWheel write SetOnButtonMouseWheel;
- property OnMouseWheelDown: TMouseWheelUpDownEvent read GetOnButtonMouseWheelDown write SetOnButtonMouseWheelDown;
- property OnMouseWheelUp: TMouseWheelUpDownEvent read GetOnButtonMouseWheelUp write SetOnButtonMouseWheelUp;
- property TabStop;
- property TabOrder;
- end;
- procedure Register;
- implementation
- uses math, PropEdits, BGRAText;
- procedure Register;
- begin
- RegisterComponents('BGRA Controls', [TBCComboBox]);
- end;
- { TBCComboBox }
- procedure TBCComboBox.ButtonClick(Sender: TObject);
- const MinDelayReopen = 500/(1000*60*60*24);
- var
- p: TPoint;
- f: TCustomForm;
- monitor: TMonitor;
- begin
- CreateDropDown;
- if not CloseDropDown and (Now > FDropDownHideDate+MinDelayReopen) then
- begin
- if DropDownOnSameForm then
- begin
- f := GetParentForm(self, False);
- if Assigned(f) then
- begin
- PrepareListBoxForDropDown;
- p := ControlToScreen(Point(FButton.Left, FButton.Top + FButton.Height));
- p := f.ScreenToClient(p);
- FPanel.Parent := f;
- FPanel.Left := p.X;
- FPanel.Top := p.Y;
- FPanel.Color := FDropDownBorderColor;
- AdaptDropDownContainerSize;
- if FPanel.Top + FPanel.Height > f.ClientHeight then
- FPanel.Top := FPanel.Top - FPanel.Height - Self.Height;
- if Assigned(FOnDropDown) then FOnDropDown(self);
- FQueryDropDownHide := false;
- FTimerCheckFormHide.Enabled:= true;
- FPanel.Visible := true;
- if FPanel.CanSetFocus then
- FPanel.SetFocus;
- if FListBox.CanSetFocus then
- FListBox.SetFocus;
- end;
- end else
- begin
- PrepareListBoxForDropDown;
- p := ControlToScreen(Point(FButton.Left, FButton.Top + FButton.Height));
- FForm.Left := p.X;
- FForm.Top := p.Y;
- FForm.Color := FDropDownBorderColor;
- AdaptDropDownContainerSize;
- monitor := Screen.MonitorFromPoint(p);
- if FForm.Top + FForm.Height > monitor.WorkareaRect.Bottom then
- FForm.Top := FForm.Top - FForm.Height - Self.Height;
- if Assigned(FOnDropDown) then FOnDropDown(self);
- FQueryDropDownHide := false;
- FTimerCheckFormHide.Enabled:= true;
- {$IFDEF DARWIN}
- f := GetParentForm(self, False);
- if fsModal in f.FormState then FForm.ShowModal else
- {$ENDIF}
- begin
- FForm.Visible := True;
- if FListBox.CanSetFocus then
- FListBox.SetFocus;
- end;
- end;
- end;
- end;
- procedure TBCComboBox.FormDeactivate(Sender: TObject);
- begin
- FQueryDropDownHide := true;
- end;
- procedure TBCComboBox.PanelExit(Sender: TObject);
- begin
- FQueryDropDownHide := true;
- end;
- procedure TBCComboBox.FormHide(Sender: TObject);
- begin
- FDropDownHideDate := Now;
- end;
- function TBCComboBox.GetArrowFlip: boolean;
- begin
- result := Button.FlipArrow;
- end;
- function TBCComboBox.GetComboCanvas: TCanvas;
- begin
- if FDrawingDropDown then
- result := ListBox.Canvas
- else
- result := inherited Canvas;
- end;
- function TBCComboBox.GetArrowSize: integer;
- begin
- result := Button.DropDownArrowSize;
- end;
- function TBCComboBox.GetArrowWidth: integer;
- begin
- result := Button.DropDownWidth;
- end;
- function TBCComboBox.GetButtonHint: TTranslateString;
- begin
- result := FButton.Hint;
- end;
- function TBCComboBox.GetButtonShowHint: Boolean;
- begin
- result := FButton.ShowHint;
- end;
- function TBCComboBox.GetGlobalOpacity: byte;
- begin
- result := Button.GlobalOpacity;
- end;
- function TBCComboBox.GetItemText: string;
- begin
- if ItemIndex<>-1 then
- result := Items[ItemIndex]
- else
- result := '';
- end;
- function TBCComboBox.GetDropDownColor: TColor;
- begin
- if Assigned(FListBox) then
- result := FListBox.Color
- else result := FDropDownColor;
- end;
- function TBCComboBox.GetItemIndex: integer;
- begin
- if Assigned(FListBox) then
- result := FListBox.ItemIndex
- else
- begin
- if FItemIndex >= Items.Count then
- FItemIndex := -1;
- result := FItemIndex;
- end;
- end;
- function TBCComboBox.GetItems: TStrings;
- begin
- if Assigned(FListBox) then
- Result := FListBox.Items
- else Result := FItems;
- end;
- function TBCComboBox.GetMemoryUsage: TBCButtonMemoryUsage;
- begin
- result := Button.MemoryUsage;
- end;
- function TBCComboBox.GetOnDrawSelectedItem: TOnAfterRenderBCButton;
- begin
- result := FOnDrawSelectedItem;
- end;
- function TBCComboBox.GetRounding: TBCRounding;
- begin
- result := Button.Rounding;
- end;
- function TBCComboBox.GetStateClicked: TBCButtonState;
- begin
- result := Button.StateClicked;
- end;
- function TBCComboBox.GetStateHover: TBCButtonState;
- begin
- result := Button.StateHover;
- end;
- function TBCComboBox.GetStateNormal: TBCButtonState;
- begin
- result := Button.StateNormal;
- end;
- function TBCComboBox.GetStaticButton: boolean;
- begin
- result := Button.StaticButton;
- end;
- procedure TBCComboBox.ListBoxKeyDown(Sender: TObject; var Key: Word;
- Shift: TShiftState);
- begin
- if (Key = VK_RETURN) or (Key = VK_ESCAPE) then
- begin
- ButtonClick(nil);
- Key := 0;
- end;
- end;
- procedure TBCComboBox.ListBoxMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- CloseDropDown;
- end;
- procedure TBCComboBox.ListBoxMouseLeave(Sender: TObject);
- begin
- FHoverItem := -1;
- FListBox.Repaint;
- end;
- procedure TBCComboBox.ListBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
- Y: Integer);
- var
- TempItem: integer;
- begin
- TempItem := FListBox.ItemAtPos(Point(x, y), True);
- if TempItem <> FHoverItem then
- begin
- FHoverItem := TempItem;
- if (FHoverItem<>-1) and ([ssLeft,ssRight]*Shift <> []) then
- FListBox.ItemIndex := FHoverItem;
- FListBox.Repaint;
- end;
- end;
- procedure TBCComboBox.ListBoxSelectionChange(Sender: TObject; User: boolean);
- begin
- Button.Caption := GetItemText;
- if User and Assigned(FOnChange) then FOnChange(self);
- {$IFDEF WINDOWS}
- // ensure redrawing of all items
- (Sender as TListBox).Invalidate;
- {$ENDIF}
- end;
- procedure TBCComboBox.ListBoxDrawItem(Control: TWinControl; Index: Integer;
- ARect: TRect; State: TOwnerDrawState);
- var
- aCanvas: TCanvas;
- padding: integer;
- r: TRect;
- begin
- if Index = 0 then
- begin
- padding := max(0, ARect.Height - TListBox(Control).ItemHeight);
- if padding <> FItemPadding then
- begin
- // next time, use a better adjustment
- FItemPadding := padding;
- end;
- end;
- if Assigned(FOnDrawItem) then
- begin
- FDrawingDropDown := true;
- Exclude(State, odSelected);
- if Index = HoverItem then Include(State, odSelected);
- if Index = ItemIndex then Include(State, odChecked);
- try
- r := ARect;
- {$IFDEF DARWIN}
- // on MacOS the vertical scrollbar is over the content
- Dec(r.Right, 8);
- {$ENDIF}
- FOnDrawItem(Control, Index, r, State);
- finally
- FDrawingDropDown := false;
- end;
- exit;
- end;
- aCanvas := TListBox(Control).Canvas;
- aCanvas.Pen.Style := psClear;
- {$IFDEF DARWIN}
- // paint top and bottom margin on MacOS
- aCanvas.Brush.Color := DropDownColor;
- if Index = 0 then
- begin
- r := ARect;
- r.Bottom := r.Top;
- dec(r.Top, 10);
- aCanvas.FillRect(r);
- end;
- if Index = TListBox(Control).Count-1 then
- begin
- r := ARect;
- r.Top := r.Bottom;
- inc(r.Bottom, 10);
- aCanvas.FillRect(r);
- end;
- {$ENDIF}
- if Index = HoverItem then
- begin
- aCanvas.Brush.Color := DropDownHighlight;
- aCanvas.Font.Color := DropDownFontHighlight;
- end
- else
- begin
- aCanvas.Brush.Color := DropDownColor;
- aCanvas.Font.Color := DropDownFontColor;
- end;
- aCanvas.FillRect(ARect);
- aCanvas.TextRect(ARect, ARect.Left+4, ARect.Top +
- (ARect.Height - aCanvas.GetTextHeight(Items[Index])) div 2,
- Items[Index]);
- end;
- procedure TBCComboBox.OnAfterRenderButton(Sender: TObject;
- const ABGRA: TBGRABitmap; AState: TBCButtonState; ARect: TRect);
- var
- FocusMargin: integer;
- begin
- if Assigned(FOnDrawSelectedItem) then
- FOnDrawSelectedItem(self, ABGRA, AState, ARect);
- if Focused then
- begin
- FocusMargin := round(2 * FButton.CanvasScale);
- ABGRA.RoundRectAntialias(
- ARect.Left + FocusMargin,
- ARect.Top + FocusMargin,
- ARect.Right - FocusMargin - 1,
- ARect.Bottom - FocusMargin - 1,
- Max(0, FButton.Rounding.RoundX - FocusMargin),
- Max(0, FButton.Rounding.RoundY - FocusMargin),
- ColorToBGRA(FFocusBorderColor, FFocusBorderOpacity),
- FButton.CanvasScale);
- end;
- end;
- procedure TBCComboBox.OnTimerCheckFormHide(Sender: TObject);
- {$ifdef WINDOWS}
- function IsDropDownOnTop: boolean;
- begin
- result := Assigned(FForm) and (GetForegroundWindow = FForm.Handle);
- end;
- {$endif}
- procedure DoClose;
- begin
- CloseDropDown;
- FQueryDropDownHide := false;
- FTimerCheckFormHide.Enabled := false;
- end;
- begin
- {$IFNDEF LCLgtk3}
- if not Application.Active then FQueryDropDownHide:= true;
- {$ENDIF}
- if not FQueryDropDownHide then exit;
- if Assigned(FPanel) then DoClose;
- {$IFDEF WINDOWS}
- If Assigned(FForm) and FForm.Visible then DoClose;
- {$ELSE}
- If Assigned(FForm) and not FForm.Active then DoClose;
- {$ENDIF}
- end;
- procedure TBCComboBox.SetArrowFlip(AValue: boolean);
- begin
- Button.FlipArrow:= AValue;
- end;
- procedure TBCComboBox.SetArrowSize(AValue: integer);
- begin
- Button.DropDownArrowSize:= AValue;
- end;
- procedure TBCComboBox.SetArrowWidth(AValue: integer);
- begin
- Button.DropDownWidth:= AValue;
- end;
- procedure TBCComboBox.SetButtonHint(const AValue: TTranslateString);
- begin
- FButton.Hint := AValue;
- end;
- procedure TBCComboBox.SetButtonShowHint(AValue: Boolean);
- begin
- FButton.ShowHint := AValue;
- end;
- procedure TBCComboBox.SetCanvasScaleMode(AValue: TBCCanvasScaleMode);
- begin
- if FCanvasScaleMode=AValue then Exit;
- FCanvasScaleMode:=AValue;
- UpdateButtonCanvasScaleMode;
- end;
- procedure TBCComboBox.SetDropDownColor(AValue: TColor);
- begin
- if Assigned(FListBox) then
- FListBox.Color := AValue
- else FDropDownColor:= AValue;
- end;
- procedure TBCComboBox.SetGlobalOpacity(AValue: byte);
- begin
- Button.GlobalOpacity := AValue;
- end;
- procedure TBCComboBox.SetItemIndex(AValue: integer);
- begin
- if Assigned(FListBox) then
- FListBox.ItemIndex := AValue
- else
- begin
- if AValue <> FItemIndex then
- begin
- FItemIndex := AValue;
- Button.Caption := GetItemText;
- end;
- end;
- end;
- procedure TBCComboBox.SetItems(AValue: TStrings);
- begin
- if Assigned(FListBox) then
- FListBox.Items.Assign(AValue)
- else FItems.Assign(AValue);
- end;
- procedure TBCComboBox.SetMemoryUsage(AValue: TBCButtonMemoryUsage);
- begin
- Button.MemoryUsage := AValue;
- end;
- procedure TBCComboBox.SetOnDrawSelectedItem(AValue: TOnAfterRenderBCButton);
- begin
- if @FOnDrawSelectedItem = @AValue then Exit;
- FOnDrawSelectedItem:= AValue;
- FButton.ShowCaption := not Assigned(AValue);
- UpdateButtonCanvasScaleMode;
- end;
- procedure TBCComboBox.SetRounding(AValue: TBCRounding);
- begin
- Button.Rounding := AValue;
- end;
- procedure TBCComboBox.SetStateClicked(AValue: TBCButtonState);
- begin
- Button.StateClicked := AValue;
- end;
- procedure TBCComboBox.SetStateHover(AValue: TBCButtonState);
- begin
- Button.StateHover := AValue;
- end;
- procedure TBCComboBox.SetStateNormal(AValue: TBCButtonState);
- begin
- Button.StateNormal := AValue;
- end;
- procedure TBCComboBox.SetStaticButton(AValue: boolean);
- begin
- Button.StaticButton:= AValue;
- end;
- function TBCComboBox.GetOnButtonMouseDown: TMouseEvent;
- begin
- result := FButton.OnMouseDown;
- end;
- function TBCComboBox.GetOnButtonMouseEnter: TNotifyEvent;
- begin
- result := FButton.OnMouseEnter;
- end;
- function TBCComboBox.GetOnButtonMouseLeave: TNotifyEvent;
- begin
- result := FButton.OnMouseLeave;
- end;
- function TBCComboBox.GetOnButtonMouseMove: TMouseMoveEvent;
- begin
- result := FButton.OnMouseMove;
- end;
- function TBCComboBox.GetOnButtonMouseUp: TMouseEvent;
- begin
- result := FButton.OnMouseUp;
- end;
- function TBCComboBox.GetOnButtonMouseWheel: TMouseWheelEvent;
- begin
- result := FButton.OnMouseWheel;
- end;
- function TBCComboBox.GetOnButtonMouseWheelDown: TMouseWheelUpDownEvent;
- begin
- result := FButton.OnMouseWheelDown;
- end;
- function TBCComboBox.GetOnButtonMouseWheelUp: TMouseWheelUpDownEvent;
- begin
- result := FButton.OnMouseWheelUp;
- end;
- procedure TBCComboBox.SetOnButtonMouseDown(AValue: TMouseEvent);
- begin
- FButton.OnMouseDown := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseEnter(AValue: TNotifyEvent);
- begin
- FButton.OnMouseEnter := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseLeave(AValue: TNotifyEvent);
- begin
- FButton.OnMouseLeave := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseMove(AValue: TMouseMoveEvent);
- begin
- FButton.OnMouseMove := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseUp(AValue: TMouseEvent);
- begin
- FButton.OnMouseUp := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseWheel(AValue: TMouseWheelEvent);
- begin
- FButton.OnMouseWheel := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseWheelDown(AValue: TMouseWheelUpDownEvent);
- begin
- FButton.OnMouseWheelDown := AValue;
- end;
- procedure TBCComboBox.SetOnButtonMouseWheelUp(AValue: TMouseWheelUpDownEvent);
- begin
- FButton.OnMouseWheelUp := AValue;
- end;
- function TBCComboBox.GetStyleExtension: String;
- begin
- result := 'bccombo';
- end;
- procedure TBCComboBox.WMSetFocus(var Message: TLMSetFocus);
- begin
- UpdateFocus(True);
- end;
- procedure TBCComboBox.WMKillFocus(var Message: TLMKillFocus);
- begin
- if Message.FocusedWnd <> Handle then
- UpdateFocus(False);
- end;
- procedure TBCComboBox.UpdateFocus(AFocused: boolean);
- var
- lForm: TCustomForm;
- begin
- lForm := GetParentForm(Self);
- if lForm = nil then Exit;
- {$IFDEF FPC}//#
- if AFocused then
- ActiveDefaultControlChanged(lForm.ActiveControl)
- else
- ActiveDefaultControlChanged(nil);
- {$ENDIF}
- FButton.UpdateControl;
- Invalidate;
- end;
- procedure TBCComboBox.KeyDown(var Key: Word; Shift: TShiftState);
- begin
- if Key = VK_RETURN then
- begin
- ButtonClick(nil);
- Key := 0;
- end
- else if Key = VK_DOWN then
- begin
- if ItemIndex + 1 < Items.Count then
- begin
- ItemIndex := ItemIndex + 1;
- Button.Caption := GetItemText;
- if Assigned(FOnChange) then
- FOnChange(Self);
- end;
- Key := 0;
- end
- else if Key = VK_UP then
- begin
- if ItemIndex - 1 >= 0 then
- begin
- ItemIndex := ItemIndex - 1;
- Button.Caption := GetItemText;
- if Assigned(FOnChange) then
- FOnChange(Self);
- end;
- Key := 0;
- end;
- end;
- procedure TBCComboBox.UTF8KeyPress(var UTF8Key: TUTF8Char);
- var
- i: integer;
- begin
- for i:=0 to Items.Count-1 do
- begin
- if (Items[i] <> '') and Items[i].ToLower.StartsWith(LowerCase(UTF8Key)) then
- begin
- if ItemIndex <> i then
- begin
- ItemIndex := i;
- Button.Caption := GetItemText;
- if Assigned(FOnChange) then
- FOnChange(Self);
- break;
- end;
- end;
- end;
- end;
- procedure TBCComboBox.CreateDropDown;
- begin
- {$IFDEF LINUX}
- // ensure correct window placement on Linux
- if Assigned(FForm) and not FForm.Visible then FreeDropDown;
- {$ENDIF}
- if (FForm = nil) and not DropDownOnSameForm then
- begin
- FForm := TForm.Create(Self);
- FForm.Visible := False;
- FForm.ShowInTaskBar:= stNever;
- FForm.BorderStyle := bsNone;
- FForm.OnDeactivate:= FormDeactivate;
- FForm.OnHide:=FormHide;
- FForm.FormStyle := fsStayOnTop;
- end else
- if Assigned(FForm) and DropDownOnSameForm then
- begin
- If Assigned(FListBox) and (FListBox.Parent = FForm) then FListBox.Parent := nil;
- FreeAndNil(FForm);
- end;
- if (FPanel = nil) and DropDownOnSameForm then
- begin
- FPanel := TPanel.Create(Self);
- FPanel.Visible := False;
- FPanel.BevelInner := bvNone;
- FPanel.BevelOuter := bvNone;
- end else
- if Assigned(FPanel) and not DropDownOnSameForm then
- begin
- If Assigned(FListBox) and (FListBox.Parent = FPanel) then FListBox.Parent := nil;
- FreeAndNil(FPanel);
- end;
- if FListBox = nil then
- begin
- FListBox := TListBox.Create(self);
- FListBox.BorderStyle := bsNone;
- FListBox.OnMouseLeave:=ListBoxMouseLeave;
- FListBox.OnMouseMove:=ListBoxMouseMove;
- FListBox.OnMouseUp:= ListBoxMouseUp;
- FListBox.Style := lbOwnerDrawFixed;
- FListBox.OnDrawItem:= ListBoxDrawItem;
- FListBox.Options := []; // do not draw focus rect
- FListBox.OnKeyDown:=ListBoxKeyDown;
- if Assigned(FItems) then
- begin
- FListBox.Items.Assign(FItems);
- FreeAndNil(FItems);
- end;
- FListBox.ItemIndex := FItemIndex;
- FListBox.Color := FDropDownColor;
- FListBox.OnSelectionChange := ListBoxSelectionChange;
- end;
- if DropDownOnSameForm then
- begin
- FListBox.Parent := FPanel;
- FListBox.OnExit:= PanelExit;
- end
- else
- begin
- FListBox.Parent := FForm;
- FListBox.OnExit:= nil;
- end;
- end;
- procedure TBCComboBox.FreeDropDown;
- begin
- if Assigned(FListBox) then
- begin
- if FListBox.LCLRefCount > 0 then exit;
- if FItems = nil then
- FItems := TStringList.Create;
- FItems.Assign(FListBox.Items);
- FItemIndex := FListBox.ItemIndex;
- FDropDownColor:= FListBox.Color;
- FreeAndNil(FListBox);
- end;
- FreeAndNil(FForm);
- FreeAndNil(FPanel);
- end;
- function TBCComboBox.CloseDropDown: boolean;
- begin
- if Assigned(FForm) and FForm.Visible then
- begin
- FForm.Close;
- result := true;
- end
- else if Assigned(FPanel) and FPanel.Visible then
- begin
- FPanel.Hide;
- FDropDownHideDate := Now;
- result := true;
- end else
- begin
- result := false;
- end;
- FQueryDropDownHide := true;
- end;
- procedure TBCComboBox.PrepareListBoxForDropDown;
- var
- h: Integer;
- begin
- FListBox.Font.Name := Button.StateNormal.FontEx.Name;
- FListBox.Font.Style := Button.StateNormal.FontEx.Style;
- FListBox.Font.Height := FontEmHeightSign*Button.StateNormal.FontEx.Height;
- if Assigned(FOnDrawItem) and (FItemHeight <> 0) then
- h := FItemHeight else h := self.Canvas.GetTextHeight('Hg');
- {$IF defined(LCLgtk2)}
- inc(h,2);
- {$ELSEIF defined(LCLgtk3)}
- inc(h,4);
- {$ELSE}
- inc(h,6); // default
- {$ENDIF}
- FListBox.ItemHeight := h;
- AutosizeListBox;
- end;
- procedure TBCComboBox.AutosizeListBox;
- var
- s: TSize;
- begin
- s := TSize.Create(FButton.Width,
- (FListBox.ItemHeight + FItemPadding)*min(Items.Count, FDropDownCount)
- + 2*FDropDownBorderSize);
- {$IFDEF DARWIN}
- // on MacOS there is a top and bottom margin of both 10
- if Items.Count <= FDropDownCount then
- inc(s.cy, 20)
- else
- // if overflow, keep only either top or bottom margin
- inc(s.cy, 10);
- {$ENDIF}
- FListBox.SetBounds(FDropDownBorderSize,FDropDownBorderSize,
- s.cx - 2*FDropDownBorderSize,
- s.cy - 2*FDropDownBorderSize);
- end;
- procedure TBCComboBox.AdaptDropDownContainerSize;
- var w, h: integer;
- begin
- if not Assigned(FListBox) then exit;
- w := FListBox.Width + 2*FDropDownBorderSize;
- h := FListBox.Height + 2*FDropDownBorderSize;
- if Assigned(FPanel) then
- begin
- FPanel.ClientWidth := w;
- FPanel.ClientHeight := h;
- end;
- if Assigned(FForm) {$IFDEF LCLgtk2}and not FForm.HandleAllocated{$ENDIF} then
- begin
- FForm.SetBounds(FForm.Left, FForm.Top,
- w + FForm.Width - FForm.ClientWidth,
- h + FForm.Height - FForm.ClientHeight);
- end;
- end;
- function TBCComboBox.GetListBox: TListBox;
- begin
- CreateDropDown;
- result := FListBox;
- end;
- procedure TBCComboBox.UpdateButtonCanvasScaleMode;
- begin
- if (CanvasScaleMode = csmFullResolution) or
- ((CanvasScaleMode = csmAuto) and not Assigned(FOnDrawSelectedItem)) then
- FButton.CanvasScaleMode:= csmFullResolution
- else FButton.CanvasScaleMode:= csmScaleBitmap;
- end;
- constructor TBCComboBox.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FButton := TBCButton.Create(Self);
- FButton.Align := alClient;
- FButton.Parent := Self;
- FButton.OnClick := ButtonClick;
- FButton.DropDownArrow := True;
- FButton.OnAfterRenderBCButton := OnAfterRenderButton;
- FFocusBorderColor := clBlack;
- FFocusBorderOpacity := 0;
- UpdateButtonCanvasScaleMode;
- FItems := TStringList.Create;
- FHoverItem := -1;
- FItemIndex := -1;
- DropDownBorderSize := 1;
- DropDownColor := clWindow;
- DropDownBorderColor := clWindowText;
- DropDownCount := 8;
- DropDownFontColor := clWindowText;
- DropDownHighlight := clHighlight;
- DropDownFontHighlight := clHighlightText;
- FTimerCheckFormHide := TTimer.Create(self);
- {$IFDEF LCLgtk3}
- FTimerCheckFormHide.Enabled := false;
- {$ENDIF}
- FTimerCheckFormHide.Interval:= 30;
- FTimerCheckFormHide.OnTimer:= OnTimerCheckFormHide;
- {$IFDEF WINDOWS}
- FItemPadding:= 0;
- {$ELSE}
- {$IFDEF LCLgtk2}
- FItemPadding:= 4;
- {$ELSE}
- FItemPadding:= 0; // default
- {$ENDIF}
- {$ENDIF}
- end;
- destructor TBCComboBox.Destroy;
- begin
- FreeAndNil(FItems);
- inherited Destroy;
- end;
- procedure TBCComboBox.Assign(Source: TPersistent);
- var
- src: TBCComboBox;
- begin
- if Source is TBCComboBox then
- begin
- src := TBCComboBox(Source);
- Button.Assign(src.Button);
- Items.Assign(src.Items);
- ItemIndex := src.ItemIndex;
- DropDownBorderColor := src.DropDownBorderColor;
- DropDownBorderSize := src.DropDownBorderSize;
- DropDownColor := src.DropDownColor;
- DropDownFontColor := src.DropDownFontColor;
- DropDownCount := src.DropDownCount;
- DropDownHighlight := src.DropDownHighlight;
- DropDownFontHighlight := src.DropDownFontHighlight;
- end else
- inherited Assign(Source);
- end;
- procedure TBCComboBox.Clear;
- begin
- Items.Clear;
- end;
- end.
|