Browse Source

fix of coordinates of rectangles, added bctrackbarupdown and test project

circular17 10 years ago
parent
commit
3735812328

+ 18 - 20
bcbutton.pas

@@ -76,7 +76,7 @@ type
     FBackground: TBCBackground;
     FBorder: TBCBorder;
     FFontEx: TBCFont;
-    procedure OnChangeFont(Sender: TObject; AData: PtrInt);
+    procedure OnChangeFont(Sender: TObject; {%H-}AData: PtrInt);
     procedure OnChangeChildProperty(Sender: TObject; AData: PtrInt);
     procedure SetBackground(AValue: TBCBackground);
     procedure SetBorder(AValue: TBCBorder);
@@ -174,7 +174,7 @@ type
     { Protected declarations }
     procedure LimitMemoryUsage;
     procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
-      WithThemeSpace: boolean); override;
+      {%H-}WithThemeSpace: boolean); override;
     class function GetControlClassDefaultSize: TSize; override;
     procedure Click; override;
     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
@@ -252,7 +252,7 @@ type
     procedure SaveToFile(AFileName: string);
     procedure LoadFromFile(AFileName: string);
     procedure AssignFromFile(AFileName: string);
-    procedure OnFindClass(Reader: TReader; const AClassName: string;
+    procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
       var ComponentClass: TComponentClass);
   end;
 
@@ -324,7 +324,7 @@ procedure Register;
 
 implementation
 
-uses LCLIntf, Math, LCLProc, BGRAPolygon, BCTools, SysUtils, PropEdits, GraphPropEdits;
+uses LCLIntf, Math, LCLProc, BCTools, SysUtils, PropEdits, GraphPropEdits;
 
 type
   TBCButtonImageIndexPropertyEditor = class(TImageIndexPropertyEditor)
@@ -685,23 +685,22 @@ begin
   { Refreshing size }
   ABGRA.SetSize(Width, Height);
 
-  { Calculating rect }
+  { Clearing previous paint }
+  ABGRA.Fill(BGRAPixelTransparent);
+
+  { Basic body }
   r := GetButtonRect;
+  RenderState(ABGRA, AState, r, FRounding);
+
+  { Calculating rect }
   CalculateBorderRect(AState.Border, r);
 
   if FStyle = bbtDropDown then
   begin
     r_a := GetDropDownRect;
+    RenderState(ABGRA, AState, r_a, FRoundingDropDown);
     CalculateBorderRect(AState.Border, r_a);
-  end;
 
-  { Clearing previous paint }
-  ABGRA.Fill(BGRAPixelTransparent);
-  { Basic body }
-  RenderState(ABGRA, AState, r, FRounding);
-  if FStyle = bbtDropDown then
-  begin
-    RenderState(ABGRA, AState, r_a, FRoundingDropDown);
     // Click offset for arrow
     if FClickOffest and (AState = FStateClicked) then
     begin
@@ -773,8 +772,7 @@ end;
 procedure TCustomBCButton.RenderState(ABGRA: TBGRABitmapEx;
   AState: TBCButtonState; const ARect: TRect; ARounding: TBCRounding);
 begin
-  RenderBackground(ARect, AState.FBackground, TBGRABitmap(ABGRA), ARounding);
-  RenderBorder(ARect, AState.FBorder, TBGRABitmap(ABGRA), ARounding);
+  RenderBackgroundAndBorder(ARect, AState.FBackground, TBGRABitmap(ABGRA), ARounding, AState.FBorder);
 end;
 
 procedure TCustomBCButton.OnChangeGlyph(Sender: TObject);
@@ -1025,16 +1023,16 @@ end;
 procedure TCustomBCButton.CalculatePreferredSize(
   var PreferredWidth, PreferredHeight: integer; WithThemeSpace: boolean);
 var
-  AWidth: integer;
+//  AWidth: integer;
   gh: integer = 0;
   gw: integer = 0;
 begin
   if (Parent = nil) or (not Parent.HandleAllocated) then
     Exit;
-  if WidthIsAnchored then
+{  if WidthIsAnchored then
     AWidth := Width
   else
-    AWidth := 10000;
+    AWidth := 10000;}
 
   PreferredWidth := 0;
   PreferredHeight := 0;
@@ -1183,8 +1181,8 @@ end;
 
 procedure TCustomBCButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
   X, Y: integer);
-var
-  p: TPoint;
+{var
+  p: TPoint;}
 begin
   inherited MouseUp(Button, Shift, X, Y);
   if csDesigning in ComponentState then

+ 5 - 6
bclabel.pas

@@ -65,11 +65,11 @@ type
     procedure SetBackground(AValue: TBCBackground);
     procedure SetBorder(AValue: TBCBorder);
     procedure SetFontEx(AValue: TBCFont);
-    procedure OnChangeProperty(Sender: TObject; Data: PtrInt);
-    procedure OnChangeFont(Sender: TObject; AData: PtrInt);
+    procedure OnChangeProperty(Sender: TObject; {%H-}Data: PtrInt);
+    procedure OnChangeFont(Sender: TObject; {%H-}AData: PtrInt);
   protected
     procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
-      WithThemeSpace: boolean); override;
+      {%H-}WithThemeSpace: boolean); override;
     class function GetControlClassDefaultSize: TSize; override;
     procedure TextChanged; override;
   protected
@@ -95,7 +95,7 @@ type
     { Streaming }
     procedure SaveToFile(AFileName: string);
     procedure LoadFromFile(AFileName: string);
-    procedure OnFindClass(Reader: TReader; const AClassName: string;
+    procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
       var ComponentClass: TComponentClass);
   end;
 
@@ -157,8 +157,7 @@ begin
   r := FBGRA.ClipRect;
   CalculateBorderRect(FBorder,r);
 
-  RenderBackground(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding);
-  RenderBorder(r, FBorder, TBGRABitmap(FBGRA), FRounding);
+  RenderBackgroundAndBorder(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, FBorder);
   RenderText(FBGRA.ClipRect, FFontEx, Caption, TBGRABitmap(FBGRA));
 
   {$IFDEF DEBUG}

+ 10 - 7
bcpanel.pas

@@ -73,8 +73,8 @@ type
     procedure SetFontEx(AValue: TBCFont);
     procedure SetRounding(AValue: TBCRounding);
     procedure Render;
-    procedure OnChangeProperty(Sender: TObject; AData: PtrInt);
-    procedure OnChangeFont(Sender: TObject; AData: PtrInt);
+    procedure OnChangeProperty(Sender: TObject; {%H-}AData: PtrInt);
+    procedure OnChangeFont(Sender: TObject; {%H-}AData: PtrInt);
   protected
     { Protected declarations }
     procedure AdjustClientRect(var aRect: TRect); override;
@@ -112,7 +112,7 @@ type
     { Streaming }
     procedure SaveToFile(AFileName: string);
     procedure LoadFromFile(AFileName: string);
-    procedure OnFindClass(Reader: TReader; const AClassName: string;
+    procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
       var ComponentClass: TComponentClass);
   end;
 
@@ -231,14 +231,13 @@ begin
 
   FBGRA.SetSize(Width, Height);
   FBGRA.Fill(BGRAPixelTransparent);
-  RenderBackground(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding);
   r := FBGRA.ClipRect;
 
   case FBorderBCStyle of
   bpsBorder:
     begin
+      RenderBackgroundAndBorder(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, FBorder);
       CalculateBorderRect(FBorder,r);
-      RenderBorder(r,FBorder, TBGRABitmap(FBGRA), FRounding);
     end;
   bpsFrame3d:
     begin
@@ -247,13 +246,17 @@ begin
         FBGRA.CanvasBGRA.Frame3d(r, FBevelWidth, FBevelOuter,
           BGRA(255, 255, 255, 180), BGRA(0, 0, 0, 160)); // Note: Frame3D inflates ARect
 
-      InflateRect(r, -FBevelWidth, -FBevelWidth);
-
       // if BevelInner is set then skip the BorderWidth and draw a frame with BevelWidth
       if (FBevelInner <> bvNone) and (FBevelWidth > 0) then
+      begin
+        InflateRect(r, -FBevelWidth, -FBevelWidth);
         FBGRA.CanvasBGRA.Frame3d(r, FBevelWidth, FBevelInner,
           BGRA(255, 255, 255, 160), BGRA(0, 0, 0, 160)); // Note: Frame3D inflates ARect
+      end;
+      RenderBackground(r, FBackground, TBGRABitmap(FBGRA), nil, True);
     end;
+  else
+    RenderBackground(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, True);
   end;
 
   if Caption <> '' then

+ 78 - 66
bctools.pas

@@ -43,26 +43,32 @@ procedure AssignBCFont(AFont: TBCFont; out ATargetBGRA: TBGRABitmap);
 // Calculate text height and width (doesn't include wordwrap - just single line)
 procedure CalculateTextSize(const AText: String; AFont: TBCFont;
   out ANewWidth, ANewHeight: integer);
-// As long as there are differences between the size of the font, this method is useless
-procedure CalculateTextRect(const AText: String; AFont: TBCFont; out ARect: TRect);
 // This method correct TRect to border width. As far as border width is bigger,
 // BGRA drawing rectangle with offset (half border width)
 procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
+// This returns a rectangle that is inside the border outline
+procedure CalculateInnerRect(ABorder: TBCBorder; var ARect: TRect);
 // Create BGRA Gradient Scanner based on BCGradient properties
 function CreateGradient(AGradient: TBCGradient; ARect: TRect): TBGRAGradientScanner;
 // Render arrow (used by BCButton with DropDownMenu style)
