|
|
@@ -0,0 +1,796 @@
|
|
|
+unit BCCheckComboBox;
|
|
|
+
|
|
|
+{$mode delphi}
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+uses
|
|
|
+ {$ifdef WINDOWS}Windows,{$endif} Classes, SysUtils, LResources, Forms, Controls, ExtCtrls, Graphics, Dialogs, BCButton,
|
|
|
+ StdCtrls, BCTypes, BCBaseCtrls, BGRABitmap, BGRABitmapTypes, LMessages, LCLType,
|
|
|
+ CheckLst, BGRATheme;
|
|
|
+
|
|
|
+type
|
|
|
+
|
|
|
+ { TBCCheckComboBox }
|
|
|
+
|
|
|
+ TBCCheckComboBox = class(TBCStyleCustomControl)
|
|
|
+ private
|
|
|
+ FButton: TBCButton;
|
|
|
+ FCanvasScaleMode: TBCCanvasScaleMode;
|
|
|
+ FDropDownBorderSize: integer;
|
|
|
+ FDropDownCount: integer;
|
|
|
+ FDropDownColor: TColor;
|
|
|
+ FDropDownFontColor: TColor;
|
|
|
+ FDropDownFontHighlight: TColor;
|
|
|
+ FDropDownHighlight: TColor;
|
|
|
+ FFocusBorderColor: TColor;
|
|
|
+ FFocusBorderOpacity: byte;
|
|
|
+ FItems: TStringList;
|
|
|
+ FItemIndex: integer;
|
|
|
+ FForm: TForm;
|
|
|
+ FFormHideDate: TDateTime;
|
|
|
+ FHoverItem: integer;
|
|
|
+ FItemHeight: integer;
|
|
|
+ FListBox: TCheckListBox;
|
|
|
+ FDropDownBorderColor: TColor;
|
|
|
+ FOnDrawItem: TDrawItemEvent;
|
|
|
+ FOnDrawSelectedItem: TOnAfterRenderBCButton;
|
|
|
+ FOnChange: TNotifyEvent;
|
|
|
+ FOnDropDown: TNotifyEvent;
|
|
|
+ FDrawingDropDown: boolean;
|
|
|
+ FTimerCheckFormHide: TTimer;
|
|
|
+ FQueryFormHide: boolean;
|
|
|
+ procedure ButtonClick(Sender: TObject);
|
|
|
+ procedure DrawCheckBox(aCaption: string; State: TBGRAThemeButtonState;
|
|
|
+ aFocused: boolean; Checked: boolean; ARect: TRect;
|
|
|
+ ASurface: TBGRAThemeSurface);
|
|
|
+ procedure FormDeactivate(Sender: TObject);
|
|
|
+ procedure FormHide(Sender: TObject);
|
|
|
+ function GetArrowFlip: boolean;
|
|
|
+ function GetCaption: String;
|
|
|
+ function GetComboCanvas: TCanvas;
|
|
|
+ function GetArrowSize: integer;
|
|
|
+ function GetArrowWidth: integer;
|
|
|
+ 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 SetCanvasScaleMode(AValue: TBCCanvasScaleMode);
|
|
|
+ procedure SetCaption(AValue: String);
|
|
|
+ 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);
|
|
|
+ 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 CreateForm;
|
|
|
+ procedure FreeForm;
|
|
|
+ function GetListBox: TCheckListBox;
|
|
|
+ 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: TCheckListBox read GetListBox;
|
|
|
+ property Text: string read GetItemText;
|
|
|
+ published
|
|
|
+ property Anchors;
|
|
|
+ property Canvas: TCanvas read GetComboCanvas;
|
|
|
+ property CanvasScaleMode: TBCCanvasScaleMode read FCanvasScaleMode write SetCanvasScaleMode default csmAuto;
|
|
|
+ property Caption: String read GetCaption write SetCaption;
|
|
|
+ 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 255;
|
|
|
+ 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 GlobalOpacity: byte read GetGlobalOpacity write SetGlobalOpacity;
|
|
|
+ property MemoryUsage: TBCButtonMemoryUsage read GetMemoryUsage write SetMemoryUsage;
|
|
|
+ property Rounding: TBCRounding read GetRounding write SetRounding;
|
|
|
+ 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 TabStop;
|
|
|
+ property TabOrder;
|
|
|
+ end;
|
|
|
+
|
|
|
+procedure Register;
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+uses math, PropEdits, BGRAText;
|
|
|
+
|
|
|
+procedure Register;
|
|
|
+begin
|
|
|
+ RegisterComponents('BGRA Controls', [TBCCheckComboBox]);
|
|
|
+end;
|
|
|
+
|
|
|
+{ TBCCheckComboBox }
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.ButtonClick(Sender: TObject);
|
|
|
+const MinDelayReopen = 500/(1000*60*60*24);
|
|
|
+var
|
|
|
+ p: TPoint;
|
|
|
+ h: Integer;
|
|
|
+ s: TSize;
|
|
|
+begin
|
|
|
+ {$IFDEF DARWIN}
|
|
|
+ if Assigned(FForm) and not FForm.Visible then FreeForm;
|
|
|
+ {$ENDIF}
|
|
|
+
|
|
|
+ CreateForm;
|
|
|
+
|
|
|
+ if FForm.Visible then
|
|
|
+ FForm.Visible := false
|
|
|
+ else
|
|
|
+ if Now > FFormHideDate+MinDelayReopen then
|
|
|
+ begin
|
|
|
+ p := ControlToScreen(Point(FButton.Left, FButton.Top + FButton.Height));
|
|
|
+ FForm.Left := p.X;
|
|
|
+ FForm.Top := p.Y;
|
|
|
+ FForm.Color := FDropDownBorderColor;
|
|
|
+ FListBox.Font.Name := Button.StateNormal.FontEx.Name;
|
|
|
+ FListBox.Font.Style := Button.StateNormal.FontEx.Style;
|
|
|
+ FListBox.Font.Height := FontEmHeightSign*Button.StateNormal.FontEx.Height;
|
|
|
+ self.Canvas.Font.Assign(FListBox.Font);
|
|
|
+ if Assigned(FOnDrawItem) and (FItemHeight <> 0) then
|
|
|
+ h := FItemHeight else h := self.Canvas.GetTextHeight('Hg');
|
|
|
+ {$IFDEF WINDOWS}inc(h,6);{$ENDIF}
|
|
|
+ FListBox.ItemHeight := h;
|
|
|
+ {$IFDEF LINUX}inc(h,6);{$ENDIF}
|
|
|
+ {$IFDEF DARWIN}inc(h,2);{$ENDIF}
|
|
|
+ s := TSize.Create(FButton.Width, h*min(Items.Count, FDropDownCount) + 2*FDropDownBorderSize);
|
|
|
+ FForm.ClientWidth := s.cx;
|
|
|
+ FForm.ClientHeight := s.cy;
|
|
|
+ FListBox.SetBounds(FDropDownBorderSize,FDropDownBorderSize,
|
|
|
+ s.cx - 2*FDropDownBorderSize,
|
|
|
+ s.cy - 2*FDropDownBorderSize);
|
|
|
+ if FForm.Top + FForm.Height > Screen.WorkAreaTop + Screen.WorkAreaHeight then
|
|
|
+ FForm.Top := FForm.Top - FForm.Height - Self.Height;
|
|
|
+ if Assigned(FOnDropDown) then FOnDropDown(self);
|
|
|
+ FForm.Visible := True;
|
|
|
+ if FListBox.CanSetFocus then
|
|
|
+ FListBox.SetFocus;
|
|
|
+ FTimerCheckFormHide.Enabled:= true;
|
|
|
+ FQueryFormHide := false;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.FormDeactivate(Sender: TObject);
|
|
|
+begin
|
|
|
+ FQueryFormHide := true;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.FormHide(Sender: TObject);
|
|
|
+begin
|
|
|
+ FFormHideDate := Now;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetArrowFlip: boolean;
|
|
|
+begin
|
|
|
+ result := Button.FlipArrow;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetCaption: String;
|
|
|
+begin
|
|
|
+ Result := Button.Caption;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetComboCanvas: TCanvas;
|
|
|
+begin
|
|
|
+ if FDrawingDropDown then
|
|
|
+ result := ListBox.Canvas
|
|
|
+ else
|
|
|
+ result := inherited Canvas;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetArrowSize: integer;
|
|
|
+begin
|
|
|
+ result := Button.DropDownArrowSize;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetArrowWidth: integer;
|
|
|
+begin
|
|
|
+ result := Button.DropDownWidth;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetGlobalOpacity: byte;
|
|
|
+begin
|
|
|
+ result := Button.GlobalOpacity;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetItemText: string;
|
|
|
+begin
|
|
|
+ if ItemIndex<>-1 then
|
|
|
+ result := Items[ItemIndex]
|
|
|
+ else
|
|
|
+ result := '';
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetDropDownColor: TColor;
|
|
|
+begin
|
|
|
+ if Assigned(FListBox) then
|
|
|
+ result := FListBox.Color
|
|
|
+ else result := FDropDownColor;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetItemIndex: integer;
|
|
|
+begin
|
|
|
+ if Assigned(FListBox) then
|
|
|
+ result := FListBox.ItemIndex
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if FItemIndex >= Items.Count then
|
|
|
+ FItemIndex := -1;
|
|
|
+ result := FItemIndex;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetItems: TStrings;
|
|
|
+begin
|
|
|
+ if Assigned(FListBox) then
|
|
|
+ Result := FListBox.Items
|
|
|
+ else Result := FItems;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetMemoryUsage: TBCButtonMemoryUsage;
|
|
|
+begin
|
|
|
+ result := Button.MemoryUsage;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetOnDrawSelectedItem: TOnAfterRenderBCButton;
|
|
|
+begin
|
|
|
+ result := FOnDrawSelectedItem;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetRounding: TBCRounding;
|
|
|
+begin
|
|
|
+ result := Button.Rounding;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetStateClicked: TBCButtonState;
|
|
|
+begin
|
|
|
+ result := Button.StateClicked;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetStateHover: TBCButtonState;
|
|
|
+begin
|
|
|
+ result := Button.StateHover;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetStateNormal: TBCButtonState;
|
|
|
+begin
|
|
|
+ result := Button.StateNormal;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetStaticButton: boolean;
|
|
|
+begin
|
|
|
+ result := Button.StaticButton;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.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 TBCCheckComboBox.ListBoxMouseUp(Sender: TObject; Button: TMouseButton;
|
|
|
+ Shift: TShiftState; X, Y: Integer);
|
|
|
+begin
|
|
|
+ FQueryFormHide := true;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.ListBoxMouseLeave(Sender: TObject);
|
|
|
+begin
|
|
|
+ FHoverItem := -1;
|
|
|
+ FListBox.Repaint;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.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 TBCCheckComboBox.ListBoxSelectionChange(Sender: TObject; User: boolean);
|
|
|
+begin
|
|
|
+ Button.Caption := GetItemText;
|
|
|
+ if User and Assigned(FOnChange) then FOnChange(self);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.ListBoxDrawItem(Control: TWinControl; Index: Integer;
|
|
|
+ ARect: TRect; State: TOwnerDrawState);
|
|
|
+var
|
|
|
+ surface: TBGRAThemeSurface;
|
|
|
+ parentForm: TCustomForm;
|
|
|
+ lclDPI: Integer;
|
|
|
+begin
|
|
|
+ parentForm := GetParentForm(Control, False);
|
|
|
+ if Assigned(parentForm) then
|
|
|
+ lclDPI := parentForm.PixelsPerInch
|
|
|
+ else lclDPI := Screen.PixelsPerInch;
|
|
|
+ surface := TBGRAThemeSurface.Create(ARect, TCheckListBox(Control).Canvas, Control.GetCanvasScaleFactor, lclDPI);
|
|
|
+ try
|
|
|
+ DrawCheckBox(TCheckListBox(Control).Items[Index], btbsNormal, False, TCheckListBox(Control).Checked[Index], ARect, surface);
|
|
|
+ finally
|
|
|
+ surface.Free;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.DrawCheckBox(aCaption: string; State: TBGRAThemeButtonState;
|
|
|
+ aFocused: boolean; Checked: boolean; ARect: TRect; ASurface: TBGRAThemeSurface
|
|
|
+ );
|
|
|
+var
|
|
|
+ Style: TTextStyle;
|
|
|
+ aColor: TBGRAPixel;
|
|
|
+ aleft, atop, aright, abottom: integer;
|
|
|
+ penWidth: single;
|
|
|
+begin
|
|
|
+ with ASurface do
|
|
|
+ begin
|
|
|
+ DestCanvas.Font.Color := clBlack;
|
|
|
+ case State of
|
|
|
+ btbsHover: aColor := BGRA(0, 120, 215);
|
|
|
+ btbsActive: aColor := BGRA(0, 84, 153);
|
|
|
+ btbsDisabled:
|
|
|
+ begin
|
|
|
+ DestCanvas.Font.Color := clGray;
|
|
|
+ aColor := BGRA(204, 204, 204);
|
|
|
+ end;
|
|
|
+ else {btbsNormal}
|
|
|
+ aColor := BGRABlack;
|
|
|
+ end;
|
|
|
+
|
|
|
+ Bitmap.Fill(BGRAWhite);
|
|
|
+ BitmapRect := ARect;
|
|
|
+ penWidth := ASurface.ScaleForBitmap(10) / 10;
|
|
|
+ aleft := round(penWidth);
|
|
|
+ aright := Bitmap.Height-round(penWidth);
|
|
|
+ atop := round(penWidth);
|
|
|
+ abottom := Bitmap.Height-round(penWidth);
|
|
|
+ Bitmap.RectangleAntialias(aleft-0.5+penWidth/2, atop-0.5+penWidth/2,
|
|
|
+ aright-0.5-penWidth/2, abottom-0.5-penWidth/2,
|
|
|
+ aColor, penWidth);
|
|
|
+ aleft := round(penWidth*2);
|
|
|
+ aright := Bitmap.Height-round(penWidth*2);
|
|
|
+ atop := round(penWidth*2);
|
|
|
+ abottom := Bitmap.Height-round(penWidth*2);
|
|
|
+ if Checked then
|
|
|
+ Bitmap.DrawPolyLineAntialias(Bitmap.ComputeBezierSpline(
|
|
|
+ [BezierCurve(pointF(aleft + 2, atop + 3), PointF((aleft + aright - 1) / 2, abottom - 3)),
|
|
|
+ BezierCurve(PointF((aleft + aright - 1) / 2, abottom - 3), PointF(
|
|
|
+ (aleft + aright - 1) / 2, (atop * 2 + abottom - 1) / 3), PointF(aright - 2, atop))]),
|
|
|
+ Color, penWidth*1.5);
|
|
|
+ DrawBitmap;
|
|
|
+
|
|
|
+ if aCaption <> '' then
|
|
|
+ begin
|
|
|
+ fillchar(Style, sizeof(Style), 0);
|
|
|
+ Style.Alignment := taLeftJustify;
|
|
|
+ Style.Layout := tlCenter;
|
|
|
+ Style.Wordbreak := True;
|
|
|
+ DestCanvas.TextRect(ARect,
|
|
|
+ ARect.Height, 0, aCaption, Style);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.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 * Button.CanvasScale);
|
|
|
+ ABGRA.RectangleAntialias(ARect.Left + focusMargin, ARect.Top + focusMargin,
|
|
|
+ ARect.Right - focusMargin - 1, ARect.Bottom - focusMargin - 1,
|
|
|
+ ColorToBGRA(FocusBorderColor, FocusBorderOpacity),
|
|
|
+ Button.CanvasScale);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.OnTimerCheckFormHide(Sender: TObject);
|
|
|
+ {$ifdef WINDOWS}
|
|
|
+ function IsDropDownOnTop: boolean;
|
|
|
+ begin
|
|
|
+ result := Assigned(FForm) and (GetForegroundWindow = FForm.Handle);
|
|
|
+ end;
|
|
|
+ {$endif}
|
|
|
+
|
|
|
+begin
|
|
|
+ if Assigned(FForm) and FForm.Visible and
|
|
|
+ ({$IFDEF DARWIN}not FForm.Active or {$ENDIF}
|
|
|
+ {$IFDEF WINDOWS}not IsDropDownOnTop or{$ENDIF}
|
|
|
+ FQueryFormHide) then
|
|
|
+ begin
|
|
|
+ FForm.Visible := false;
|
|
|
+ FQueryFormHide := false;
|
|
|
+ FTimerCheckFormHide.Enabled := false;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetArrowFlip(AValue: boolean);
|
|
|
+begin
|
|
|
+ Button.FlipArrow:= AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetArrowSize(AValue: integer);
|
|
|
+begin
|
|
|
+ Button.DropDownArrowSize:= AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetArrowWidth(AValue: integer);
|
|
|
+begin
|
|
|
+ Button.DropDownWidth:= AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetCanvasScaleMode(AValue: TBCCanvasScaleMode);
|
|
|
+begin
|
|
|
+ if FCanvasScaleMode=AValue then Exit;
|
|
|
+ FCanvasScaleMode:=AValue;
|
|
|
+ UpdateButtonCanvasScaleMode;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetCaption(AValue: String);
|
|
|
+begin
|
|
|
+ Button.Caption := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetDropDownColor(AValue: TColor);
|
|
|
+begin
|
|
|
+ if Assigned(FListBox) then
|
|
|
+ FListBox.Color := AValue
|
|
|
+ else FDropDownColor:= AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetGlobalOpacity(AValue: byte);
|
|
|
+begin
|
|
|
+ Button.GlobalOpacity := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.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 TBCCheckComboBox.SetItems(AValue: TStrings);
|
|
|
+begin
|
|
|
+ if Assigned(FListBox) then
|
|
|
+ FListBox.Items.Assign(AValue)
|
|
|
+ else FItems.Assign(AValue);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetMemoryUsage(AValue: TBCButtonMemoryUsage);
|
|
|
+begin
|
|
|
+ Button.MemoryUsage := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetOnDrawSelectedItem(AValue: TOnAfterRenderBCButton);
|
|
|
+begin
|
|
|
+ if @FOnDrawSelectedItem = @AValue then Exit;
|
|
|
+ FOnDrawSelectedItem:= AValue;
|
|
|
+ FButton.ShowCaption := not Assigned(AValue);
|
|
|
+ UpdateButtonCanvasScaleMode;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetRounding(AValue: TBCRounding);
|
|
|
+begin
|
|
|
+ Button.Rounding := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetStateClicked(AValue: TBCButtonState);
|
|
|
+begin
|
|
|
+ Button.StateClicked := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetStateHover(AValue: TBCButtonState);
|
|
|
+begin
|
|
|
+ Button.StateHover := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetStateNormal(AValue: TBCButtonState);
|
|
|
+begin
|
|
|
+ Button.StateNormal := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.SetStaticButton(AValue: boolean);
|
|
|
+begin
|
|
|
+ Button.StaticButton:= AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetStyleExtension: String;
|
|
|
+begin
|
|
|
+ result := 'bccombo';
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.WMSetFocus(var Message: TLMSetFocus);
|
|
|
+begin
|
|
|
+ UpdateFocus(True);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.WMKillFocus(var Message: TLMKillFocus);
|
|
|
+begin
|
|
|
+ if Message.FocusedWnd <> Handle then
|
|
|
+ UpdateFocus(False);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.UpdateFocus(AFocused: boolean);
|
|
|
+var
|
|
|
+ lForm: TCustomForm;
|
|
|
+ oldCaption: string;
|
|
|
+begin
|
|
|
+ lForm := GetParentForm(Self);
|
|
|
+ if lForm = nil then
|
|
|
+ exit;
|
|
|
+
|
|
|
+ {$IFDEF FPC}//#
|
|
|
+ if AFocused then
|
|
|
+ ActiveDefaultControlChanged(lForm.ActiveControl)
|
|
|
+ else
|
|
|
+ ActiveDefaultControlChanged(nil);
|
|
|
+ {$ENDIF}
|
|
|
+
|
|
|
+ oldCaption := FButton.Caption;
|
|
|
+ FButton.Caption := FButton.Caption + '1';
|
|
|
+ FButton.Caption := oldCaption;
|
|
|
+
|
|
|
+ Invalidate;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.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 TBCCheckComboBox.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 TBCCheckComboBox.CreateForm;
|
|
|
+begin
|
|
|
+ if FForm = nil 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;
|
|
|
+
|
|
|
+ if FListBox = nil then
|
|
|
+ begin
|
|
|
+ FListBox := TCheckListBox.Create(self);
|
|
|
+ FListBox.Parent := FForm;
|
|
|
+ FListBox.BorderStyle := bsNone;
|
|
|
+ //FListBox.OnSelectionChange := ListBoxSelectionChange;
|
|
|
+ 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;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.FreeForm;
|
|
|
+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);
|
|
|
+end;
|
|
|
+
|
|
|
+function TBCCheckComboBox.GetListBox: TCheckListBox;
|
|
|
+begin
|
|
|
+ CreateForm;
|
|
|
+ result := FListBox;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.UpdateButtonCanvasScaleMode;
|
|
|
+begin
|
|
|
+ if (CanvasScaleMode = csmFullResolution) or
|
|
|
+ ((CanvasScaleMode = csmAuto) and not Assigned(FOnDrawSelectedItem)) then
|
|
|
+ FButton.CanvasScaleMode:= csmFullResolution
|
|
|
+ else FButton.CanvasScaleMode:= csmScaleBitmap;
|
|
|
+end;
|
|
|
+
|
|
|
+constructor TBCCheckComboBox.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;
|
|
|
+ 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);
|
|
|
+ FTimerCheckFormHide.Interval:= 30;
|
|
|
+ FTimerCheckFormHide.OnTimer:= OnTimerCheckFormHide;
|
|
|
+end;
|
|
|
+
|
|
|
+destructor TBCCheckComboBox.Destroy;
|
|
|
+begin
|
|
|
+ FreeAndNil(FItems);
|
|
|
+ inherited Destroy;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBCCheckComboBox.Assign(Source: TPersistent);
|
|
|
+var
|
|
|
+ src: TBCCheckComboBox;
|
|
|
+begin
|
|
|
+ if Source is TBCCheckComboBox then
|
|
|
+ begin
|
|
|
+ src := TBCCheckComboBox(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 TBCCheckComboBox.Clear;
|
|
|
+begin
|
|
|
+ Items.Clear;
|
|
|
+end;
|
|
|
+
|
|
|
+end.
|