fcshapebtn.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:23k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit fcShapeBtn;
  2. {
  3. //
  4. // Components : TfcShapeBtn
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. // Revision: History
  8. // 5/10/99 - PYW - Fixed Flat Style painting bug in High Color mode.
  9. // 5/24/2000-PYW-Add check to not paint in 3D if control is disabled.
  10. //
  11. }
  12. interface
  13. {$i fcIfDef.pas}
  14. uses Windows, Messages, Classes, Controls, Forms, Graphics, StdCtrls,
  15.   CommCtrl, Buttons, Dialogs, Math, Consts, SysUtils, fcCommon, fcText,
  16.   {$ifdef fcDelphi7Up}
  17.   themes,
  18.   {$endif}
  19.   {$ifdef ThemeManager}
  20.   thememgr, themesrv, uxtheme,
  21.   {$endif}
  22.   fcButton, fcImgBtn, fcEvaluator, fcBitmap
  23.   {$ifdef fcDelphi4up}
  24.   ,ImgList, ActnList
  25.   {$endif};
  26. const DEFUNUSECOLOR = clRed;
  27.       DEFUNUSECOLOR2 = clBlue;
  28. type
  29.   TfcShapeOrientation = (soLeft, soRight, soUp, soDown);
  30. {  1/9/2000 - Already in fccommon.pas
  31.   PfcPolyGonPoints = ^TFCPolyGonPoints;
  32.   TfcPolyGonPoints = array[0..0] of TPoint;
  33. }
  34.   TfcButtonShape = (bsRoundRect, bsEllipse, bsTriangle, bsArrow, bsDiamond,
  35.     bsRect, bsStar, bsTrapezoid, bsCustom);
  36.   TwwComputeCanvasAttributes = Procedure(
  37.      Sender: TObject; ACanvas: TCanvas) of object;
  38.   TfcCustomShapeBtn = class(TfcCustomImageBtn)
  39.   private
  40.     // Property Storage Variables
  41.     FPointList: TStringList;
  42.     FShape: TfcButtonShape;
  43.     FOrientation: TfcShapeOrientation;
  44.     FRoundRectBias: Integer;
  45.     FRegionBitmap: TBitmap;
  46.     FOnComputeCanvasAttributes: TwwComputeCanvasAttributes;
  47.     // Propety Access Methods
  48.     procedure SetShape(Value: TfcButtonShape);
  49.     procedure SetOrientation(Value: TfcShapeOrientation);
  50.     procedure SetPointList(Value: TStringList);
  51.     procedure SetRoundRectBias(Value: Integer);
  52.     function CorrectedColor: TColor;
  53.   protected
  54.     procedure DoComputeCanvasAttributes(ACanvas: TCanvas); virtual;
  55.     procedure WndProc(var Message: TMessage); override;
  56.     function StoreRegionData: Boolean; override;
  57.     function UnusableColor: TColor;
  58.     procedure AssignTo(Dest: TPersistent); override;
  59.     procedure Draw3dLines(Bitmap: TfcBitmap; PointList: array of TPoint;
  60.       NumPoints: Integer; TransColor: TColor);
  61.     procedure SetPointToOrientation(Points: PFCPolygonPoints;
  62.       NumPoints: Integer; Orientation: TfcShapeOrientation; Size: TSize);
  63.     function GetCustomPoints(var Points: PFCPolygonPoints; Size: TSize): Integer;
  64.     function GetStarPoints(var Points: PFCPolygonPoints; Size: TSize): Integer;
  65.     function GetPolygonPoints(var Points: PFCPolyGonPoints): Integer;
  66.     // Overriden Methods
  67.     function CreateRegion(DoImplementation: Boolean; Down: Boolean): HRgn; override;
  68.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  69.       X, Y: Integer); override;
  70.     function UseRegions: boolean; override;
  71.     property RegionBitmap: TBitmap read FRegionBitmap write FRegionBitmap;
  72.   public
  73.     Patch: Variant;
  74.     constructor Create(AOwner: TComponent); override;
  75.     destructor Destroy; override;
  76.     function IsMultipleRegions: Boolean; override;
  77.     function RoundShape: Boolean; virtual;
  78.     procedure GetDrawBitmap(DrawBitmap: TfcBitmap; ForRegion: Boolean;
  79.       ShadeStyle: TfcShadeStyle; Down: Boolean); override;
  80.     procedure SizeToDefault; override;
  81.     property Orientation: TfcShapeOrientation read FOrientation write SetOrientation default soUp;
  82.     property PointList: TStringList read FPointList write SetPointList;
  83.     property RoundRectBias: Integer read FRoundRectBias write SetRoundRectBias default 0;
  84.     property Shape: TfcButtonShape read FShape write SetShape default bsRect;
  85.     property OnComputeCanvasAttributes: TwwComputeCanvasAttributes read
  86.        FOnComputeCanvasAttributes write FOnComputeCanvasAttributes;
  87.   end;
  88.   TfcShapeBtn = class(TfcCustomShapeBtn)
  89.   published
  90.     {$ifdef fcDelphi4Up}
  91.     property Action;
  92.     property Anchors;
  93.     property Constraints;
  94.     {$endif}
  95.     property StaticCaption;
  96.     property AllowAllUp;
  97.     property Cancel;
  98.     property Caption;
  99.     property Color;
  100.     property Default;
  101.     property DitherColor;
  102.     property Down;
  103.     property DragCursor; //3/31/99 - PYW - Exposed DragCursor, DragMode, DragKind properties.
  104.     property DataSource;
  105.     property DataField;
  106.     {$ifdef fcDelphi4Up}
  107.     property DragKind;
  108.     {$endif}
  109.     property DragMode;
  110.     property Font;
  111.     property Enabled;
  112.     property Glyph;
  113.     property GroupIndex;
  114.     property Kind;
  115.     property Layout;
  116.     property Margin;
  117.     property ModalResult;
  118.     property NumGlyphs;
  119.     property Options;
  120.     property Offsets;
  121.     property Orientation;
  122.     property ParentClipping;
  123.     property ParentFont;
  124.     property ParentShowHint;
  125.     property PointList;
  126.     property PopupMenu;
  127.     property RoundRectBias;
  128.     property ShadeColors;
  129.     property ShadeStyle;
  130.     property Shape;
  131.     property ShowHint;
  132.     {$ifdef fcDelphi4Up}
  133.     property SmoothFont;
  134.     {$endif}
  135.     property Spacing;
  136.     property Style;
  137.     property TabOrder;
  138.     property TabStop;
  139.     property TextOptions;
  140.     property Visible;
  141.     property OnClick;
  142.     property OnDragDrop;
  143.     property OnDragOver;
  144.     property OnEndDrag;
  145.     property OnEnter;
  146.     property OnExit;
  147.     property OnKeyDown;
  148.     property OnKeyPress;
  149.     property OnKeyUp;
  150.     property OnMouseDown;
  151.     property OnMouseEnter;
  152.     property OnMouseLeave;
  153.     property OnMouseMove;
  154.     property OnMouseUp;
  155.     property OnSelChange;
  156.     property OnStartDrag;
  157.     property OnComputeCanvasAttributes;
  158.     property DisableThemes;
  159.   end;
  160. implementation
  161. var GoodVideoDriverVar: Integer = -1;
  162. function GoodVideoDriver: Boolean;
  163. var TmpBm: TfcBitmap;
  164.     TmpBitmap: TBitmap;
  165. begin
  166.   if GoodVideoDriverVar = -1 then
  167.   begin
  168.     TmpBm := TfcBitmap.Create;
  169.     TmpBm.LoadBlank(1, 1);
  170.     TmpBm.Pixels[0, 0] := fcGetColor(RGB(192, 192, 192));
  171.     TmpBitmap := TBitmap.Create;
  172.     TmpBitmap.Width := 1;
  173.     TmpBitmap.Height := 1;
  174.     TmpBitmap.Canvas.Draw(0, 0, TmpBm);
  175.     with fcGetColor(TmpBitmap.Canvas.Pixels[0, 0]) do
  176.       GoodVideoDriverVar := ord((r < 200) and (g < 200) and (b < 200));
  177.     TmpBitmap.Free;
  178.     TmpBm.Free;
  179.   end;
  180.   result := GoodVideoDriverVar = 1;
  181. end;
  182. {$R-}
  183. procedure TfcCustomShapeBtn.MouseUp(Button: TMouseButton; Shift: TShiftState;
  184.   X, Y: Integer);
  185. begin
  186.   inherited MouseUp(Button, Shift, X, Y);
  187.   exit;
  188.   if (Button = mbLeft) and Enabled then
  189.   begin
  190.     if not Down then
  191.     begin
  192.       Down:=False;
  193.       Invalidate;
  194.     end;
  195.   end;
  196. end;
  197. constructor TfcCustomShapeBtn.Create(AOwner: TComponent);
  198. begin
  199.   inherited Create(AOwner);
  200.   UseHalftonePalette:= False;
  201.   FPointList := TStringList.Create;
  202.   FShape := bsRect;
  203.   FOrientation := soUp;
  204.   FRoundRectBias := 25;
  205.   FRegionBitmap := TBitmap.Create;
  206.   Color := clBtnFace;
  207.   ShadeStyle := fbsHighlight;
  208. end;
  209. destructor TfcCustomShapeBtn.Destroy;
  210. begin
  211.   FPointList.Free;
  212.   FRegionBitmap.Free;
  213.   inherited;
  214. end;
  215. procedure TfcCustomShapeBtn.SetOrientation(Value: TfcShapeOrientation);
  216. begin
  217.   if FOrientation<> Value then
  218.   begin
  219.     FOrientation:= Value;
  220.     Recreatewnd;
  221.   end
  222. end;
  223. procedure TfcCustomShapeBtn.SetPointList(Value: TStringList);
  224. begin
  225.   FPointList.Assign(Value);
  226.   RecreateWnd;
  227. end;
  228. procedure TfcCustomShapeBtn.SetShape(Value: TfcButtonShape);
  229. begin
  230.   if FShape <> Value then
  231.   begin
  232.     FShape := Value;
  233.     Recreatewnd;
  234.     // Ensures that the control's rectangle gets invalidated even in a transparent button group
  235.     if (Parent <> nil) and fcIsClass(Parent.ClassType, 'TfcCustomButtonGroup') then
  236.       fcParentInvalidate(Parent, True);
  237.   end
  238. end;
  239. // Given a set of points will rotate the points to the given orientation.
  240. // Method assumes points passed in are oriented up
  241. procedure TfcCustomShapeBtn.SetPointToOrientation(Points: PFCPolygonPoints;
  242.   NumPoints: Integer; Orientation: TfcShapeOrientation; Size: TSize);
  243. var i: Integer;
  244.     RepeatInc, RepCount: Integer;
  245. begin
  246.   RepCount := 0;
  247.   case Orientation of
  248.     soLeft: RepCount := 3;
  249.     soRight: RepCount := 1;
  250.     soUp: RepCount := 0;
  251.     soDown: RepCount := 2;
  252.   end;
  253.   for RepeatInc := 1 to RepCount do
  254.     for i := 0 to NumPoints - 1 do with Points[i] do
  255.       Points[i] := Point(Size.cx - (y * Size.cx div Size.cy), (x * Size.cy div Size.cx));
  256. end;
  257. procedure SetupPointList(var PointList: PfcPolygonPoints; NumPoints: Integer);
  258. begin
  259.   PointList := AllocMem((NumPoints + 1) * SizeOf(TPoint));
  260.   FillChar(PointList^, (NumPoints + 1) * SizeOf(TPoint), 0);
  261. end;
  262. function GetNum(Num: Integer): Integer;
  263. begin
  264.   result := Num;
  265. end;
  266. function TfcCustomShapeBtn.GetCustomPoints(var Points: PFCPolygonPoints; Size: TSize): Integer;
  267. var i: Integer;
  268.     CurPoint, x, y: string;
  269. begin
  270.   result := PointList.Count;
  271.   if result <= 2 then
  272.   begin
  273.     result := 0;
  274.     Exit;
  275.   end;
  276.   SetupPointList(Points, result);
  277.   try
  278.     for i := 0 to result - 1 do
  279.     begin
  280.       CurPoint := UpperCase(PointList[i]);
  281.       if Pos(',', CurPoint) = 0 then
  282.         raise EInvalidOperation.Create('Invalid Custom Points Format.  X and Y ' +
  283.           'Coordinates must be separated by a comma and space.');
  284.       CurPoint := fcReplace(CurPoint, ',', ', ');
  285.       CurPoint := fcReplace(CurPoint, ',  ', ', ');
  286.       CurPoint := fcReplace(CurPoint, 'WIDTH', InttoStr(Size.cx));
  287.       CurPoint := fcReplace(CurPoint, 'HEIGHT', InttoStr(Size.cy));
  288.       x := fcGetToken(CurPoint, ', ', 0);
  289.       y := fcGetToken(CurPoint, ', ', 1);
  290.       with Point(TfcEvaluator.Evaluate(x), TfcEvaluator.Evaluate(y)) do
  291.         Points[i] := Point(x, y);
  292.     end;
  293.   except
  294.     FreeMem(Points);
  295.     Points := nil;
  296.     FShape := bsRect;
  297.     raise;
  298.   end;
  299. end;
  300. function TfcCustomShapeBtn.GetStarPoints(var Points: PFCPolygonPoints; Size: TSize): Integer;
  301. var BottomOff: Integer;
  302.     BaseTri, SideTri, HeightTri: Integer;
  303.     Side: Integer;
  304. begin
  305.   result := 10;
  306.   SetupPointList(Points, result);
  307.   Side := Trunc(Size.cy / Cos(DegToRad(18)));
  308.   SideTri := Trunc(Side / (2 + 2 * Sin(DegToRad(18))));
  309.   BaseTri := Side - 2 * SideTri;
  310.   HeightTri := Trunc(SideTri * Cos(DegToRad(18)));
  311.   BottomOff := Trunc(Tan(DegToRad(18)) * Size.cy);
  312.   Points[GetNum(0)] := Point(Size.cx div 2, 0);
  313.   Points[GetNum(1)] := Point(Size.cx div 2 + BaseTri div 2, HeightTri);
  314.   Points[GetNum(2)] := Point(Size.cx, Points[GetNum(1)].y);
  315.   Points[GetNum(3)] := Point(Points[GetNum(1)].x + Trunc(Sin(DegToRad(18)) * BaseTri),
  316.                      Points[GetNum(1)].y + Trunc(Cos(DegToRad(18)) * BaseTri));
  317.   Points[GetNum(4)] := Point(Size.cx div 2 + BottomOff, Size.cy);
  318.   Points[GetNum(5)] := Point(Size.cx div 2, Size.cy - Trunc(Sin(DegToRad(36)) * SideTri));
  319.   Points[GetNum(6)] := Point(Size.cx div 2 - BottomOff, Size.cy);
  320.   Points[GetNum(7)] := Point(Size.cx - Points[GetNum(3)].x, Points[GetNum(3)].y);
  321.   Points[GetNum(8)] := Point(0, Points[GetNum(2)].y);
  322.   Points[GetNum(9)] := Point(Size.cx - Points[GetNum(1)].x, Points[GetNum(1)].y);
  323. end;
  324. function TfcCustomShapeBtn.GetPolygonPoints(var Points: PfcPolygonPoints): Integer;
  325. var Size: TSize;
  326. begin
  327.   result := 0;
  328.   Size := fcSize(Width - 1, Height - 1);
  329.   case Shape of
  330.     bsTriangle: begin
  331.       result := 3;
  332.       SetupPointList(Points, result);
  333.       // Default Up, SetPointToOrientation adjusts for orientation
  334.       Points[GetNum(0)] := Point(Size.cx div 2, 0);
  335.       Points[GetNum(1)] := Point(Size.cx, Size.cy);
  336.       Points[GetNum(2)] := Point(0, Size.cy);
  337.     end;
  338.     bsTrapezoid: begin
  339.       result := 4;
  340.       SetupPointList(Points, result);
  341.       // Default Up, SetPointToOrientation adjusts for orientation
  342.       Points[GetNum(0)] := Point(fcMin(Size.cy div 2, Size.cx div 2 div 2), 0);
  343.       Points[GetNum(1)] := Point(Size.cx - fcMin(Size.cy div 2, Size.cx div 2 div 2), 0);
  344.       Points[GetNum(2)] := Point(Size.cx, Size.cy);
  345.       Points[GetNum(3)] := Point(0, Size.cy);
  346.     end;
  347.     bsArrow: begin
  348.       result := 7;
  349.       SetupPointList(Points, result);
  350.       // Default Up, SetPointToOrientation adjusts for orientation
  351.       Points[GetNum(0)] := Point(0, Size.cy div 3);
  352.       Points[GetNum(1)] := Point(Size.cx div 2, 0);
  353.       Points[GetNum(2)] := Point(Size.cx, Size.cy div 3);
  354.       Points[GetNum(3)] := Point(Size.cx - Size.cx div 4, Size.cy div 3);
  355.       Points[GetNum(4)] := Point(Size.cx - Size.cx div 4, Size.cy);
  356.       Points[GetNum(5)] := Point(Size.cx div 4, Size.cy);
  357.       Points[GetNum(6)] := Point(Size.cx div 4, Size.cy div 3);
  358.     end;
  359.     bsDiamond: begin
  360.       result := 4;
  361.       SetupPointList(Points, result);
  362.       Points[GetNum(0)] := Point(Size.cx div 2, 0);
  363.       Points[GetNum(1)] := Point(Size.cx, Size.cy div 2);
  364.       Points[GetNum(2)] := Point(Size.cx div 2, Size.cy);
  365.       Points[GetNum(3)] := Point(0, Size.cy div 2);
  366.     end;
  367.     bsRect: begin
  368.       result := 4;
  369.       SetupPointList(Points, result);
  370.       Points[GetNum(0)] := Point(0, 0);
  371.       Points[GetNum(1)] := Point(Size.cx, 0);
  372.       Points[GetNum(2)] := Point(Size.cx, Size.cy);
  373.       Points[GetNum(3)] := Point(0, Size.cy);
  374.     end;
  375.     bsStar: result := GetStarPoints(Points, Size);
  376.     bsCustom: result := GetCustomPoints(Points, Size);
  377.   end;
  378.   if result > 0 then
  379.   begin
  380.     Points[result] := Points[0];
  381.     inc(result);
  382.     SetPointToOrientation(Points, result, Orientation, Size);
  383.   end;
  384. end;
  385. function TfcCustomShapeBtn.CreateRegion(DoImplementation: Boolean; Down: Boolean): HRgn;
  386. var DrawBitmap: TfcBitmap;
  387. begin
  388.   result := inherited CreateRegion(False, Down);
  389.   if not DoImplementation or (result <> 0) then Exit;
  390.   if (bsRect = Shape) and (parent<>nil) and
  391.      fcIsClass(parent.classtype, 'TCustomGrid') then exit; // No shape region needed
  392.   DrawBitmap := TfcBitmap.Create;
  393.   try
  394.     GetDrawBitmap(DrawBitmap, True, ShadeStyle, Down);
  395.     result := fcRegionFromBitmap(DrawBitmap, UnusableColor);
  396.   finally
  397.     SaveRegion(result, Down);
  398.     DrawBitmap.Free;
  399.   end;
  400. end;
  401. function TfcCustomShapeBtn.IsMultipleRegions: Boolean;
  402. begin
  403.   result := False;
  404. end;
  405. function TfcCustomShapeBtn.StoreRegionData: Boolean;
  406. begin
  407.   result := False;
  408. end;
  409. function TfcCustomShapeBtn.CorrectedColor: TColor;
  410. begin
  411.   with fcGetColor(Color) do
  412.   begin
  413.     if not GoodVideoDriver then
  414.     begin
  415.       // 5/10/99 - PYW - Fixed Flat Style painting bug in High Color mode.
  416.       if (r > 0) and (r mod 8 = 0) then dec(r);
  417.       if (g > 0) and (g mod 8 = 0) then dec(g);
  418.       if (b > 0) and (b mod 8 = 0) then dec(b);
  419.     end;
  420.     result := RGB(r, g, b);
  421.   end;
  422. end;
  423. function TfcCustomShapeBtn.UnusableColor: TColor;
  424. begin
  425.   //11/28/00 - Fix bug when 3dColor is set to clRed
  426.   if ColorToRGB(Color) <> DEFUNUSECOLOR then
  427.     result := DEFUNUSECOLOR else result := DEFUNUSECOLOR2;
  428. end;
  429. type TBooleanArray = array[0..0] of Boolean;
  430.      PBooleanArray = ^TBooleanArray;
  431. procedure TfcCustomShapeBtn.AssignTo(Dest: TPersistent);
  432. begin
  433.   if Dest is TfcCustomShapeBtn then
  434.     with Dest as TfcCustomShapeBtn do
  435.   begin
  436.     Orientation := self.Orientation;
  437.     PointList := self.PointList;
  438.     RoundRectBias := self.RoundRectBias;
  439.     Shape := self.Shape;
  440.   end;
  441.   inherited;
  442. end;
  443. procedure TfcCustomShapeBtn.Draw3dLines(Bitmap: TfcBitmap; PointList: array of TPoint;
  444.   NumPoints: Integer; TransColor: TColor);
  445.   function MidPoint(p1, p2: TPoint): TPoint;
  446.   begin
  447.     result := Point(p1.x + (p2.x - p1.x) div 2, p1.y + (p2.y - p1.y) div 2);
  448.   end;
  449. var PolyRgn: HRGN;
  450.     i: Integer;
  451.     Difference: TSize;
  452.     OutsideColor, InsideColor: TColor;
  453.     Highlights: PBooleanArray;
  454.     Offsets: PfcPolygonPoints;
  455.     Focused: Integer;
  456.     ACanvas: TCanvas;
  457.     DownFlag:boolean;
  458.     // 6/17/02
  459.     Function DrawDarkBorder: boolean;
  460.     begin
  461.        result:= not (csPaintCopy in ControlState) and
  462.                (self.Focused or Default);
  463.     end;
  464. begin
  465.   DownFlag := Down and not (csPaintCopy in ControlState); // 6/17/02
  466.   if ShowDownAsUp then begin
  467.      DownFlag := False;
  468.      if Clicked and MouseInControl(-1,-1,False) and not Selected then
  469.         DownFlag := True;
  470.   end;
  471.   ACanvas := Bitmap.Canvas;
  472.   if RoundShape then
  473.   begin
  474. //    fcOffsetBitmap(Bitmap, TransColor, Point(1, 1));
  475.     inherited Draw3dLines(Bitmap, Bitmap, TransColor, DownFlag);
  476. //    fcOffsetBitmap(Bitmap, TransColor, Point(-1, -1));
  477.     Exit;
  478.   end;
  479.   PolyRgn := CreatePolygonRgn(PointList, NumPoints, WINDING);
  480.   if PolyRgn = 0 then Exit;
  481.   Highlights := AllocMem(SizeOf(Boolean) * NumPoints);
  482.   Offsets := AllocMem(SizeOf(TPoint) * NumPoints);
  483.   try
  484.     for i := 0 to NumPoints - 2 do
  485.     begin
  486.       Highlights[i] := False;
  487.       Difference := fcSize(Abs(PointList[i + 1].x - PointList[i].x),
  488.                            Abs(PointList[i + 1].y - PointList[i].y));
  489.       with MidPoint(PointList[i], PointList[i + 1]) do
  490.         if (Difference.cx > Difference.cy) then
  491.         begin
  492.           if PtInRegion(PolyRgn, x, y + 1) then
  493.           begin
  494.             Highlights[i] := True;
  495.             Offsets[i] := Point(0, 1);
  496.           end else Offsets[i] := Point(0, -1);
  497.         end else
  498.         begin
  499.           if PtInRegion(PolyRgn, x + 1, y) then
  500.           begin
  501.             Highlights[i] := True;
  502.             Offsets[i] := Point(1, 0);
  503.           end else Offsets[i] := Point(-1, 0);
  504.         end;
  505.       if (Difference.cx = 0) then
  506.       begin
  507.         Offsets[i] := Point(Offsets[i].x, -1);
  508.         if PtInRegion(PolyRgn, PointList[i].x, fcMax(PointList[i].y, PointList[i + 1].y) + 1) then Offsets[i].y := 1;
  509.       end else if (Difference.cy = 0) then
  510.       begin
  511.         Offsets[i] := Point(-1, Offsets[i].y);
  512.         if PtInRegion(PolyRgn, fcMax(PointList[i].x, PointList[i + 1].x), PointList[i].y) then Offsets[i].x := 1;
  513.       end;
  514.     end;
  515.     if DrawDarkBorder then Focused := 1 else Focused := 0;
  516.     for i := 0 to NumPoints - 2 do
  517.     begin
  518.       if Highlights[i] xor DownFlag then InsideColor := ColorToRGB(ShadeColors.Btn3dLight)
  519.       else InsideColor := ColorToRGB(ShadeColors.BtnShadow);
  520.       ACanvas.Pen.Color := InsideColor;
  521.       ACanvas.PolyLine([
  522.         Point(PointList[i].x + Offsets[i].x * (1 + Focused), PointList[i].y + Offsets[i].y * (1 + Focused)),
  523.         Point(PointList[i + 1].x + Offsets[i].x * (1 + Focused), PointList[i + 1].y + Offsets[i].y * (1 + Focused))
  524.       ]);
  525.     end;
  526.     for i := 0 to NumPoints - 2 do
  527.     begin
  528.       if Highlights[i] xor DownFlag then OutsideColor := ColorToRGB(ShadeColors.BtnHighlight)
  529.       else OutsideColor := ColorToRGB(ShadeColors.BtnBlack);
  530.       ACanvas.Pen.Color := OutsideColor;
  531.       ACanvas.Polyline([
  532.         Point(PointList[i].x + Offsets[i].x * Focused, PointList[i].y + Offsets[i].y * Focused),
  533.         Point(PointList[i + 1].x + Offsets[i].x * Focused, PointList[i + 1].y + Offsets[i].y * Focused)
  534.       ]);
  535.     end;
  536.     if DrawDarkBorder then
  537.       for i := 0 to NumPoints - 2 do
  538.       begin
  539.         ACanvas.Pen.Color := ShadeColors.BtnFocus;
  540.         ACanvas.PolyLine([PointList[i], PointList[i + 1]]);
  541.       end;
  542.   finally
  543.     DeleteObject(PolyRgn);
  544.     FreeMem(Highlights);
  545.     FreeMem(Offsets);
  546.   end;
  547. end;
  548. function TfcCustomShapeBtn.RoundShape: Boolean;
  549. begin
  550.   result := Shape in [bsRoundRect, bsEllipse];
  551. end;
  552. procedure TfcCustomShapeBtn.DoComputeCanvasAttributes(ACanvas: TCanvas);
  553. begin
  554.   if Assigned(FOnComputeCanvasAttributes) then
  555.      FOnComputeCanvasAttributes(Self, ACanvas);
  556. end;
  557. procedure TfcCustomShapeBtn.GetDrawBitmap(DrawBitmap: TfcBitmap; ForRegion: Boolean;
  558.   ShadeStyle: TfcShadeStyle; Down: Boolean);
  559. var PointList: PfcPolyGonPoints;
  560.     NumPoints: Integer;
  561. //    DitherBm: TBitmap;
  562.     DoDraw3d: Boolean;
  563.     OldBrush, ABrush: HBRUSH;
  564.     {$ifdef fcUseThemeManager}
  565.     Button: TThemedButton;
  566.     Details: TThemedElementDetails;
  567.     r: TRect;
  568.     {$endif}
  569. //    IsDefault: boolean;
  570. begin
  571.   DoDraw3d := True;
  572.   //5/24/2000-PYW-Add check to not paint in 3D if control is disabled.
  573.   case ShadeStyle of
  574.     fbsFlat: DoDraw3d := (csDesigning in ComponentState) or (MouseInControl(-1, -1, False) and Enabled) or Down;
  575.   end;
  576.   ABrush := 0;
  577.   OldBrush := 0;
  578.   DrawBitmap.SetSize(Width, Height);
  579.   //3/16/99 - PYW - Raises canvas draw error when anchors cause width or height to be <=0
  580.   if (Width <=0) or (Height<=0) then exit;
  581.   DrawBitmap.Canvas.Brush.Color := UnusableColor;
  582.   DrawBitmap.Canvas.FillRect(Rect(0, 0, Width, Height));
  583.   DrawBitmap.Canvas.Brush.Color := CorrectedColor;
  584. //  DrawBitmap.Canvas.Brush.Color := clRed;
  585.   DoComputeCanvasAttributes(DrawBitmap.Canvas);
  586.   if DoDraw3d then DrawBitmap.Canvas.Pen.Color := ColorToRGB(DitherColor)
  587.   else DrawBitmap.Canvas.Pen.Color := DrawBitmap.Canvas.Brush.Color;
  588.   if Down and (DitherColor <> clNone) and (GroupIndex <> 0) then
  589.   begin
  590.     ABrush := fcGetDitherBrush;
  591.     SetBkColor(DrawBitmap.Canvas.Handle, ColorToRGB(DitherColor));
  592.     SetTextColor(DrawBitmap.Canvas.Handle, ColorToRGB(Color));
  593.     OldBrush := SelectObject(DrawBitmap.Canvas.Handle, ABrush);
  594.   end;
  595.   try
  596.     PointList := nil;
  597.     if RoundShape then
  598.     begin
  599.       DrawBitmap.Canvas.Pen.Color := CorrectedColor;
  600.       case Shape of
  601.         bsRoundRect: DrawBitmap.Canvas.RoundRect(
  602.           0, 0, Width - 1, Height - 1, RoundRectBias, RoundRectBias);
  603.         bsEllipse: DrawBitmap.Canvas.Ellipse(
  604.           0, 0, Width - 1, Height - 1);
  605.       end;
  606.       if not ForRegion and DoDraw3d then { 5/2/99 - RSW - Support flat for RoundShape }
  607.          Draw3dLines(DrawBitmap, [Point(0, 0)], 0, UnusableColor);
  608.     end else begin
  609.       NumPoints := GetPolygonPoints(PointList);
  610.       if PointList <> nil then Polygon(DrawBitmap.Canvas.Handle, PointList^, NumPoints);
  611.       if not ForRegion and DoDraw3d and (PointList <> nil) then Draw3dLines(DrawBitmap, Slice(PointList^, NumPoints), NumPoints, UnusableColor);
  612.       if (Shape in [bsRect]) and fcUseThemes(self) then
  613.       begin
  614. {         with LastDrawItemStruct do
  615.          begin
  616.            IsDefault := itemState and ODS_FOCUS <> 0;
  617.          end;
  618. }
  619.          {$ifdef fcUseThemeManager}
  620.          if not Enabled then
  621.             Button := tbPushButtonDisabled
  622.          else if Down then
  623.             Button := tbPushButtonPressed
  624.          else if MouseInControl(-1,-1, False) and not (csPaintCopy in ControlState) then
  625.             Button := tbPushButtonHot
  626.          else if Focused {or IsDefault } then
  627.             Button := tbPushButtonDefaulted
  628.          else
  629.             Button := tbPushButtonNormal;
  630. // 4/3/03 - Comment following code has it causes buttons in buttongroup to have bad canvas when transparent is true for the buttongroup
  631. //        if (parent<>nil) and not fcIsClass(parent.classtype, 'TCustomGrid') then
  632. //           ThemeServices.DrawParentBackground(Handle, DrawBitmap.Canvas.handle, nil, False);
  633.         Details := ThemeServices.GetElementDetails(Button);
  634.         r:= Rect(0, 0, Width-1, Height-1);
  635.         ThemeServices.DrawElement(DrawBitmap.Canvas.Handle, Details, r);
  636.         {$endif}
  637.       end
  638.       else if fcUseThemes(self) then
  639.       begin
  640.       end
  641.     end;
  642.     if OldBrush <> 0 then SelectObject(DrawBitmap.Canvas.Handle, OldBrush);
  643.     if ABrush <> 0 then DeleteObject(ABrush);
  644.   finally
  645.     if not RoundShape then FreeMem(PointList);
  646.   end;
  647. end;
  648. procedure TfcCustomShapeBtn.SizeToDefault;
  649. begin
  650.   if Width > Height then Height := Width else Width := Height;
  651. end;
  652. procedure TfcCustomShapeBtn.SetRoundRectBias(Value:Integer);
  653. begin
  654.   if Value <> FRoundRectBias then
  655.   begin
  656.     FRoundRectBias := Value;
  657.     RecreateWnd;
  658.   end;
  659. end;
  660. function TfcCustomShapeBtn.UseRegions: boolean;
  661. begin
  662.    result:= True;
  663. end;
  664. procedure TfcCustomShapeBtn.WndProc(var Message: TMessage);
  665. begin
  666.   inherited;
  667. end;
  668. {$R+}
  669. end.