-procedure RenderArrow(out ATargetBGRA: TBGRABitmap; const ARect: TRect;
+procedure RenderArrow(ATargetBGRA: TBGRABitmap; const ARect: TRect;
   ASize: Integer; ADirection: TBCArrowDirection; AColor: TColor = clBlack;
   AOpacity: Byte = 255);
 // Render customizable backgroud (used e.g. by TBCButton, TBCPanel, TBCLabel)
-procedure RenderBackground(const ARect: TRect; const ABackground: TBCBackground;
-  out ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
+procedure RenderBackground(const ARect: TRect; ABackground: TBCBackground;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil; AHasNoBorder: boolean = false);
+procedure RenderBackgroundF(x1,y1,x2,y2: single; ABackground: TBCBackground;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
+procedure RenderBackgroundAndBorder(const ARect: TRect; ABackground: TBCBackground;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding; ABorder: TBCBorder);
 // Render customizable border (used e.g. by TBCButton, TBCPanel, TBCLabel)
-procedure RenderBorder(const ARect: TRect; const ABorder: TBCBorder;
-  out ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
+procedure RenderBorder(const ARect: TRect; ABorder: TBCBorder;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
+procedure RenderBorderF(x1,y1,x2,y2: single; ABorder: TBCBorder;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
 // Render BCFont (used e.g. by TBCButton, TBCPanel, TBCLabel)
-procedure RenderText(const ARect: TRect; const AFont: TBCFont;
-  const AText: String; out ATargetBGRA: TBGRABitmap);
+procedure RenderText(const ARect: TRect; AFont: TBCFont;
+  const AText: String; ATargetBGRA: TBGRABitmap);
 // Return LCL horizontal equivalent for BCAlignment
 function BCAlign2HAlign(AAlign: TBCAlignment): TAlignment;
 // Return LCL vertical equivalent for BCAlignment
@@ -72,49 +78,26 @@ implementation
 
 uses Types, BGRAPolygon, BGRAFillInfo, BGRAText, math, LCLType, LCLIntf;
 
-procedure CalculateTextRect(const AText: String; AFont: TBCFont; out ARect: TRect);
-var
-  tmp: TBGRABitmap;
-  flags: LongInt;
+procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
+var w: integer;
 begin
-  tmp := TBGRABitmap.Create(0,0);
-  AssignBCFont(AFont,tmp);
-  flags := 0;
-  case AFont.TextAlignment of
-    bcaCenter, bcaCenterBottom, bcaCenterTop: flags := flags or DT_CENTER;
-    bcaRightCenter, bcaRightBottom, bcaRightTop: flags := flags or DT_RIGHT;
-  end;
-  case AFont.TextAlignment of
-    bcaLeftTop, bcaCenterTop, bcaRightTop: flags := flags or DT_TOP;
-    bcaLeftCenter, bcaCenter, bcaRightCenter: flags := flags or DT_VCENTER;
-    bcaLeftBottom, bcaCenterBottom, bcaRightBottom: flags := flags or DT_BOTTOM;
-  end;
-  if AFont.EndEllipsis then
-    flags := flags or DT_END_ELLIPSIS;
-  // This condition is from TCanvas.TextRect
-  if AFont.WordBreak then
-  begin
-    flags := flags or DT_WORDBREAK;
-    if AFont.EndEllipsis then
-      flags := flags and not DT_END_ELLIPSIS;
-  end;
-  if AFont.SingleLine then
-    flags := flags or DT_SINGLELINE;
-
-  flags := flags or DT_CALCRECT;
-
-  LCLIntf.DrawText(tmp.Canvas.Handle, PChar(AText), Length(AText), ARect, flags);
-
-  tmp.Free;
+  if ABorder = nil then Exit;
+  w := ABorder.Width div 2;
+  Inc(ARect.Left, w);
+  Inc(ARect.Top, w);
+  Dec(ARect.Right, w);
+  Dec(ARect.Bottom, w);
 end;
 
-procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
+procedure CalculateInnerRect(ABorder: TBCBorder; var ARect: TRect);
+var w: integer;
 begin
-  if ABorder = nil then Exit;
-  Inc(ARect.Left, Round(ABorder.Width / 2));
-  Inc(ARect.Top, Round(ABorder.Width / 2));
-  Dec(ARect.Right, Round(ABorder.Width / 2) + 1);
-  Dec(ARect.Bottom, Round(ABorder.Width / 2) + 1);
+  if (ABorder = nil) or (ABorder.Style = bboNone) then Exit;
+  w := ABorder.Width;
+  Inc(ARect.Left, w);
+  Inc(ARect.Top, w);
+  Dec(ARect.Right, w);
+  Dec(ARect.Bottom, w);
 end;
 
 function CreateGradient(AGradient: TBCGradient; ARect: TRect): TBGRAGradientScanner;
@@ -131,7 +114,29 @@ begin
     AGradient.ColorCorrection, AGradient.Sinus);
 end;
 
-procedure RenderBorder(const ARect: TRect; const ABorder: TBCBorder; out
+procedure RenderBackgroundAndBorder(const ARect: TRect;
+  ABackground: TBCBackground; ATargetBGRA: TBGRABitmap;
+  ARounding: TBCRounding; ABorder: TBCBorder);
+var w: single;
+begin
+  if ABorder.Style = bboNone then
+    RenderBackground(ARect,ABackground,ATargetBGRA,ARounding,True)
+  else
+  begin
+    w := (ABorder.Width-1)/2;
+    RenderBackgroundF(ARect.Left+w,ARect.Top+w,ARect.Right-1-w,ARect.Bottom-1-w,ABackground,ATargetBGRA,ARounding);
+    RenderBorderF(ARect.Left+w,ARect.Top+w,ARect.Right-1-w,ARect.Bottom-1-w,ABorder,ATargetBGRA,ARounding);
+  end;
+end;
+
+procedure RenderBorder(const ARect: TRect; ABorder: TBCBorder;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
+begin
+  RenderBorderF(ARect.Left,ARect.Top,ARect.Right-1,ARect.Bottom-1,ABorder,
+  ATargetBGRA,ARounding);
+end;
+
+procedure RenderBorderF(x1,y1,x2,y2: single; ABorder: TBCBorder;
   ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
 var
   fiLight: TFillBorderRoundRectInfo;
@@ -152,7 +157,7 @@ begin
     ropt := ARounding.RoundOptions;
   end;
 
-  ATargetBGRA.RoundRectAntialias(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom,
+  ATargetBGRA.RoundRectAntialias(x1,y1,x2,y2,
     rx, ry, ColorToBGRA(ColorToRGB(ABorder.Color),ABorder.ColorOpacity),
     ABorder.Width, ropt);
 
@@ -160,7 +165,7 @@ begin
   begin
     //compute light position
     fiLight := TFillBorderRoundRectInfo.Create(
-      ARect.Left, ARect.Top, ARect.Right, ARect.Bottom, rx,
+      x1,y1,x2,y2, rx,
       ry, ABorder.Width + ABorder.LightWidth, ropt);
     //check if there is an inner position
     if fiLight.InnerBorder <> nil then
@@ -173,8 +178,8 @@ begin
   end;
 end;
 
-procedure RenderText(const ARect: TRect; const AFont: TBCFont;
-  const AText: String; out ATargetBGRA: TBGRABitmap);
+procedure RenderText(const ARect: TRect; AFont: TBCFont;
+  const AText: String; ATargetBGRA: TBGRABitmap);
 var
   shd: TBGRABitmap;
   hal: TAlignment;
@@ -186,7 +191,7 @@ begin
   hal := BCAlign2HAlign(AFont.TextAlignment);
   val := BCAlign2VAlign(AFont.TextAlignment);
 
-  FillChar(st, SizeOf(st),0);
+  FillChar({%H-}st, SizeOf({%H-}st),0);
 
   st.Wordbreak   := AFont.WordBreak;
   st.Alignment   := hal;
@@ -312,7 +317,7 @@ begin
   ANewHeight := s.cy;
 end;
 
-procedure RenderArrow(out ATargetBGRA: TBGRABitmap; const ARect: TRect;
+procedure RenderArrow(ATargetBGRA: TBGRABitmap; const ARect: TRect;
   ASize: Integer; ADirection: TBCArrowDirection; AColor: TColor; AOpacity: Byte);
 var
   p: ArrayOfTPointF;
@@ -388,7 +393,7 @@ begin
   temp.Free;
 end;
 
-procedure RenderBackground(const ARect: TRect; const ABackground: TBCBackground; out
+procedure RenderBackgroundF(x1,y1,x2,y2: single; ABackground: TBCBackground;
   ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil);
 var
   backcolor: TBGRAPixel;
@@ -396,7 +401,6 @@ var
   back: TBGRABitmap;
   grect1, grect2: TRect;
   gra: TBGRAGradientScanner;
-  fiLight: TFillBorderRoundRectInfo;
   rx,ry: Byte;
   ropt: TRoundRectangleOptions;
 begin
@@ -424,8 +428,7 @@ begin
   case ABackground.Style of
     bbsClear, bbsColor:
       { Solid background color }
-      ATargetBGRA.FillRoundRectAntialias(ARect.Left, ARect.Top, ARect.Right,
-        ARect.Bottom, rx, ry, backcolor, ropt);
+      ATargetBGRA.FillRoundRectAntialias(x1,y1,x2,y2, rx, ry, backcolor, ropt);
     bbsGradient:
     begin
       { Using multishape filler to merge background gradient and border }
@@ -434,12 +437,12 @@ begin
 
       { Gradients }
       back := TBGRABitmap.Create(ATargetBGRA.Width, ATargetBGRA.Height, BGRAPixelTransparent);
-      grect1 := ARect;
-      grect2 := ARect;
+      grect1 := rect(floor(x1),floor(y1),ceil(x2)+1,ceil(y2)+1);
+      grect2 := grect1;
       { Gradient 1 }
       if ABackground.Gradient1EndPercent > 0 then
       begin
-        grect1.Bottom := Round((grect1.Bottom / 100) * ABackground.Gradient1EndPercent);
+        grect1.Bottom := grect1.top + Round(((grect1.Bottom-grect1.Top) / 100) * ABackground.Gradient1EndPercent);
         gra := CreateGradient(ABackground.Gradient1, grect1);
         back.FillRect(grect1.Left, grect1.Top, grect1.Right, grect1.Bottom,
           gra, dmSet
@@ -449,8 +452,7 @@ begin
       { Gradient 2 }
       if ABackground.Gradient1EndPercent < 100 then
       begin
-        if grect1.Bottom < ARect.Bottom then
-          grect2.Top := grect1.Bottom - 1;
+        grect2.Top := grect1.Bottom;
         gra := CreateGradient(ABackground.Gradient2, grect2);
         back.FillRect(grect2.Left, grect2.Top, grect2.Right, grect2.Bottom,
           gra, dmSet
@@ -458,8 +460,7 @@ begin
         gra.Free;
       end;
 
-      multi.AddRoundRectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom,
-        rx, ry, back, ropt);
+      multi.AddRoundRectangle(x1,y1,x2,y2, rx, ry, back, ropt);
 
       multi.Draw(ATargetBGRA);
       multi.Free;
@@ -468,5 +469,16 @@ begin
   end;
 end;
 
+procedure RenderBackground(const ARect: TRect; ABackground: TBCBackground;
+  ATargetBGRA: TBGRABitmap; ARounding: TBCRounding = nil; AHasNoBorder: boolean = false);
+var
+  extraSize: single;
+begin
+  if AHasNoBorder then extraSize := 0.5
+    else extraSize := 0;
+  RenderBackgroundF(ARect.Left-extraSize, ARect.Top-extraSize, ARect.Right-1+extraSize,
+        ARect.Bottom-1+extraSize,ABackground,ATargetBGRA,ARounding);
+end;
+
 end.
 

+ 696 - 0
bctrackbarupdown.pas

@@ -0,0 +1,696 @@
+unit BCTrackbarUpdown;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  LCLType, Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
+  ExtCtrls, BGRABitmap, BCBaseCtrls, BCTypes;
+
+type
+  TTrackBarUpDownChangeEvent = procedure(Sender: TObject; AByUser: boolean) of object;
+
+  { TCustomBCTrackbarUpdown }
+
+  TCustomBCTrackbarUpdown = class(TBCCustomControl)
+  private
+    FArrowColor: TColor;
+    procedure SetArrowColor(AValue: TColor);
+  protected
+    FHandlingUserInput: boolean;
+    FLongTimeInterval,FShortTimeInterval: integer;
+    FMinValue,FMaxValue,FIncrement,FValue: integer;
+    FBarExponent: single;
+    FSelStart,FSelLength: integer;
+    FEmptyText: boolean;
+    FBarClick,FUpClick,FDownClick: boolean;
+
+    FTimer: TTimer;
+    FOnChange: TTrackBarUpDownChangeEvent;
+    FBCBorder: TBCBorder;
+    FBCRounding: TBCRounding;
+    FBCBackground: TBCBackground;
+    FBCButtonBackground,FBCButtonDownBackground: TBCBackground;
+
+    FTextLeft: Integer;
+    FBarLeft,FBarTop,FBarWidth,FBarHeight: Integer;
+    FUpDownWidth: Integer;
+    FUpDownLeft: Integer;
+    function GetValue: integer;
+    procedure SetBarExponent(AValue: single);
+    procedure SetBCBackground(AValue: TBCBackground);
+    procedure SetBCBorder(AValue: TBCBorder);
+    procedure SetBCButtonBackground(AValue: TBCBackground);
+    procedure SetBCButtonDownBackground(AValue: TBCBackground);
+    procedure SetBCRounding(AValue: TBCRounding);
+    procedure OnChangeProperty(Sender: TObject; {%H-}AData: PtrInt);
+    procedure Timer(Sender: TObject);
+    procedure RenderOnBitmap(ABitmap: TBGRABitmap);
+    procedure DrawControl; override;
+    procedure DoSelectAll;
+    function GetText: string; virtual;
+    procedure SetText(AValue: string); virtual;
+    procedure EnabledChanged; override;
+    procedure NotifyChange; virtual;
+    procedure SetIncrement(AValue: integer);
+    procedure SetMaxValue(AValue: integer);
+    procedure SetMinValue(AValue: integer);
+    procedure SetValue(AValue: integer);
+    function ValueToBarPos(AValue: integer): integer;
+    function BarPosToValue(ABarPos: integer): integer;
+    procedure MouseDown(Button: TMouseButton; {%H-}Shift: TShiftState; X, Y: Integer); override;
+    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
+    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
+    procedure UTF8KeyPress(var UTF8Key: TUTF8Char); override;
+    procedure DoEnter; override;
+    procedure DoExit; override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    procedure SelectAll;
+    function RemoveSelection: boolean; //returns True if there was a selection to be removed
+    procedure DelayTimer; //use after the program has been busy updating something according to the value of this component
+    procedure SetFocus; override;
+    destructor Destroy; override;
+    property Border: TBCBorder read FBCBorder write SetBCBorder;
+    property Background: TBCBackground read FBCBackground write SetBCBackground;
+    property ButtonBackground: TBCBackground read FBCButtonBackground write SetBCButtonBackground;
+    property ButtonDownBackground: TBCBackground read FBCButtonDownBackground write SetBCButtonDownBackground;
+    property Rounding: TBCRounding read FBCRounding write SetBCRounding;
+    property ArrowColor: TColor read FArrowColor write SetArrowColor;
+
+    property BarExponent: single read FBarExponent write SetBarExponent;
+    property Increment: integer read FIncrement write SetIncrement;
+    property LongTimeInterval: integer read FLongTimeInterval write FLongTimeInterval;
+    property MinValue: integer read FMinValue write SetMinValue;
+    property MaxValue: integer read FMaxValue write SetMaxValue;
+    property OnChange: TTrackBarUpDownChangeEvent read FOnChange write FOnChange;
+    property Text: string read GetText write SetText;
+    property Value: integer read GetValue write SetValue;
+    property SelStart: integer read FSelStart;
+    property SelLength: integer read FSelLength;
+    property ShortTimeInterval: integer read FShortTimeInterval write FShortTimeInterval;
+  end;
+
+  TBCTrackbarUpdown = class(TCustomBCTrackbarUpdown)
+  published
+    property BarExponent;
+    property Increment;
+    property LongTimeInterval;
+    property MinValue;
+    property MaxValue;
+    property OnChange;
+    property Value;
+    property SelStart;
+    property SelLength;
+    property ShortTimeInterval;
+    property Background;
+    property ButtonBackground;
+    property ButtonDownBackground;
+    property Border;
+    property Rounding;
+    property Font;
+
+    //inherited
+    property Align;
+    property Anchors;
+    property BorderSpacing;
+    property ChildSizing;
+    property ClientHeight;
+    property ClientWidth;
+    property Constraints;
+    property DockSite;
+    property DragCursor;
+    property DragKind;
+    property DragMode;
+    property Enabled;
+    property ParentShowHint;
+    property PopupMenu;
+    property ShowHint;
+    property TabOrder;
+    property TabStop;
+    property UseDockManager default True;
+    property Visible;
+    property OnClick;
+    property OnContextPopup;
+    property OnDockDrop;
+    property OnDockOver;
+    property OnDblClick;
+    property OnDragDrop;
+    property OnDragOver;
+    property OnEndDock;
+    property OnEndDrag;
+    property OnEnter;
+    property OnExit;
+    property OnGetSiteInfo;
+    property OnGetDockCaption;
+    property OnMouseDown;
+    property OnMouseEnter;
+    property OnMouseLeave;
+    property OnMouseMove;
+    property OnMouseUp;
+    property OnResize;
+    property OnStartDock;
+    property OnStartDrag;
+    property OnUnDock;
+  end;
+
+procedure Register;
+
+implementation
+
+uses BGRABitmapTypes, Types, Math, BCTools;
+
+procedure Register;
+begin
+{$I icons\bctrackbarupdown_icon.lrs}
+  RegisterComponents('BGRA Controls', [TBCTrackbarUpdown]);
+end;
+
+{ TCustomBCTrackbarUpdown }
+
+function TCustomBCTrackbarUpdown.GetText: string;
+begin
+  if FEmptyText then result := '' else
+    result := IntToStr(FValue);
+end;
+
+procedure TCustomBCTrackbarUpdown.SetText(AValue: string);
+var errPos,tempValue: integer;
+  txt: string;
+  prevActualValue: integer;
+begin
+  if trim(AValue) = '' then
+  begin
+    if not FEmptyText then
+    begin
+      FEmptyText:= true;
+      Invalidate;
+    end;
+    exit;
+  end;
+  prevActualValue:= Value;
+  val(AValue,tempValue,errPos);
+  if errPos = 0 then
+  begin
+    if tempValue > FMaxValue then tempValue := FMaxValue;
+    if (FValue = tempValue) and not FEmptyText then exit;
+    FValue := tempValue;
+    FEmptyText:= false;
+  end;
+  txt := Text;
+  if FSelStart > length(txt) then FSelStart := length(txt);
+  if FSelStart+FSelLength > length(txt) then FSelLength:= length(txt)-FSelStart;
+  Repaint;
+  if Value <> prevActualValue then NotifyChange;
+end;
+
+procedure TCustomBCTrackbarUpdown.EnabledChanged;
+begin
+  inherited EnabledChanged;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.NotifyChange;
+begin
+  if Assigned(FOnChange) then FOnChange(self, FHandlingUserInput);
+end;
+
+procedure TCustomBCTrackbarUpdown.SetIncrement(AValue: integer);
+begin
+  if FIncrement=AValue then Exit;
+  FIncrement:=AValue;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetMaxValue(AValue: integer);
+begin
+  if AValue < 0 then AValue := 0;
+  if FMaxValue=AValue then Exit;
+  FMaxValue:=AValue;
+  if FMaxValue < FMinValue then FMinValue := FMaxValue;
+  if AValue > FMaxValue then FMaxValue:= AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetMinValue(AValue: integer);
+begin
+  if AValue < 0 then AValue := 0;
+  if FMinValue=AValue then Exit;
+  FMinValue:=AValue;
+  if FMinValue > FMaxValue then FMaxValue := FMinValue;
+  if AValue < FMinValue then FMinValue:= AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetValue(AValue: integer);
+begin
+  if AValue < FMinValue then AValue := FMinValue;
+  if AValue > FMaxValue then AValue := FMaxValue;
+  if FValue=AValue then Exit;
+  FValue:=AValue;
+  FEmptyText:= false;
+  DoSelectAll;
+  Invalidate;
+  NotifyChange;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetArrowColor(AValue: TColor);
+begin
+  if FArrowColor=AValue then Exit;
+  FArrowColor:=AValue;
+  Invalidate;
+end;
+
+function TCustomBCTrackbarUpdown.GetValue: integer;
+begin
+  if FValue < FMinValue then result := FMinValue else
+    result := FValue;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetBarExponent(AValue: single);
+begin
+  if AValue <= 0 then exit;
+  if FBarExponent=AValue then Exit;
+  FBarExponent:=AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetBCBackground(AValue: TBCBackground);
+begin
+  if FBCBackground=AValue then Exit;
+  FBCBackground.Assign(AValue);
+end;
+
+procedure TCustomBCTrackbarUpdown.SetBCBorder(AValue: TBCBorder);
+begin
+  if FBCBorder=AValue then Exit;
+  FBCBorder.Assign(AValue);
+end;
+
+procedure TCustomBCTrackbarUpdown.SetBCButtonBackground(AValue: TBCBackground);
+begin
+  if FBCButtonBackground=AValue then Exit;
+  FBCButtonBackground.Assign(AValue);
+end;
+
+procedure TCustomBCTrackbarUpdown.SetBCButtonDownBackground(
+  AValue: TBCBackground);
+begin
+  if FBCButtonDownBackground=AValue then Exit;
+  FBCButtonDownBackground.Assign(AValue);
+end;
+
+procedure TCustomBCTrackbarUpdown.SetBCRounding(AValue: TBCRounding);
+begin
+  if FBCRounding=AValue then Exit;
+  FBCRounding.Assign(AValue);
+end;
+
+procedure TCustomBCTrackbarUpdown.OnChangeProperty(Sender: TObject;
+  AData: PtrInt);
+begin
+  RenderControl;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.Timer(Sender: TObject);
+begin
+  FHandlingUserInput:= true;
+  if FUpClick then
+  begin
+    Value := Value + Increment;
+  end else
+  if FDownClick then
+    Value := Value - Increment;
+  FHandlingUserInput:= false;
+  FTimer.Interval := ShortTimeInterval;
+end;
+
+procedure TCustomBCTrackbarUpdown.RenderOnBitmap(ABitmap: TBGRABitmap);
+var bordercolor,fgcolor,btntext: TBGRAPixel;
+  x,y,ty,barx: integer;
+  s: TSize;
+  midy: integer;
+  midx: single;
+  beforeSel,inSel,afterSel: string;
+  bounds,fullBounds: TRect;
+begin
+  fullbounds := rect(0,0,ABitmap.Width,ABitmap.Height);
+  bounds := fullBounds;
+  CalculateInnerRect(Border, bounds);
+  ty := bounds.bottom-bounds.top-2;
+  FTextLeft := bounds.left+1+((ty+5) div 10);
+  FBarHeight := (bounds.bottom-bounds.top+3) div 5+1;
+  FUpDownWidth := (ty*3+3) div 5;
+  FUpDownLeft := bounds.right-FUpDownWidth;
+  FBarLeft := bounds.left+1;
+  if (Rounding.RoundX > 1) and (Rounding.RoundY > 1) then
+    FBarLeft += FBarHeight+1;
+  FBarWidth := bounds.right-FUpDownWidth-FBarHeight+1-FBarLeft;
+  FBarTop := bounds.bottom-FBarHeight;
+  midy := ABitmap.Height div 2;
+
+  ABitmap.ClipRect := rect(fullbounds.left,fullbounds.top,FUpDownLeft+1,fullbounds.bottom);
+  RenderBackgroundAndBorder(fullbounds, Background, ABitmap, Rounding, Border);
+
+  bordercolor := ColorToBGRA(ColorToRGB(Border.Color),Border.ColorOpacity);
+  ABitmap.VertLine(FUpDownLeft,bounds.top,bounds.bottom-1,bordercolor,dmDrawWithTransparency);
+
+  if FUpClick then
+  begin
+    ABitmap.ClipRect := rect(FUpDownLeft+1,fullbounds.top,fullbounds.Right,midy);
+    RenderBackgroundAndBorder(fullbounds, ButtonDownBackground, ABitmap, Rounding, Border);
+    ABitmap.ClipRect := rect(FUpDownLeft+1,midy,fullbounds.Right,fullbounds.bottom);
+    RenderBackgroundAndBorder(fullbounds, ButtonBackground, ABitmap, Rounding, Border);
+  end else
+  if FDownClick then
+  begin
+    ABitmap.ClipRect := rect(FUpDownLeft+1,fullbounds.top,fullbounds.Right,midy+1);
+    RenderBackgroundAndBorder(fullbounds, ButtonBackground, ABitmap, Rounding, Border);
+    ABitmap.ClipRect := rect(FUpDownLeft+1,midy+1,fullbounds.Right,fullbounds.bottom);
+    RenderBackgroundAndBorder(fullbounds, ButtonDownBackground, ABitmap, Rounding, Border);
+  end else
+  begin
+    ABitmap.ClipRect := rect(FUpDownLeft+1,fullbounds.top,fullbounds.Right,fullbounds.bottom);
+    RenderBackgroundAndBorder(fullbounds, ButtonBackground, ABitmap, Rounding, Border);
+  end;
+  ABitmap.NoClip;
+  ABitmap.HorizLine(FUpDownLeft+1,midy,bounds.right-1,bordercolor,dmDrawWithTransparency);
+
+  ABitmap.FontQuality := fqFineAntialiasing;
+  ABitmap.FontName := Font.Name;
+  ABitmap.FontStyle := Font.Style;
+  ABitmap.FontHeight := ((ty-FBarHeight+1)*8+4) div 9;
+  fgcolor := ColorToBGRA(ColorToRGB(Font.Color));
+
+  x := FTextLeft;
+  y := bounds.top+1;
+  if Focused then
+  begin
+    if SelStart = 0 then
+    begin
+      beforeSel := '';
+      inSel := Text;
+    end else
+    begin
+      beforeSel := copy(Text,1,SelStart);
+      inSel := copy(Text,SelStart+1,length(Text)-SelStart);
+    end;
+    if length(inSel)>SelLength then
+    begin
+      afterSel:= copy(inSel,SelLength+1,length(inSel)-SelLength);
+      inSel := copy(inSel,1,SelLength);
+    end else
+      afterSel := '';
+    ABitmap.TextOut(x,y,beforeSel,fgcolor);
+    inc(x, ABitmap.TextSize(beforeSel).cx);
+    if inSel = '' then ABitmap.SetVertLine(x,y,y+ABitmap.FontFullHeight-1,fgcolor)
+    else
+    begin
+      s := ABitmap.TextSize(inSel);
+      ABitmap.FillRect(x,y+1,x+s.cx,y+s.cy,ColorToBGRA(ColorToRGB(clHighlight)),dmSet);
+      ABitmap.TextOut(x,y,inSel,ColorToBGRA(ColorToRGB(clHighlightText)));
+      inc(x,s.cx);
+    end;
+    ABitmap.TextOut(x,y,afterSel,fgcolor);
+  end else
+  begin
+    if Enabled then
+      ABitmap.TextOut(x,y,Text,fgcolor)
+    else
+      ABitmap.TextOut(x,y,Text,BGRA(fgcolor.red,fgcolor.green,fgcolor.blue,fgcolor.alpha div 2));
+  end;
+
+  barx := ValueToBarPos(Value);
+  ABitmap.FillPolyAntialias([PointF(barx,FBarTop),PointF(barx+FBarHeight,FBarTop+FBarHeight),
+  PointF(barx-FBarHeight,FBarTop+FBarHeight)],fgcolor);
+  midx := FUpDownLeft+(FUpDownWidth-1)/2;
+  btntext := ColorToBGRA(ColorToRGB(FArrowColor));
+  ABitmap.FillPolyAntialias([PointF(FUpDownLeft+2,midy*4/5),PointF(midx,midy/5),PointF(FUpDownLeft+FUpDownWidth-3,midy*4/5)],btntext);
+  ABitmap.FillPolyAntialias([PointF(FUpDownLeft+2,midy*6/5),PointF(midx,ABitmap.Height-midy/5),PointF(FUpDownLeft+FUpDownWidth-3,midy*6/5)],btntext);
+end;
+
+function TCustomBCTrackbarUpdown.ValueToBarPos(AValue: integer): integer;
+var t: single;
+begin
+  if FMaxValue>FMinValue then
+  begin
+    t := (AValue-FMinValue)/(FMaxValue-FMinValue);
+    if t < 0 then t := 0;
+    if t > 1 then t := 1;
+    result := FBarLeft+round(power(t,1/FBarExponent)*(FBarWidth-1))
+  end
+  else
+    result := FBarLeft;
+end;
+
+function TCustomBCTrackbarUpdown.BarPosToValue(ABarPos: integer): integer;
+var t: single;
+begin
+  if FBarWidth > FBarLeft then
+  begin
+    t := (ABarPos-FBarLeft)/(FBarWidth-1);
+    if t < 0 then t := 0;
+    if t > 1 then t := 1;
+    result := round(power(t,FBarExponent)*(FMaxValue-FMinValue))+FMinValue
+  end
+  else
+    result := FMinValue;
+end;
+
+procedure TCustomBCTrackbarUpdown.MouseDown(Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+begin
+  if Button = mbLeft then
+  begin
+    FHandlingUserInput:= true;
+    if X >= FUpDownLeft then
+    begin
+      if Y > Height div 2 then
+      begin
+        FDownClick:= true;
+        Value := Value-Increment;
+        Invalidate;
+        FTimer.Interval := LongTimeInterval;
+        FTimer.Enabled:= true;
+      end else
+      if Y < Height div 2 then
+      begin
+        FUpClick:= true;
+        Value := Value+Increment;
+        Invalidate;
+        FTimer.Interval := LongTimeInterval;
+        FTimer.Enabled:= true;
+      end;
+    end else
+    if (Y >= Height-FBarHeight-1) and (FBarWidth>1) then
+    begin
+      FBarClick:= true;
+      Value := BarPosToValue(X);
+      Repaint;
+    end;
+    FHandlingUserInput:= false;
+  end;
+  if not Focused then
+  begin
+    SetFocus;
+    SelectAll;
+  end;
+end;
+
+procedure TCustomBCTrackbarUpdown.MouseMove(Shift: TShiftState; X, Y: Integer);
+begin
+  inherited MouseMove(Shift, X, Y);
+  if FBarClick and (FBarWidth>1) then
+  begin
+    FHandlingUserInput:= true;
+    Value := BarPosToValue(X);
+    FHandlingUserInput:= false;
+  end;
+end;
+
+procedure TCustomBCTrackbarUpdown.MouseUp(Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+begin
+  inherited MouseUp(Button, Shift, X, Y);
+  if Button = mbLeft then
+  begin
+    if FBarClick then FBarClick:= false else
+    if FUpClick then
+    begin
+      FUpClick:= false;
+      Invalidate;
+      FTimer.Enabled:= false;
+    end else
+    if FDownClick then
+    begin
+      FDownClick:= false;
+      Invalidate;
+      FTimer.Enabled:= false;
+    end;
+  end;
+end;
+
+procedure TCustomBCTrackbarUpdown.UTF8KeyPress(var UTF8Key: TUTF8Char);
+var tempText: string;
+begin
+  FHandlingUserInput:= true;
+  if UTF8Key = #8 then
+  begin
+    if not RemoveSelection and (SelStart > 0) then
+    begin
+      tempText := Text;
+      Dec(FSelStart);
+      Delete(tempText,SelStart+1,1);
+      Text := tempText;
+      Invalidate;
+    end;
+    UTF8Key:= #0;
+  end else
+  if (length(UTF8Key)=1) and (UTF8Key[1] in['0'..'9']) then
+  begin
+    RemoveSelection;
+    tempText := Text;
+    Insert(UTF8Key,tempText,SelStart+1);
+    Text := tempText;
+    if FSelStart < length(Text) then inc(FSelStart);
+    Invalidate;
+    UTF8Key:= #0;
+  end;
+  FHandlingUserInput:= false;
+end;
+
+procedure TCustomBCTrackbarUpdown.DoEnter;
+begin
+  inherited DoEnter;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.DoExit;
+begin
+  inherited DoExit;
+  FEmptyText:= false;
+  if FValue < FMinValue then FValue := FMinValue;
+  Invalidate;
+end;
+
+procedure TCustomBCTrackbarUpdown.DrawControl;
+var bmp: TBGRABitmap;
+begin
+  bmp := TBGRABitmap.Create(Width,Height);
+  RenderOnBitmap(bmp);
+  bmp.Draw(Canvas,0,0,False);
+  bmp.Free;
+end;
+
+constructor TCustomBCTrackbarUpdown.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FMinValue:= 0;
+  FMaxValue := 100;
+  FValue := 50;
+  FIncrement := 1;
+  FBarExponent:= 1;
+  FTimer := TTimer.Create(self);
+  FTimer.Enabled := false;
+  FTimer.OnTimer:=@Timer;
+  FLongTimeInterval:= 400;
+  FShortTimeInterval:= 100;
+  FBCBorder := TBCBorder.Create(self);
+  FBCBorder.Color := clWindowText;
+  FBCBorder.Width := 1;
+  FBCBorder.Style := bboSolid;
+  FBCBorder.OnChange := @OnChangeProperty;
+  FBCRounding := TBCRounding.Create(self);
+  FBCRounding.RoundX := 1;
+  FBCRounding.RoundY := 1;
+  FBCRounding.OnChange := @OnChangeProperty;
+  FBCBackground := TBCBackground.Create(self);
+  FBCBackground.Style := bbsColor;
+  FBCBackground.Color := clWindow;
+  FBCBackground.OnChange := @OnChangeProperty;
+  FBCButtonBackground := TBCBackground.Create(self);
+  FBCButtonBackground.Style := bbsGradient;
+  FBCButtonBackground.Gradient1EndPercent := 50;
+  FBCButtonBackground.Gradient1.Point1YPercent := -50;
+  FBCButtonBackground.Gradient1.Point2YPercent := 50;
+  FBCButtonBackground.Gradient1.StartColor := clBtnShadow;
+  FBCButtonBackground.Gradient1.EndColor := clBtnFace;
+  FBCButtonBackground.Gradient2.Point1YPercent := 50;
+  FBCButtonBackground.Gradient2.Point2YPercent := 150;
+  FBCButtonBackground.Gradient2.StartColor := clBtnFace;
+  FBCButtonBackground.Gradient2.EndColor := clBtnShadow;
+  FBCButtonBackground.OnChange := @OnChangeProperty;
+  FBCButtonDownBackground := TBCBackground.Create(self);
+  FBCButtonDownBackground.Style := bbsColor;
+  FBCButtonDownBackground.Color := clBtnShadow;
+  FBCButtonDownBackground.OnChange := @OnChangeProperty;
+  FArrowColor:= clBtnText;
+  Font.Color := clWindowText;
+  Font.Name := 'Arial';
+
+  DoSelectAll;
+  TabStop := true;
+end;
+
+procedure TCustomBCTrackbarUpdown.DoSelectAll;
+begin
+  FSelStart := 0;
+  FSelLength := length(Text);
+end;
+
+procedure TCustomBCTrackbarUpdown.SelectAll;
+begin
+  DoSelectAll;
+  Invalidate;
+end;
+
+function TCustomBCTrackbarUpdown.RemoveSelection: boolean;
+var
+  tempText: string;
+  len:integer;
+begin
+  if SelLength > 0 then
+  begin
+    tempText := Text;
+    len := FSelLength;
+    FSelLength := 0;
+    Delete(tempText,SelStart+1,len);
+    Text := tempText;
+    Invalidate;
+    result := true
+  end else
+    result := false;
+end;
+
+procedure TCustomBCTrackbarUpdown.DelayTimer;
+begin
+  if FTimer.Enabled then
+  begin
+    FTimer.Enabled:= false;
+    FTimer.Enabled:= true;
+  end;
+end;
+
+procedure TCustomBCTrackbarUpdown.SetFocus;
+begin
+  try
+    inherited SetFocus;
+  except
+    //in some cases, it is impossible to set the focus
+    //but that's not a reason to crash the program
+  end;
+end;
+
+destructor TCustomBCTrackbarUpdown.Destroy;
+begin
+  FreeAndNil(FTimer);
+  FreeAndNil(FBCBackground);
+  FreeAndNil(FBCButtonBackground);
+  FreeAndNil(FBCButtonDownBackground);
+  FreeAndNil(FBCBorder);
+  FreeAndNil(FBCRounding);
+  inherited Destroy;
+end;
+
+end.

+ 6 - 1
bgracontrols.lpk

@@ -27,7 +27,7 @@
       </Other>
     </CompilerOptions>
     <Version Major="3" Minor="5"/>
-    <Files Count="38">
+    <Files Count="39">
       <Item1>
         <Filename Value="bcbasectrls.pas"/>
         <UnitName Value="BCBaseCtrls"/>
@@ -208,6 +208,11 @@
         <HasRegisterProc Value="True"/>
         <UnitName Value="uPSI_BGRAPascalScript"/>
       </Item38>
+      <Item39>
+        <Filename Value="bctrackbarupdown.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="BCTrackbarUpdown"/>
+      </Item39>
     </Files>
     <Type Value="RunAndDesignTime"/>
     <RequiredPkgs Count="3">

+ 3 - 1
bgracontrols.pas

@@ -14,7 +14,8 @@ uses
   BGRAScript, BGRAShape, BGRASpeedButton, BGRASpriteAnimation, 
   BGRAVirtualScreen, DTAnalogClock, DTAnalogCommon, DTAnalogGauge, 
   dtthemedclock, dtthemedgauge, uEKnob, ueled, uEMultiTurn, uERotImage, 
-  uESelector, BGRAPascalScript, uPSI_BGRAPascalScript, LazarusPackageIntf;
+  uESelector, BGRAPascalScript, uPSI_BGRAPascalScript, BCTrackbarUpdown, 
+  LazarusPackageIntf;
 
 implementation
 
@@ -47,6 +48,7 @@ begin
   RegisterUnit('uERotImage', @uERotImage.Register);
   RegisterUnit('uESelector', @uESelector.Register);
   RegisterUnit('uPSI_BGRAPascalScript', @uPSI_BGRAPascalScript.Register);
+  RegisterUnit('BCTrackbarUpdown', @BCTrackbarUpdown.Register);
 end;
 
 initialization

+ 1 - 1
bgrashape.pas

@@ -61,7 +61,7 @@ type
     { Streaming }
     procedure SaveToFile(AFileName: string);
     procedure LoadFromFile(AFileName: string);
-    procedure OnFindClass(Reader: TReader; const AClassName: string;
+    procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
       var ComponentClass: TComponentClass);
   published
     { Published declarations }

+ 10 - 0
icons/bctrackbarupdown_icon.lrs

@@ -0,0 +1,10 @@
+LazarusResources.Add('tbctrackbarupdown','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#16#0#0#0#16#8#2#0#0#0#144#145'h6'#0
+  +#0#0#6'tRNS'#0#0#0#0#0#0'n'#166#7#145#0#0#0'rIDATx'#156'c`'#24#140#128#145'D'
+  +#196#192#248#31#7#0'Jm'#0#131#149'+WB'#24'('#26'n'#220#184#129#166#25#162'a'
+  +#225#194#133#186#186#186's'#231#206'E'#209'p'#253#250'u'#27#27#27'L'#13'k'
+  +#214#172'qrr'#2'2'#172#173#173'W'#175'^'#141#208#16#27#27#139#213#134'U'#171
+  +'V'#205#129#1' '#27#221#15#152#26#8'x'#154#10'6'#224#244#3#178#3#136#10'%'
+  +#210#226#129#212#152#166'1'#0#0'g'#237#250#30#214#138'3'#19#0#0#0#0'IEND'#174
+  +'B`'#130
+]);

+ 94 - 0
test/test_bccontrols/test_bctrackbarupdown/ptestupdown.lpi

@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="ptestupdown"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="bgracontrols"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="ptestupdown.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ptestupdown"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="unit1.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="Unit1"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="ptestupdown"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+    <Other>
+      <CompilerMessages>
+        <MsgFileName Value=""/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 21 - 0
test/test_bccontrols/test_bctrackbarupdown/ptestupdown.lpr

@@ -0,0 +1,21 @@
+program ptestupdown;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Interfaces, // this includes the LCL widgetset
+  Forms, Unit1
+  { you can add units after this };
+
+{$R *.res}
+
+begin
+  RequireDerivedFormResource := True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
+

+ 657 - 0
test/test_bccontrols/test_bctrackbarupdown/unit1.lfm

@@ -0,0 +1,657 @@
+object Form1: TForm1
+  Left = 326
+  Height = 240
+  Top = 38
+  Width = 320
+  Caption = 'Form1'
+  ClientHeight = 240
+  ClientWidth = 320
+  LCLVersion = '1.0.10.0'
+  object BCTrackbarUpdown1: TBCTrackbarUpdown
+    Left = 48
+    Height = 45
+    Top = 40
+    Width = 100
+    BarExponent = 1
+    Increment = 1
+    LongTimeInterval = 400
+    MinValue = 0
+    MaxValue = 100
+    Value = 50
+    ShortTimeInterval = 100
+    Background.Color = clWindow
+    Background.ColorOpacity = 255
+    Background.Gradient1.StartColor = clWhite
+    Background.Gradient1.StartColorOpacity = 255
+    Background.Gradient1.DrawMode = dmSet
+    Background.Gradient1.EndColor = clBlack
+    Background.Gradient1.EndColorOpacity = 255
+    Background.Gradient1.ColorCorrection = True
+    Background.Gradient1.GradientType = gtLinear
+    Background.Gradient1.Point1XPercent = 0
+    Background.Gradient1.Point1YPercent = 0
+    Background.Gradient1.Point2XPercent = 0
+    Background.Gradient1.Point2YPercent = 100
+    Background.Gradient1.Sinus = False
+    Background.Gradient2.StartColor = clWhite
+    Background.Gradient2.StartColorOpacity = 255
+    Background.Gradient2.DrawMode = dmSet
+    Background.Gradient2.EndColor = clBlack
+    Background.Gradient2.EndColorOpacity = 255
+    Background.Gradient2.ColorCorrection = True
+    Background.Gradient2.GradientType = gtLinear
+    Background.Gradient2.Point1XPercent = 0
+    Background.Gradient2.Point1YPercent = 0
+    Background.Gradient2.Point2XPercent = 0
+    Background.Gradient2.Point2YPercent = 100
+    Background.Gradient2.Sinus = False
+    Background.Gradient1EndPercent = 35
+    Background.Style = bbsColor
+    ButtonBackground.Color = clBlack
+    ButtonBackground.ColorOpacity = 255
+    ButtonBackground.Gradient1.StartColor = clBtnShadow
+    ButtonBackground.Gradient1.StartColorOpacity = 255
+    ButtonBackground.Gradient1.DrawMode = dmSet
+    ButtonBackground.Gradient1.EndColor = clBtnFace
+    ButtonBackground.Gradient1.EndColorOpacity = 255
+    ButtonBackground.Gradient1.ColorCorrection = True
+    ButtonBackground.Gradient1.GradientType = gtLinear
+    ButtonBackground.Gradient1.Point1XPercent = 0
+    ButtonBackground.Gradient1.Point1YPercent = -50
+    ButtonBackground.Gradient1.Point2XPercent = 0
+    ButtonBackground.Gradient1.Point2YPercent = 50
+    ButtonBackground.Gradient1.Sinus = False
+    ButtonBackground.Gradient2.StartColor = clBtnFace
+    ButtonBackground.Gradient2.StartColorOpacity = 255
+    ButtonBackground.Gradient2.DrawMode = dmSet
+    ButtonBackground.Gradient2.EndColor = clBtnShadow
+    ButtonBackground.Gradient2.EndColorOpacity = 255
+    ButtonBackground.Gradient2.ColorCorrection = True
+    ButtonBackground.Gradient2.GradientType = gtLinear
+    ButtonBackground.Gradient2.Point1XPercent = 0
+    ButtonBackground.Gradient2.Point1YPercent = 50
+    ButtonBackground.Gradient2.Point2XPercent = 0
+    ButtonBackground.Gradient2.Point2YPercent = 150
+    ButtonBackground.Gradient2.Sinus = False
+    ButtonBackground.Gradient1EndPercent = 50
+    ButtonBackground.Style = bbsGradient
+    ButtonDownBackground.Color = clBtnShadow
+    ButtonDownBackground.ColorOpacity = 255
+    ButtonDownBackground.Gradient1.StartColor = clWhite
+    ButtonDownBackground.Gradient1.StartColorOpacity = 255
+    ButtonDownBackground.Gradient1.DrawMode = dmSet
+    ButtonDownBackground.Gradient1.EndColor = clBlack
+    ButtonDownBackground.Gradient1.EndColorOpacity = 255
+    ButtonDownBackground.Gradient1.ColorCorrection = True
+    ButtonDownBackground.Gradient1.GradientType = gtLinear
+    ButtonDownBackground.Gradient1.Point1XPercent = 0
+    ButtonDownBackground.Gradient1.Point1YPercent = 0
+    ButtonDownBackground.Gradient1.Point2XPercent = 0
+    ButtonDownBackground.Gradient1.Point2YPercent = 100
+    ButtonDownBackground.Gradient1.Sinus = False
+    ButtonDownBackground.Gradient2.StartColor = clWhite
+    ButtonDownBackground.Gradient2.StartColorOpacity = 255
+    ButtonDownBackground.Gradient2.DrawMode = dmSet
+    ButtonDownBackground.Gradient2.EndColor = clBlack
+    ButtonDownBackground.Gradient2.EndColorOpacity = 255
+    ButtonDownBackground.Gradient2.ColorCorrection = True
+    ButtonDownBackground.Gradient2.GradientType = gtLinear
+    ButtonDownBackground.Gradient2.Point1XPercent = 0
+    ButtonDownBackground.Gradient2.Point1YPercent = 0
+    ButtonDownBackground.Gradient2.Point2XPercent = 0
+    ButtonDownBackground.Gradient2.Point2YPercent = 100
+    ButtonDownBackground.Gradient2.Sinus = False
+    ButtonDownBackground.Gradient1EndPercent = 35
+    ButtonDownBackground.Style = bbsColor
+    Border.Color = clWindowText
+    Border.ColorOpacity = 255
+    Border.LightColor = clWhite
+    Border.LightOpacity = 255
+    Border.LightWidth = 0
+    Border.Style = bboSolid
+    Border.Width = 2
+    Rounding.RoundX = 8
+    Rounding.RoundY = 8
+    Rounding.RoundOptions = []
+    Font.Color = clWindowText
+    Font.Name = 'Arial'
+    TabOrder = 0
+    TabStop = True
+    UseDockManager = False
+  end
+  object BCTrackbarUpdown2: TBCTrackbarUpdown
+    Left = 46
+    Height = 37
+    Top = 157
+    Width = 68
+    BarExponent = 1
+    Increment = 1
+    LongTimeInterval = 400
+    MinValue = 0
+    MaxValue = 9
+    Value = 9
+    ShortTimeInterval = 100
+    Background.Color = clWindow
+    Background.ColorOpacity = 255
+    Background.Gradient1.StartColor = clWhite
+    Background.Gradient1.StartColorOpacity = 255
+    Background.Gradient1.DrawMode = dmSet
+    Background.Gradient1.EndColor = clBlack
+    Background.Gradient1.EndColorOpacity = 255
+    Background.Gradient1.ColorCorrection = True
+    Background.Gradient1.GradientType = gtLinear
+    Background.Gradient1.Point1XPercent = 0
+    Background.Gradient1.Point1YPercent = 0
+    Background.Gradient1.Point2XPercent = 0
+    Background.Gradient1.Point2YPercent = 100
+    Background.Gradient1.Sinus = False
+    Background.Gradient2.StartColor = clWhite
+    Background.Gradient2.StartColorOpacity = 255
+    Background.Gradient2.DrawMode = dmSet
+    Background.Gradient2.EndColor = clBlack
+    Background.Gradient2.EndColorOpacity = 255
+    Background.Gradient2.ColorCorrection = True
+    Background.Gradient2.GradientType = gtLinear
+    Background.Gradient2.Point1XPercent = 0
+    Background.Gradient2.Point1YPercent = 0
+    Background.Gradient2.Point2XPercent = 0
+    Background.Gradient2.Point2YPercent = 100
+    Background.Gradient2.Sinus = False
+    Background.Gradient1EndPercent = 35
+    Background.Style = bbsColor
+    ButtonBackground.Color = clBlack
+    ButtonBackground.ColorOpacity = 255
+    ButtonBackground.Gradient1.StartColor = clBtnShadow
+    ButtonBackground.Gradient1.StartColorOpacity = 255
+    ButtonBackground.Gradient1.DrawMode = dmSet
+    ButtonBackground.Gradient1.EndColor = clBtnFace
+    ButtonBackground.Gradient1.EndColorOpacity = 255
+    ButtonBackground.Gradient1.ColorCorrection = True
+    ButtonBackground.Gradient1.GradientType = gtLinear
+    ButtonBackground.Gradient1.Point1XPercent = 0
+    ButtonBackground.Gradient1.Point1YPercent = -50
+    ButtonBackground.Gradient1.Point2XPercent = 0
+    ButtonBackground.Gradient1.Point2YPercent = 50
+    ButtonBackground.Gradient1.Sinus = False
+    ButtonBackground.Gradient2.StartColor = clBtnFace
+    ButtonBackground.Gradient2.StartColorOpacity = 255
+    ButtonBackground.Gradient2.DrawMode = dmSet
+    ButtonBackground.Gradient2.EndColor = clBtnShadow
+    ButtonBackground.Gradient2.EndColorOpacity = 255
+    ButtonBackground.Gradient2.ColorCorrection = True
+    ButtonBackground.Gradient2.GradientType = gtLinear
+    ButtonBackground.Gradient2.Point1XPercent = 0
+    ButtonBackground.Gradient2.Point1YPercent = 50
+    ButtonBackground.Gradient2.Point2XPercent = 0
+    ButtonBackground.Gradient2.Point2YPercent = 150
+    ButtonBackground.Gradient2.Sinus = False
+    ButtonBackground.Gradient1EndPercent = 50
+    ButtonBackground.Style = bbsGradient
+    ButtonDownBackground.Color = clBtnShadow
+    ButtonDownBackground.ColorOpacity = 255
+    ButtonDownBackground.Gradient1.StartColor = clWhite
+    ButtonDownBackground.Gradient1.StartColorOpacity = 255
+    ButtonDownBackground.Gradient1.DrawMode = dmSet
+    ButtonDownBackground.Gradient1.EndColor = clBlack
+    ButtonDownBackground.Gradient1.EndColorOpacity = 255
+    ButtonDownBackground.Gradient1.ColorCorrection = True
+    ButtonDownBackground.Gradient1.GradientType = gtLinear
+    ButtonDownBackground.Gradient1.Point1XPercent = 0
+    ButtonDownBackground.Gradient1.Point1YPercent = 0
+    ButtonDownBackground.Gradient1.Point2XPercent = 0
+    ButtonDownBackground.Gradient1.Point2YPercent = 100
+    ButtonDownBackground.Gradient1.Sinus = False
+    ButtonDownBackground.Gradient2.StartColor = clWhite
+    ButtonDownBackground.Gradient2.StartColorOpacity = 255
+    ButtonDownBackground.Gradient2.DrawMode = dmSet
+    ButtonDownBackground.Gradient2.EndColor = clBlack
+    ButtonDownBackground.Gradient2.EndColorOpacity = 255
+    ButtonDownBackground.Gradient2.ColorCorrection = True
+    ButtonDownBackground.Gradient2.GradientType = gtLinear
+    ButtonDownBackground.Gradient2.Point1XPercent = 0
+    ButtonDownBackground.Gradient2.Point1YPercent = 0
+    ButtonDownBackground.Gradient2.Point2XPercent = 0
+    ButtonDownBackground.Gradient2.Point2YPercent = 100
+    ButtonDownBackground.Gradient2.Sinus = False
+    ButtonDownBackground.Gradient1EndPercent = 35
+    ButtonDownBackground.Style = bbsColor
+    Border.Color = clWindowText
+    Border.ColorOpacity = 255
+    Border.LightColor = clWhite
+    Border.LightOpacity = 255
+    Border.LightWidth = 0
+    Border.Style = bboSolid
+    Border.Width = 1
+    Rounding.RoundX = 1
+    Rounding.RoundY = 1
+    Rounding.RoundOptions = []
+    Font.Color = clWindowText
+    Font.Name = 'Arial'
+    TabOrder = 1
+    TabStop = True
+    UseDockManager = False
+  end
+  object BCTrackbarUpdown3: TBCTrackbarUpdown
+    Left = 202
+    Height = 25
+    Top = 57
+    Width = 56
+    BarExponent = 1
+    Increment = 1
+    LongTimeInterval = 400
+    MinValue = 20
+    MaxValue = 100
+    OnChange = BCTrackbarUpdown3Change
+    Value = 50
+    ShortTimeInterval = 100
+    Background.Color = clWindow
+    Background.ColorOpacity = 255
+    Background.Gradient1.StartColor = clWhite
+    Background.Gradient1.StartColorOpacity = 255
+    Background.Gradient1.DrawMode = dmSet
+    Background.Gradient1.EndColor = clBlack
+    Background.Gradient1.EndColorOpacity = 255
+    Background.Gradient1.ColorCorrection = True
+    Background.Gradient1.GradientType = gtLinear
+    Background.Gradient1.Point1XPercent = 0
+    Background.Gradient1.Point1YPercent = 0
+    Background.Gradient1.Point2XPercent = 0
+    Background.Gradient1.Point2YPercent = 100
+    Background.Gradient1.Sinus = False
+    Background.Gradient2.StartColor = clWhite
+    Background.Gradient2.StartColorOpacity = 255
+    Background.Gradient2.DrawMode = dmSet
+    Background.Gradient2.EndColor = clBlack
+    Background.Gradient2.EndColorOpacity = 255
+    Background.Gradient2.ColorCorrection = True
+    Background.Gradient2.GradientType = gtLinear
+    Background.Gradient2.Point1XPercent = 0
+    Background.Gradient2.Point1YPercent = 0
+    Background.Gradient2.Point2XPercent = 0
+    Background.Gradient2.Point2YPercent = 100
+    Background.Gradient2.Sinus = False
+    Background.Gradient1EndPercent = 35
+    Background.Style = bbsColor
+    ButtonBackground.Color = clBlack
+    ButtonBackground.ColorOpacity = 255
+    ButtonBackground.Gradient1.StartColor = clBtnShadow
+    ButtonBackground.Gradient1.StartColorOpacity = 255
+    ButtonBackground.Gradient1.DrawMode = dmSet
+    ButtonBackground.Gradient1.EndColor = clBtnFace
+    ButtonBackground.Gradient1.EndColorOpacity = 255
+    ButtonBackground.Gradient1.ColorCorrection = True
+    ButtonBackground.Gradient1.GradientType = gtLinear
+    ButtonBackground.Gradient1.Point1XPercent = 0
+    ButtonBackground.Gradient1.Point1YPercent = -50
+    ButtonBackground.Gradient1.Point2XPercent = 0
+    ButtonBackground.Gradient1.Point2YPercent = 50
+    ButtonBackground.Gradient1.Sinus = False
+    ButtonBackground.Gradient2.StartColor = clBtnFace
+    ButtonBackground.Gradient2.StartColorOpacity = 255
+    ButtonBackground.Gradient2.DrawMode = dmSet
+    ButtonBackground.Gradient2.EndColor = clBtnShadow
+    ButtonBackground.Gradient2.EndColorOpacity = 255
+    ButtonBackground.Gradient2.ColorCorrection = True
+    ButtonBackground.Gradient2.GradientType = gtLinear
+    ButtonBackground.Gradient2.Point1XPercent = 0
+    ButtonBackground.Gradient2.Point1YPercent = 50
+    ButtonBackground.Gradient2.Point2XPercent = 0
+    ButtonBackground.Gradient2.Point2YPercent = 150
+    ButtonBackground.Gradient2.Sinus = False
+    ButtonBackground.Gradient1EndPercent = 50
+    ButtonBackground.Style = bbsGradient
+    ButtonDownBackground.Color = clBtnShadow
+    ButtonDownBackground.ColorOpacity = 255
+    ButtonDownBackground.Gradient1.StartColor = clWhite
+    ButtonDownBackground.Gradient1.StartColorOpacity = 255
+    ButtonDownBackground.Gradient1.DrawMode = dmSet
+    ButtonDownBackground.Gradient1.EndColor = clBlack
+    ButtonDownBackground.Gradient1.EndColorOpacity = 255
+    ButtonDownBackground.Gradient1.ColorCorrection = True
+    ButtonDownBackground.Gradient1.GradientType = gtLinear
+    ButtonDownBackground.Gradient1.Point1XPercent = 0
+    ButtonDownBackground.Gradient1.Point1YPercent = 0
+    ButtonDownBackground.Gradient1.Point2XPercent = 0
+    ButtonDownBackground.Gradient1.Point2YPercent = 100
+    ButtonDownBackground.Gradient1.Sinus = False
+    ButtonDownBackground.Gradient2.StartColor = clWhite
+    ButtonDownBackground.Gradient2.StartColorOpacity = 255
+    ButtonDownBackground.Gradient2.DrawMode = dmSet
+    ButtonDownBackground.Gradient2.EndColor = clBlack
+    ButtonDownBackground.Gradient2.EndColorOpacity = 255
+    ButtonDownBackground.Gradient2.ColorCorrection = True
+    ButtonDownBackground.Gradient2.GradientType = gtLinear
+    ButtonDownBackground.Gradient2.Point1XPercent = 0
+    ButtonDownBackground.Gradient2.Point1YPercent = 0
+    ButtonDownBackground.Gradient2.Point2XPercent = 0
+    ButtonDownBackground.Gradient2.Point2YPercent = 100
+    ButtonDownBackground.Gradient2.Sinus = False
+    ButtonDownBackground.Gradient1EndPercent = 35
+    ButtonDownBackground.Style = bbsColor
+    Border.Color = clWindowText
+    Border.ColorOpacity = 255
+    Border.LightColor = clWhite
+    Border.LightOpacity = 255
+    Border.LightWidth = 0
+    Border.Style = bboSolid
+    Border.Width = 1
+    Rounding.RoundX = 4
+    Rounding.RoundY = 4
+    Rounding.RoundOptions = []
+    Font.Color = clWindowText
+    Font.Name = 'Arial'
+    TabOrder = 2
+    TabStop = True
+    UseDockManager = False
+  end
+  object Label1: TLabel
+    Left = 192
+    Height = 16
+    Top = 94
+    Width = 35
+    Caption = 'Label1'
+    ParentColor = False
+  end
+  object BCButton1: TBCButton
+    Left = 132
+    Height = 33
+    Top = 158
+    Width = 123
+    StateClicked.Background.Color = clBlack
+    StateClicked.Background.ColorOpacity = 255
+    StateClicked.Background.Gradient1.StartColor = 8404992
+    StateClicked.Background.Gradient1.StartColorOpacity = 255
+    StateClicked.Background.Gradient1.DrawMode = dmSet
+    StateClicked.Background.Gradient1.EndColor = 4194304
+    StateClicked.Background.Gradient1.EndColorOpacity = 255
+    StateClicked.Background.Gradient1.ColorCorrection = True
+    StateClicked.Background.Gradient1.GradientType = gtRadial
+    StateClicked.Background.Gradient1.Point1XPercent = 50
+    StateClicked.Background.Gradient1.Point1YPercent = 100
+    StateClicked.Background.Gradient1.Point2XPercent = 0
+    StateClicked.Background.Gradient1.Point2YPercent = 0
+    StateClicked.Background.Gradient1.Sinus = False
+    StateClicked.Background.Gradient2.StartColor = clWhite
+    StateClicked.Background.Gradient2.StartColorOpacity = 255
+    StateClicked.Background.Gradient2.DrawMode = dmSet
+    StateClicked.Background.Gradient2.EndColor = clBlack
+    StateClicked.Background.Gradient2.EndColorOpacity = 255
+    StateClicked.Background.Gradient2.ColorCorrection = True
+    StateClicked.Background.Gradient2.GradientType = gtLinear
+    StateClicked.Background.Gradient2.Point1XPercent = 0
+    StateClicked.Background.Gradient2.Point1YPercent = 0
+    StateClicked.Background.Gradient2.Point2XPercent = 0
+    StateClicked.Background.Gradient2.Point2YPercent = 100
+    StateClicked.Background.Gradient2.Sinus = False
+    StateClicked.Background.Gradient1EndPercent = 100
+    StateClicked.Background.Style = bbsGradient
+    StateClicked.Border.Color = clBlack
+    StateClicked.Border.ColorOpacity = 255
+    StateClicked.Border.LightColor = clWhite
+    StateClicked.Border.LightOpacity = 255
+    StateClicked.Border.LightWidth = 0
+    StateClicked.Border.Style = bboNone
+    StateClicked.Border.Width = 1
+    StateClicked.FontEx.Color = 16770790
+    StateClicked.FontEx.EndEllipsis = False
+    StateClicked.FontEx.FontQuality = fqSystemClearType
+    StateClicked.FontEx.Height = 0
+    StateClicked.FontEx.SingleLine = True
+    StateClicked.FontEx.Shadow = True
+    StateClicked.FontEx.ShadowColor = clBlack
+    StateClicked.FontEx.ShadowColorOpacity = 255
+    StateClicked.FontEx.ShadowRadius = 2
+    StateClicked.FontEx.ShadowOffsetX = 1
+    StateClicked.FontEx.ShadowOffsetY = 1
+    StateClicked.FontEx.Style = [fsBold]
+    StateClicked.FontEx.TextAlignment = bcaCenter
+    StateClicked.FontEx.WordBreak = False
+    StateHover.Background.Color = clBlack
+    StateHover.Background.ColorOpacity = 255
+    StateHover.Background.Gradient1.StartColor = 16744448
+    StateHover.Background.Gradient1.StartColorOpacity = 255
+    StateHover.Background.Gradient1.DrawMode = dmSet
+    StateHover.Background.Gradient1.EndColor = 8404992
+    StateHover.Background.Gradient1.EndColorOpacity = 255
+    StateHover.Background.Gradient1.ColorCorrection = True
+    StateHover.Background.Gradient1.GradientType = gtRadial
+    StateHover.Background.Gradient1.Point1XPercent = 50
+    StateHover.Background.Gradient1.Point1YPercent = 100
+    StateHover.Background.Gradient1.Point2XPercent = 0
+    StateHover.Background.Gradient1.Point2YPercent = 0
+    StateHover.Background.Gradient1.Sinus = False
+    StateHover.Background.Gradient2.StartColor = clWhite
+    StateHover.Background.Gradient2.StartColorOpacity = 255
+    StateHover.Background.Gradient2.DrawMode = dmSet
+    StateHover.Background.Gradient2.EndColor = clBlack
+    StateHover.Background.Gradient2.EndColorOpacity = 255
+    StateHover.Background.Gradient2.ColorCorrection = True
+    StateHover.Background.Gradient2.GradientType = gtLinear
+    StateHover.Background.Gradient2.Point1XPercent = 0
+    StateHover.Background.Gradient2.Point1YPercent = 0
+    StateHover.Background.Gradient2.Point2XPercent = 0
+    StateHover.Background.Gradient2.Point2YPercent = 100
+    StateHover.Background.Gradient2.Sinus = False
+    StateHover.Background.Gradient1EndPercent = 100
+    StateHover.Background.Style = bbsGradient
+    StateHover.Border.Color = clBlack
+    StateHover.Border.ColorOpacity = 255
+    StateHover.Border.LightColor = clWhite
+    StateHover.Border.LightOpacity = 255
+    StateHover.Border.LightWidth = 0
+    StateHover.Border.Style = bboNone
+    StateHover.Border.Width = 1
+    StateHover.FontEx.Color = clWhite
+    StateHover.FontEx.EndEllipsis = False
+    StateHover.FontEx.FontQuality = fqSystemClearType
+    StateHover.FontEx.Height = 0
+    StateHover.FontEx.SingleLine = True
+    StateHover.FontEx.Shadow = True
+    StateHover.FontEx.ShadowColor = clBlack
+    StateHover.FontEx.ShadowColorOpacity = 255
+    StateHover.FontEx.ShadowRadius = 2
+    StateHover.FontEx.ShadowOffsetX = 1
+    StateHover.FontEx.ShadowOffsetY = 1
+    StateHover.FontEx.Style = [fsBold]
+    StateHover.FontEx.TextAlignment = bcaCenter
+    StateHover.FontEx.WordBreak = False
+    StateNormal.Background.Color = clBlack
+    StateNormal.Background.ColorOpacity = 255
+    StateNormal.Background.Gradient1.StartColor = 4194304
+    StateNormal.Background.Gradient1.StartColorOpacity = 255
+    StateNormal.Background.Gradient1.DrawMode = dmSet
+    StateNormal.Background.Gradient1.EndColor = 8405056
+    StateNormal.Background.Gradient1.EndColorOpacity = 255
+    StateNormal.Background.Gradient1.ColorCorrection = True
+    StateNormal.Background.Gradient1.GradientType = gtLinear
+    StateNormal.Background.Gradient1.Point1XPercent = 0
+    StateNormal.Background.Gradient1.Point1YPercent = 0
+    StateNormal.Background.Gradient1.Point2XPercent = 0
+    StateNormal.Background.Gradient1.Point2YPercent = 100
+    StateNormal.Background.Gradient1.Sinus = False
+    StateNormal.Background.Gradient2.StartColor = 8405056
+    StateNormal.Background.Gradient2.StartColorOpacity = 255
+    StateNormal.Background.Gradient2.DrawMode = dmSet
+    StateNormal.Background.Gradient2.EndColor = 4194304
+    StateNormal.Background.Gradient2.EndColorOpacity = 255
+    StateNormal.Background.Gradient2.ColorCorrection = True
+    StateNormal.Background.Gradient2.GradientType = gtRadial
+    StateNormal.Background.Gradient2.Point1XPercent = 50
+    StateNormal.Background.Gradient2.Point1YPercent = 100
+    StateNormal.Background.Gradient2.Point2XPercent = 0
+    StateNormal.Background.Gradient2.Point2YPercent = 0
+    StateNormal.Background.Gradient2.Sinus = False
+    StateNormal.Background.Gradient1EndPercent = 60
+    StateNormal.Background.Style = bbsGradient
+    StateNormal.Border.Color = clYellow
+    StateNormal.Border.ColorOpacity = 255
+    StateNormal.Border.LightColor = clWhite
+    StateNormal.Border.LightOpacity = 80
+    StateNormal.Border.LightWidth = 0
+    StateNormal.Border.Style = bboSolid
+    StateNormal.Border.Width = 1
+    StateNormal.FontEx.Color = 16770790
+    StateNormal.FontEx.EndEllipsis = False
+    StateNormal.FontEx.FontQuality = fqSystemClearType
+    StateNormal.FontEx.Height = 0
+    StateNormal.FontEx.SingleLine = True
+    StateNormal.FontEx.Shadow = True
+    StateNormal.FontEx.ShadowColor = clBlack
+    StateNormal.FontEx.ShadowColorOpacity = 255
+    StateNormal.FontEx.ShadowRadius = 2
+    StateNormal.FontEx.ShadowOffsetX = 1
+    StateNormal.FontEx.ShadowOffsetY = 1
+    StateNormal.FontEx.Style = [fsBold]
+    StateNormal.FontEx.TextAlignment = bcaCenter
+    StateNormal.FontEx.WordBreak = False
+    Caption = 'BCButton1'
+    Color = clNone
+    DropDownWidth = 16
+    DropDownArrowSize = 8
+    GlobalOpacity = 255
+    ParentColor = False
+    Rounding.RoundX = 8
+    Rounding.RoundY = 8
+    Rounding.RoundOptions = [rrTopRightSquare, rrBottomRightSquare, rrBottomLeftBevel]
+    RoundingDropDown.RoundX = 8
+    RoundingDropDown.RoundY = 8
+    RoundingDropDown.RoundOptions = [rrTopLeftSquare, rrBottomLeftSquare, rrTopRightBevel]
+    Style = bbtDropDown
+    TextApplyGlobalOpacity = False
+    DropDownArrow = True
+    MemoryUsage = bmuHigh
+  end
+  object CheckBox1: TCheckBox
+    Left = 56
+    Height = 19
+    Top = 8
+    Width = 62
+    Caption = 'Enabled'
+    Checked = True
+    OnChange = CheckBox1Change
+    State = cbChecked
+    TabOrder = 3
+  end
+  object BCLabel1: TBCLabel
+    Left = 45
+    Height = 17
+    Top = 112
+    Width = 51
+    Background.Color = clBlack
+    Background.ColorOpacity = 255
+    Background.Gradient1.StartColor = clWhite
+    Background.Gradient1.StartColorOpacity = 255
+    Background.Gradient1.DrawMode = dmSet
+    Background.Gradient1.EndColor = clBlack
+    Background.Gradient1.EndColorOpacity = 255
+    Background.Gradient1.ColorCorrection = True
+    Background.Gradient1.GradientType = gtLinear
+    Background.Gradient1.Point1XPercent = 0
+    Background.Gradient1.Point1YPercent = 0
+    Background.Gradient1.Point2XPercent = 0
+    Background.Gradient1.Point2YPercent = 100
+    Background.Gradient1.Sinus = False
+    Background.Gradient2.StartColor = clWhite
+    Background.Gradient2.StartColorOpacity = 255
+    Background.Gradient2.DrawMode = dmSet
+    Background.Gradient2.EndColor = clBlack
+    Background.Gradient2.EndColorOpacity = 255
+    Background.Gradient2.ColorCorrection = True
+    Background.Gradient2.GradientType = gtLinear
+    Background.Gradient2.Point1XPercent = 0
+    Background.Gradient2.Point1YPercent = 0
+    Background.Gradient2.Point2XPercent = 0
+    Background.Gradient2.Point2YPercent = 100
+    Background.Gradient2.Sinus = False
+    Background.Gradient1EndPercent = 35
+    Background.Style = bbsClear
+    Border.Color = clBlack
+    Border.ColorOpacity = 255
+    Border.LightColor = clWhite
+    Border.LightOpacity = 255
+    Border.LightWidth = 0
+    Border.Style = bboSolid
+    Border.Width = 1
+    Caption = 'BCLabel1'
+    FontEx.Color = clDefault
+    FontEx.EndEllipsis = False
+    FontEx.FontQuality = fqSystemClearType
+    FontEx.Height = 0
+    FontEx.SingleLine = True
+    FontEx.Shadow = False
+    FontEx.ShadowColor = clBlack
+    FontEx.ShadowColorOpacity = 255
+    FontEx.ShadowRadius = 5
+    FontEx.ShadowOffsetX = 5
+    FontEx.ShadowOffsetY = 5
+    FontEx.Style = []
+    FontEx.TextAlignment = bcaCenter
+    FontEx.WordBreak = False
+    Rounding.RoundX = 4
+    Rounding.RoundY = 4
+    Rounding.RoundOptions = []
+  end
+  object BCPanel1: TBCPanel
+    Left = 248
+    Height = 48
+    Top = 111
+    Width = 64
+    Background.Color = clHotLight
+    Background.ColorOpacity = 255
+    Background.Gradient1.StartColor = clWhite
+    Background.Gradient1.StartColorOpacity = 255
+    Background.Gradient1.DrawMode = dmSet
+    Background.Gradient1.EndColor = clBlack
+    Background.Gradient1.EndColorOpacity = 255
+    Background.Gradient1.ColorCorrection = True
+    Background.Gradient1.GradientType = gtLinear
+    Background.Gradient1.Point1XPercent = 0
+    Background.Gradient1.Point1YPercent = 0
+    Background.Gradient1.Point2XPercent = 0
+    Background.Gradient1.Point2YPercent = 100
+    Background.Gradient1.Sinus = False
+    Background.Gradient2.StartColor = clWhite
+    Background.Gradient2.StartColorOpacity = 255
+    Background.Gradient2.DrawMode = dmSet
+    Background.Gradient2.EndColor = clBlack
+    Background.Gradient2.EndColorOpacity = 255
+    Background.Gradient2.ColorCorrection = True
+    Background.Gradient2.GradientType = gtLinear
+    Background.Gradient2.Point1XPercent = 0
+    Background.Gradient2.Point1YPercent = 0
+    Background.Gradient2.Point2XPercent = 0
+    Background.Gradient2.Point2YPercent = 100
+    Background.Gradient2.Sinus = False
+    Background.Gradient1EndPercent = 35
+    Background.Style = bbsColor
+    BevelInner = bvLowered
+    BevelOuter = bvRaised
+    BevelWidth = 2
+    Border.Color = clBlack
+    Border.ColorOpacity = 255
+    Border.LightColor = clWhite
+    Border.LightOpacity = 255
+    Border.LightWidth = 0
+    Border.Style = bboSolid
+    Border.Width = 1
+    Caption = 'BCPanel1'
+    FontEx.Color = clDefault
+    FontEx.EndEllipsis = False
+    FontEx.FontQuality = fqSystemClearType
+    FontEx.Height = 0
+    FontEx.SingleLine = True
+    FontEx.Shadow = False
+    FontEx.ShadowColor = clBlack
+    FontEx.ShadowColorOpacity = 255
+    FontEx.ShadowRadius = 5
+    FontEx.ShadowOffsetX = 5
+    FontEx.ShadowOffsetY = 5
+    FontEx.Style = []
+    FontEx.TextAlignment = bcaCenter
+    FontEx.WordBreak = False
+    Rounding.RoundX = 10
+    Rounding.RoundY = 10
+    Rounding.RoundOptions = []
+    TabOrder = 4
+  end
+end

+ 54 - 0
test/test_bccontrols/test_bctrackbarupdown/unit1.pas

@@ -0,0 +1,54 @@
+unit Unit1;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  BCTrackbarUpdown, BCButton, BCLabel, BCPanel;
+
+type
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    BCButton1: TBCButton;
+    BCLabel1: TBCLabel;
+    BCPanel1: TBCPanel;
+    BCTrackbarUpdown1: TBCTrackbarUpdown;
+    BCTrackbarUpdown2: TBCTrackbarUpdown;
+    BCTrackbarUpdown3: TBCTrackbarUpdown;
+    CheckBox1: TCheckBox;
+    Label1: TLabel;
+    procedure BCTrackbarUpdown3Change(Sender: TObject; AByUser: boolean);
+    procedure CheckBox1Change(Sender: TObject);
+  private
+    { private declarations }
+  public
+    { public declarations }
+    changeCount: integer;
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.BCTrackbarUpdown3Change(Sender: TObject; AByUser: boolean);
+begin
+  inc(changeCount);
+  label1.Caption := '#'+inttostr(changeCount)+': '+inttostr(TBCTrackbarUpdown(Sender).Value);
+end;
+
+procedure TForm1.CheckBox1Change(Sender: TObject);
+begin
+  BCTrackbarUpdown1.Enabled := CheckBox1.Checked;
+end;
+
+end.
+