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

Delphi控件源码

开发平台:

Delphi

  1. unit fcImgBtn;
  2. {
  3. //
  4. // Components : TfcImageBtn
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. // 12/7/99 - Transfer patch variables to support bitmap palette
  8. // 3/27/2002 - This can get called during destroy in which time the RegionData is invalid so exit.
  9. }
  10. interface
  11. {$i fcIfDef.pas}
  12. uses Windows, Messages, Classes, Controls, Forms, Graphics, StdCtrls,
  13.   CommCtrl, Buttons, Dialogs, Math, Consts, SysUtils, fcCommon, fcText,
  14.   fcButton, fcBitmap, fcChangeLink, fcImager
  15.   {$ifdef fcDelphi4up}
  16.   ,ImgList, ActnList
  17.   {$endif};
  18. type
  19.   TfcDitherStyle = (dsDither, dsBlendDither, dsFill);
  20.   TfcImgDownOffsets = class(TfcOffsets)
  21.   private
  22.     FImageDownX: Integer;
  23.     FImageDownY: Integer;
  24.   protected
  25.     procedure AssignTo(Dest: TPersistent); override;
  26.   public
  27.     constructor Create(AControl: TfcCustomBitBtn);
  28.   published
  29.     property ImageDownX: Integer read FImageDownX write FImageDownX default 2;
  30.     property ImageDownY: Integer read FImageDownY write FImageDownY default 2;
  31.   end;
  32.   TfcCustomImageBtn = class (TfcCustomBitBtn)
  33.   private
  34.     // Property Storage Variables
  35.     FDitherColor: TColor;
  36.     FDitherStyle: TfcDitherStyle;
  37.     FImage: TfcBitmap;
  38.     FImageDown: TfcBitmap;
  39.     FImageChangeLink: TfcChangeLink;
  40.     FExtImage: TComponent;
  41.     FExtImageDown: TComponent;
  42.     FTransparentColor: TColor;
  43.     // Property Access Methods
  44.     function GetOffsets: TfcImgDownOffsets;
  45.     function GetParentClipping: Boolean;
  46.     function GetRespectPalette: Boolean;
  47.     procedure SetDitherColor(Value: TColor);
  48.     procedure SetDitherStyle(Value: TfcDitherStyle);
  49.     procedure SetExtImage(Value: TComponent);
  50.     procedure SetExtImageDown(Value: TComponent);
  51.     procedure SetImage(Value: TfcBitmap);
  52.     procedure SetImageDown(Value: TfcBitmap);
  53.     procedure SetOffsets(Value: TfcImgDownOffsets);
  54.     procedure SetParentClipping(Value: Boolean);
  55.     procedure SetRespectPalette(Value: Boolean);
  56.     procedure SetTransparentColor(Value: TColor);
  57.   protected
  58.     procedure Draw3DLines(SrcBitmap, DstBitmap: TfcBitmap; TransColor: TColor; Down: Boolean);
  59.     procedure SetExtImages(Value: TComponent; var Prop: TComponent);
  60.     // Virtual Methods
  61.     procedure WndProc(var Message: TMessage); override;
  62.     function CreateRegion(DoImplementation: Boolean; Down: Boolean): HRgn; override;
  63.     function CreateOffsets: TfcOffsets; override;
  64.     function GetTransparentColor(Down: Boolean): TColor;
  65.     function ObtainImage(DownImage: Boolean): TfcBitmap; virtual;
  66.     function StoreRegionData: Boolean; override;
  67.     procedure AssignTo(Dest: TPersistent); override;
  68.     procedure CreateWnd; override;
  69.     procedure DestroyWnd; override;
  70.     procedure GetSizedImage(SourceBitmap: TfcBitmap; DestBitmap: TfcBitmap;
  71.       ShadeStyle: TfcShadeStyle; ForRegion,DownFlag: Boolean); virtual;
  72.     procedure ImageChanged(Sender: TObject); virtual;
  73.     procedure ExtImageDestroying(Sender: TObject);
  74.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  75.     function UseRegions: boolean; override;
  76.   public
  77.     Patch: Variant;
  78.     constructor Create(AOwner: TComponent); override;
  79.     destructor Destroy; override;
  80.     function ColorAtPoint(APoint: TPoint): TColor; virtual;
  81.     function IsMultipleRegions: Boolean; override;
  82.     procedure GetDrawBitmap(DrawBitmap: TfcBitmap; ForRegion: Boolean;
  83.       ShadeStyle: TfcShadeStyle; Down: Boolean); override;
  84.     procedure SplitImage; virtual;
  85.     procedure SizeToDefault; override;
  86.     // Public Properties
  87.     property DitherColor: TColor read FDitherColor write SetDitherColor;
  88.     property DitherStyle: TfcDitherStyle read FDitherStyle write SetDitherStyle;
  89.     property ExtImage: TComponent read FExtImage write SetExtImage;
  90.     property ExtImageDown: TComponent read FExtImageDown write SetExtImageDown;
  91.     property Image: TfcBitmap read FImage write SetImage;
  92.     property ImageDown: TfcBitmap read FImageDown write SetImageDown;
  93.     property Offsets: TfcImgDownOffsets read GetOffsets write SetOffsets;
  94.     property ParentClipping: Boolean read GetParentClipping write SetParentClipping;
  95.     property RespectPalette: Boolean read GetRespectPalette write SetRespectPalette default False;
  96.     property TransparentColor: TColor read FTransparentColor write SetTransparentColor;
  97.   end;
  98.   TfcImageBtn = class(TfcCustomImageBtn)
  99.   published
  100.     {$ifdef fcDelphi4Up}
  101.     property Action;
  102.     property Anchors;
  103.     property Constraints;
  104.     {$endif}
  105.     property AllowAllUp;
  106.     property Cancel;
  107.     property Caption;
  108.     property Color;
  109.     property Default;
  110.     property DitherColor;
  111.     property DitherStyle;
  112.     property DragCursor;   //3/31/99 - PYW - Exposed DragCursor and DragKind properties.
  113.     {$ifdef fcDelphi4Up}
  114.     property DragKind;
  115.     {$endif}
  116.     property DragMode;
  117.     property Down;
  118.     property Font;
  119.     property Enabled;
  120.     property ExtImage;
  121.     property ExtImageDown;
  122.     property Glyph;
  123.     property GroupIndex;
  124.     property Image;
  125.     property ImageDown;
  126.     property Kind;
  127.     property Layout;
  128.     property Margin;
  129.     property ModalResult;
  130.     property NumGlyphs;
  131.     property Offsets;
  132.     property Options;
  133.     property ParentClipping;
  134.     property ParentFont;
  135.     property ParentShowHint;
  136.     property PopupMenu;
  137.     property RespectPalette;
  138.     property ShadeColors;
  139.     property ShadeStyle;
  140.     property ShowHint;
  141.     {$ifdef fcDelphi4Up}
  142.     property SmoothFont;
  143.     {$endif}
  144.     property Style;
  145.     property Spacing;
  146.     property TabOrder;
  147.     property TabStop;
  148.     property TextOptions;
  149.     property TransparentColor;
  150.     property Visible;
  151.     property OnClick;
  152.     property OnDragDrop;
  153.     property OnDragOver;
  154.     property OnEndDrag;
  155.     property OnEnter;
  156.     property OnExit;
  157.     property OnKeyDown;
  158.     property OnKeyPress;
  159.     property OnKeyUp;
  160.     property OnMouseDown;
  161.     property OnMouseEnter;
  162.     property OnMouseLeave;
  163.     property OnMouseMove;
  164.     property OnMouseUp;
  165.     property OnSelChange;
  166.     property OnStartDrag;
  167.   end;
  168. implementation
  169. {$r-}
  170. constructor TfcImgDownOffsets.Create(AControl: TfcCustomBitBtn);
  171. begin
  172.   inherited;
  173.   FImageDownX := 2;
  174.   FImageDownY := 2;
  175. end;
  176. procedure TfcImgDownOffsets.AssignTo(Dest: TPersistent);
  177. begin
  178.   if Dest is TfcImgDownOffsets then
  179.     with Dest as TfcImgDownOffsets do
  180.   begin
  181.     ImageDownX := self.ImageDownX;
  182.     ImageDownY := self.ImageDownY;
  183.   end;
  184.   inherited;
  185. end;
  186. constructor TfcCustomImageBtn.Create(AOwner: TComponent);
  187. begin
  188.   inherited Create(AOwner);
  189.   UseHalftonePalette:= True;
  190.   FDitherColor := clWhite;
  191.   FImage := TfcBitmap.Create;
  192.   FImage.OnChange := ImageChanged;
  193.   FImageDown := TfcBitmap.Create;
  194.   FImageDown.OnChange := ImageChanged;
  195.   FTransparentColor := clNone;
  196.   FImageChangeLink := TfcChangeLink.Create;
  197.   FImageChangeLink.OnChange := ImageChanged;
  198.   Color := clNone;
  199. end;
  200. destructor TfcCustomImageBtn.Destroy;
  201. begin
  202.   FImage.Free;
  203.   FImageDown.Free;
  204.   FImageChangeLink.Free;
  205.   inherited Destroy;
  206. end;
  207. function TfcCustomImageBtn.IsMultipleRegions: Boolean;
  208. begin
  209.   result := (not ObtainImage(False).Empty and not ObtainImage(True).Empty) or (ShadeStyle = fbsRaised);
  210.   if result and (FTransparentColor=clNullColor) then result:= false;
  211. end;
  212. function TfcCustomImageBtn.StoreRegionData: Boolean;
  213. begin
  214.   result := True;
  215. end;
  216. // Added Down parameter to fix bug. - 4/6/99
  217. function TfcCustomImageBtn.GetTransparentColor(Down: Boolean): TColor;
  218. begin
  219.   if FTransparentColor <> clNullColor then
  220.   begin
  221.     if FTransparentColor = clNone then
  222.     begin
  223.       if Down and not ObtainImage(True).Empty then
  224.         result := fcGetStdColor(ObtainImage(True).Pixels[0, 0])
  225.       else result:= fcGetStdColor(ObtainImage(False).Pixels[0, 0]);
  226.       result := ColorToRGB(result) and $00FFFFFF;
  227.     end else result := FTransparentColor;
  228.   end else result := clNullColor;
  229. end;
  230. function TfcCustomImageBtn.ObtainImage(DownImage: Boolean): TfcBitmap;
  231. begin
  232.   if (not DownImage and (FExtImage <> nil)) and not (csDestroying in FExtImage.ComponentState) then
  233.   begin
  234.     result := Image;
  235.     if FExtImage is TfcCustomImager then with FExtImage as TfcCustomImager do
  236.     begin
  237.       if WorkBitmap.Empty and not PictureEmpty then Resized;
  238.       result := WorkBitmap;
  239.     end else if FExtImage is TfcCustomImageBtn then with FExtImage as TfcCustomImageBtn do
  240.       result := Image;
  241.   end else if DownImage and (FExtImageDown <> nil) and not (csDestroying in FExtImageDown.ComponentState) then
  242.   begin
  243.     result := ImageDown;
  244.     if FExtImageDown is TfcCustomImager then with FExtImageDown as TfcCustomImager do
  245.     begin
  246.       if WorkBitmap.Empty and not PictureEmpty then Resized;
  247.       result := WorkBitmap;
  248.     end else if FExtImageDown is TfcCustomImageBtn then with FExtImageDown as TfcCustomImageBtn do
  249.       result := ImageDown;
  250.   end else if DownImage then result := ImageDown
  251.   else result := Image;
  252. end;
  253. function TfcCustomImageBtn.CreateOffsets: TfcOffsets;
  254. begin
  255.   result := TfcImgDownOffsets.Create(self);
  256. end;
  257. function TfcCustomImageBtn.CreateRegion(DoImplementation: Boolean; Down: Boolean): HRgn;
  258. var SizedImage: TfcBitmap;
  259.     Rgn: HRGN;
  260. begin
  261.   if TransparentColor = clNullColor then
  262.   begin
  263.     result := 0;
  264.     Exit;
  265.   end;
  266.   result := inherited CreateRegion(False, Down);
  267.   if not DoImplementation or (result <> 0) or ObtainImage(False).Empty then Exit;
  268.   SizedImage := TfcBitmap.Create;
  269.   SizedImage.RespectPalette := RespectPalette;
  270.   GetSizedImage(ObtainImage(Down and not ObtainImage(True).Empty), SizedImage, ShadeStyle, True, Down);
  271.   result := fcRegionFromBitmap(SizedImage, GetTransparentColor(Down));
  272.   if ShadeStyle = fbsRaised then
  273.   begin
  274.     Rgn := CreateRectRgn(0, 0, 10, 10);
  275.     if CombineRgn(Rgn, result, 0, RGN_COPY) = ERROR then Exit;
  276.     OffsetRgn(Rgn, 2, 2);
  277.     if Down then CombineRgn(result, Rgn, 0, RGN_COPY)
  278.     else CombineRgn(result, Rgn, result, RGN_OR);
  279.     DeleteObject(Rgn);
  280.   end;
  281.   SizedImage.Free;
  282.   SaveRegion(result, Down);
  283. end;
  284. procedure TfcCustomImageBtn.SetDitherColor(Value: TColor);
  285. begin
  286.   if FDitherColor <> Value then
  287.   begin
  288.     FDitherColor := Value;
  289.     Invalidate;
  290.   end;
  291. end;
  292. procedure TfcCustomImageBtn.SetDitherStyle(Value: TfcDitherStyle);
  293. begin
  294.   if FDitherStyle <> Value then
  295.   begin
  296.     FDitherStyle := Value;
  297.     Invalidate;
  298.   end;
  299. end;
  300. procedure TfcCustomImageBtn.SetImage(Value: TfcBitmap);
  301. begin
  302.   if Value <> nil then ExtImage := nil;
  303.   FImage.Assign(Value);
  304.   if not Down or ObtainImage(True).Empty then RecreateWnd;
  305. end;
  306. procedure TfcCustomImageBtn.SetImageDown(Value: TfcBitmap);
  307. begin
  308.   if Value <> nil then ExtImageDown := nil;
  309.   FImageDown.Assign(Value);
  310.   if Down then RecreateWnd;
  311. end;
  312. procedure TfcCustomImageBtn.SetExtImages(Value: TComponent; var Prop: TComponent);
  313. begin
  314.   if Prop <> nil then
  315.   begin
  316.     if Prop is TfcCustomImager then (Prop as TfcCustomImager).UnRegisterChanges(FImageChangeLink)
  317.     else if Prop is TfcCustomImageBtn then (Prop as TfcCustomImageBtn).UnRegisterChanges(FImageChangeLink);
  318.   end;
  319.   Prop := Value;
  320.   if Value <> nil then
  321.   begin
  322.     if Value is TfcCustomImager then (Value as TfcCustomImager).RegisterChanges(FImageChangeLink)
  323.     else if Value is TfcCustomImageBtn then (Value as TfcCustomImageBtn).Image.RegisterChanges(FImageChangeLink);
  324.     Value.FreeNotification(self);
  325.   end;
  326.   RecreateWnd;
  327. end;
  328. procedure TfcCustomImageBtn.SetExtImage(Value: TComponent);
  329. begin
  330.   if Value <> nil then Image.Clear;
  331.   SetExtImages(Value, FExtImage);
  332. end;
  333. procedure TfcCustomImageBtn.SetExtImageDown(Value: TComponent);
  334. begin
  335.   if Value <> nil then ImageDown.Clear;
  336.   SetExtImages(Value, FExtImageDown);
  337. end;
  338. procedure TfcCustomImageBtn.Draw3DLines(SrcBitmap, DstBitmap: TfcBitmap; TransColor: TColor; Down: Boolean);
  339. var WorkingBm{, DstBm}: TfcBitmap;
  340.     DstPixels, SrcPixels: PfcPLines;
  341.     StartPt, EndPt, OldEndPt: TPoint;
  342.     Col, Row: Integer;
  343.     ABtnHighlight, ABtn3DLight, ABtnShadow, ABtnBlack: TfcColor;
  344.     BitmapSize: TSize;
  345.   function CheckPoint(p: TPoint): TPoint;
  346.   begin
  347.     result := p;
  348.     if result.x < 0 then result.x := 0;
  349.     if result.y < 0 then result.y := 0;
  350.     if result.x > BitmapSize.cx - 1 then result.x := BitmapSize.cx - 1;
  351.     if result.y > BitmapSize.cy - 1 then result.y := BitmapSize.cy - 1;
  352.   end;
  353.   function PointValid(x, y: Integer): Boolean;
  354.   begin
  355.     result := not ((x < 0) or (y < 0) or
  356.       (x >= BitmapSize.cx) or (y >= BitmapSize.cy));
  357.   end;
  358.   procedure GetFirstPixelColor(CurrentCol, CurrentRow: Integer; var ResultPt: TPoint; AColor: TColor; NotColor: Boolean; SearchForward: Boolean);
  359.   var i, MaxIncr: Integer;
  360.       CurColor: TColor;
  361.   begin
  362.     if SearchForward then MaxIncr := fcMin(BitmapSize.cx - CurrentCol, BitmapSize.cy - CurrentRow)
  363.     else MaxIncr := fcMin(CurrentCol, CurrentRow);
  364.     for i := 0 to MaxIncr - 1 do
  365.     begin
  366.       with SrcPixels[CurrentRow, CurrentCol] do CurColor := RGB(r, g, b);
  367.       if ((CurColor = AColor) and not NotColor) or
  368.          ((CurColor <> AColor) and NotColor) then
  369.       begin
  370.         ResultPt.x := CurrentCol;
  371.         ResultPt.y := CurrentRow;
  372.         if not NotColor then ResultPt := CheckPoint(Point(ResultPt.x - 1, ResultPt.y - 1));
  373.         Break;
  374.       end;
  375.       if SearchForward then inc(CurrentCol) else dec(CurrentCol);
  376.       if SearchForward then inc(CurrentRow) else dec(CurrentRow);
  377.     end;
  378.   end;
  379.   procedure DrawHighlights(ABtnBlack, ABtnShadow, ABtn3dLight, ABtnHighlight: TfcColor);
  380.   var AEndPt, AStartPt: TPoint;
  381.   begin
  382.     AEndPt := EndPt;
  383.     AStartPt := StartPt;
  384.     if (boFocusable in Options) and (Focused) then
  385.       AStartPt := Point(AStartPt.x + 1, AStartPt.y + 1);
  386.     with Point(AEndPt.x - 1, AEndPt.y - 1) do
  387.       if PointValid(x, y) then DstPixels[y, x] := ABtnShadow;
  388.     with Point(AStartPt.x + 1, AStartPt.y + 1) do
  389.       if PointValid(x, y) then DstPixels[y, x] := ABtn3dLight;
  390.     with Point(AEndPt.x, AEndPt.y) do
  391.       if PointValid(x, y) then DstPixels[y, x] := ABtnBlack;
  392.     with Point(AStartPt.x, AStartPt.y) do
  393.       if PointValid(x, y) then DstPixels[y, x] := ABtnHighlight;
  394.     if (boFocusable in Options) and (Focused) and Down then
  395.       with Point(AStartPt.x - 1, AStartPt.y - 1) do
  396.         if PointValid(x, y) then DstPixels[y, x] := fcGetColor(clBlack);
  397.   end;
  398. begin
  399.   if SrcBitmap.Empty or (SrcBitmap.Width <> DstBitmap.Width) or (SrcBitmap.Height <> DstBitmap.Height) then
  400.     Exit;
  401.   // Must convert to BGR values because apparantly that's what PixBuf is...
  402.   ABtnHighlight := fcGetColor(ColorToRGB(ShadeColors.BtnHighlight));
  403.   ABtn3dLight := fcGetColor(ColorToRGB(ShadeColors.Btn3dLight));
  404.   ABtnShadow := fcGetColor(ColorToRGB(ShadeColors.BtnShadow));
  405.   ABtnBlack := fcGetColor(ColorToRGB(ShadeColors.BtnBlack));
  406.   BitmapSize.cx := SrcBitmap.Width;
  407.   BitmapSize.cy := SrcBitmap.Height;
  408.   WorkingBm := TfcBitmap.Create;
  409.   WorkingBm.Assign(SrcBitmap);
  410. //  DstBm := nil;
  411. {  if DstBitmap = SrcBitmap then WorkingPixels := WorkingBm.Pixels
  412.   else begin
  413.     DstBm := TfcBitmap.Create;
  414.     DstBm.Assign(DstBitmap);
  415.     WorkingPixels := DstBm.Pixels;
  416.   end;}
  417.   SrcPixels := WorkingBm.Pixels;
  418.   DstPixels := DstBitmap.Pixels;
  419.   if TransColor = -1 then TransColor := fcGetStdColor(WorkingBm.Pixels[0, 0]);
  420.   try
  421.     // Work Diagonally from top right of image to Top left of image
  422.     Col := BitmapSize.cx - 1;
  423.     Row := 0;
  424.     while Row < WorkingBm.Height do
  425.     begin
  426.       // Find the first non transparent pixel
  427.       EndPt := Point(Col - 1, Row - 1);
  428.       repeat
  429.         StartPt := Point(-1, -1);
  430.         GetFirstPixelColor(EndPt.x + 1, EndPt.y + 1, StartPt, TransColor, True, True);
  431.         if (StartPt.x <> -1) and (StartPt.y <> -1) then
  432.         begin
  433.           OldEndPt := EndPt;
  434.           EndPt := CheckPoint(Point(Col + fcMin(BitmapSize.cx - 1 - Col, BitmapSize.cy - 1 - Row),
  435.             Row + fcMin(BitmapSize.cx - 1 - Col, BitmapSize.cy - 1 - Row)));
  436.           GetFirstPixelColor(StartPt.x + 1, StartPt.y + 1, EndPt, TransColor, False, True);
  437.           if Focused or Default then
  438.           begin
  439.             StartPt := Point(StartPt.x + 1, StartPt.y + 1);
  440.             EndPt := Point(EndPt.x - 1, EndPt.y - 1);
  441.           end;
  442.           if not Down then DrawHighlights(ABtnBlack, ABtnShadow, ABtn3dLight, ABtnHighlight)
  443.           else DrawHighlights(ABtnHighlight, ABtn3dLight, ABtnShadow, ABtnBlack);
  444.           if Focused or Default then
  445.           begin
  446.             StartPt := Point(StartPt.x - 1, StartPt.y - 1);
  447.             EndPt := Point(EndPt.x + 1, EndPt.y + 1);
  448.             DstPixels[StartPt.y, StartPt.x] := ABtnBlack;
  449.             DstPixels[EndPt.y, EndPt.x] := ABtnBlack;
  450.           end;
  451.         end;
  452.       until (StartPt.x = -1) and (StartPt.y = -1);
  453.       if Col > 0 then dec(Col) else inc(Row);
  454.     end;
  455. {
  456.     if SrcBitmap = DstBitmap then
  457.       DstBitmap.Canvas.Draw(0, 0, WorkingBm)
  458.     else begin
  459.       DstBitmap.Canvas.Draw(0, 0, DstBm);
  460.       DstBm.Free;
  461.     end;}
  462.   finally
  463.     WorkingBm.Free;
  464.   end;
  465. end;
  466. function TfcCustomImageBtn.ColorAtPoint(APoint: TPoint): TColor;
  467. var Bitmap: TfcBitmap;
  468. begin
  469.   Bitmap := TfcBitmap.Create;
  470.   try
  471.     GetDrawBitmap(Bitmap, False, ShadeStyle, Down);
  472.     result := Bitmap.Canvas.Pixels[APoint.x, APoint.y];
  473.   finally
  474.     Bitmap.Free;
  475.   end;
  476. end;
  477. procedure TfcCustomImageBtn.GetDrawBitmap(DrawBitmap: TfcBitmap; ForRegion: Boolean;
  478.   ShadeStyle: TfcShadeStyle; Down: Boolean);
  479. var TempImage: TfcBitmap;
  480.     Offset: TPoint;
  481. begin
  482.   DrawBitmap.SetSize(Width, Height);
  483.   if RespectPalette then
  484.   begin
  485.     CopyMemory(@DrawBitmap.Colors, @ObtainImage(False).Colors, SizeOf(ObtainImage(False).Colors));
  486.     DrawBitmap.Patch[0]:= ObtainImage(False).Patch[0]; { 12/7/99 - Transfer patch variables to support bitmap palette}
  487.     DrawBitmap.Patch[1]:= ObtainImage(False).Patch[1];
  488.     DrawBitmap.RespectPalette := True;
  489.   end;
  490.   //3/16/99 - PYW - Raises canvas draw error when anchors cause width or height to be <=0
  491.   with DrawBitmap do if (Width <=0) or (Height<=0) then exit;
  492.   if ObtainImage(False).Empty then with DrawBitmap do
  493.   begin
  494.     Canvas.Brush.Color := clBtnFace;
  495.     Canvas.Pen.Style := psDashDot;
  496.     Canvas.Pen.Color := clBlack;
  497.     Canvas.Rectangle(0, 0, Width, Height);
  498.     Exit;
  499.   end;
  500.   Offset := Point(0, 0);                                       // Offset used if drawing shadows, etc.
  501.   TempImage := TfcBitmap.Create;                                 // Temp image stores a copy of either Image or ImageDown
  502.   TempImage.RespectPalette := RespectPalette;
  503.   if not Down or ObtainImage(True).Empty then
  504.     GetSizedImage(ObtainImage(False), TempImage, ShadeStyle, ForRegion, Down)                            // If the button is not down or there is no down image
  505.   else
  506.     GetSizedImage(ObtainImage(True), TempImage, ShadeStyle, ForRegion, Down);                    // defined then use the up image, otherwise use the down image.
  507.   try
  508.     if Down and ObtainImage(True).Empty then Offset := Point(Offsets.ImageDownX, Offsets.ImageDownY);  // Offset for Upper-left shadow
  509.     if (ShadeStyle = fbsHighlight) or ((ShadeStyle = fbsFlat) and MouseInControl(-1, -1, False)) then
  510.     begin
  511.       DrawBitmap.Canvas.Draw(Offset.x, Offset.y, TempImage);
  512.       Draw3dLines(TempImage, DrawBitmap, GetTransparentColor(Down), Down);
  513.       Offset := Point(-1, -1);
  514.     end else begin
  515.        { 12/7/99 - The next 2 lines should not be needed anymore }
  516.       DrawBitmap.Canvas.Brush.Color := ShadeColors.Shadow;
  517.       DrawBitmap.Canvas.Pen.Color := ShadeColors.Shadow;
  518.       DrawBitmap.Canvas.Rectangle(0, 0, Width, Height); // 1/20/2000 - Don't use TRect for Delphi 5 compatibility
  519. //      DrawBitmap.Canvas.Rectangle(Rect(0, 0, Width, Height));   // Fill in with shadow color
  520.     end;
  521.     if (Offset.x <> -1) and (Offset.y <> -1) then
  522.     begin
  523.       if TransparentColor <> clNullColor then
  524.       begin
  525.         { 12/7/99 - Change transparent pixels to shadow color }
  526.         if Down and (DitherStyle=dsBlendDither) then begin
  527.           TempImage.Transparent := True;
  528.           TempImage.TransparentColor := GetTransparentColor(Down);
  529.         end
  530.         else
  531.           TempImage.ChangeColor(fcGetColor(GetTransparentColor(down)), fcGetcolor(ShadeColors.Shadow));
  532. //        TempImage.Transparent := True;
  533. //        TempImage.TransparentColor := GetTransparentColor(Down);
  534.       end;
  535.       DrawBitmap.Canvas.Draw(Offset.x, Offset.y, TempImage)
  536.     end;
  537.   finally
  538.     TempImage.Free;                                            // Clean up temp bitmaps
  539.   end;
  540. end;
  541. procedure TfcCustomImageBtn.SplitImage;
  542. var Bitmap, Bitmap2: TfcBitmap;
  543.     ARgn: HRGN;
  544. begin
  545.   if not ObtainImage(False).Empty then
  546.   begin
  547.     Bitmap := TfcBitmap.Create;
  548.     Bitmap2 := TfcBitmap.Create;
  549.     GetDrawBitmap(Bitmap, False, fbsHighlight, False);
  550.     GetDrawBitmap(Bitmap2, False, fbsHighlight, True);
  551.     ARgn := CreateRegion(True, Down);
  552.     fcClipBitmapToRegion(Bitmap2, ARgn);
  553.     DeleteObject(ARgn);
  554.     ObtainImage(False).Assign(Bitmap);
  555.     ImageDown.Assign(Bitmap2);
  556.     Bitmap.Free;
  557.     Bitmap2.Free;
  558.     RecreateWnd;
  559.   end;
  560. end;
  561. procedure TfcCustomImageBtn.SizeToDefault;
  562. var Rect: TRect;
  563. begin
  564.   if not ObtainImage(False).Empty then
  565.   begin
  566.     Width := ObtainImage(False).Width;
  567.     Height := ObtainImage(False).Height;
  568.     Rect := BoundsRect;
  569.     if Parent <> nil then InvalidateRect(Parent.Handle, @Rect, True);
  570.   end;
  571. end;
  572. procedure TfcCustomImageBtn.AssignTo(Dest: TPersistent);
  573. begin
  574.   if Dest is TfcCustomImageBtn then
  575.     with Dest as TfcCustomImageBtn do
  576.   begin
  577.     DitherColor := self.DitherColor;
  578.     DitherStyle := self.DitherStyle;
  579. {    Image := self.Image;
  580.     ImageDown := self.ImageDown;  DONT CHANGE THIS!!!}
  581.     ExtImage := self;
  582.     ExtImageDown := self;
  583.     Offsets.Assign(self.Offsets);
  584.     RespectPalette := self.RespectPalette;
  585.     TransparentColor := self.TransparentColor;
  586.   end;
  587.   inherited;
  588. end;
  589. procedure TfcCustomImageBtn.CreateWnd;
  590. begin
  591.   if Image.Sleeping then Image.Wake;
  592.   inherited;
  593.   ApplyRegion;
  594. end;
  595. procedure TfcCustomImageBtn.DestroyWnd;
  596. begin
  597.   inherited;
  598.   Image.Sleep;
  599. end;
  600. procedure TfcCustomImageBtn.GetSizedImage(SourceBitmap: TfcBitmap; DestBitmap: TfcBitmap;
  601.   ShadeStyle: TfcShadeStyle; ForRegion,DownFlag: Boolean);
  602. var s: TSize;
  603.     Rgn: HRGN;
  604.     BlendColor: TColor;
  605. begin
  606.   Rgn := 0;
  607.   s := fcSize(Width, Height);
  608.     //3/16/99 - PYW - Raises canvas draw error when anchors cause width or height to be <=0
  609.   if (Width <=0) or (Height<=0) then exit;
  610.   if ShadeStyle = fbsRaised then s := fcSize(Width - 2, Height - 2);
  611.   DestBitmap.SetSize(s.cx, s.cy);
  612.   if not ForRegion and ((Color <> clNone) or
  613.      ((GroupIndex > 0) and DownFlag and (DitherColor <> clNone) and ObtainImage(True).Empty)) then
  614.     Rgn := CreateRegion(True, DownFlag);
  615.   DestBitmap.Canvas.StretchDraw(Rect(0, 0, s.cx, s.cy), SourceBitmap);
  616.   if not ForRegion and (Color <> clNone) then
  617.   begin
  618.     SelectClipRgn(DestBitmap.Canvas.Handle, Rgn);
  619.     DestBitmap.TransparentColor := GetTransparentColor(DownFlag);
  620.     with fcBitmap.fcGetColor(Color) do DestBitmap.Colorize(r, g, b);
  621.   end;
  622.   if (GroupIndex > 0) and DownFlag and (DitherColor <> clNone) and not ForRegion and ObtainImage(True).Empty then
  623.   begin
  624.     if ShadeStyle = fbsRaised then OffsetRgn(Rgn, -2, -2);
  625.     SelectClipRgn(DestBitmap.Canvas.Handle, Rgn);
  626.     if DitherStyle in [dsDither, dsBlendDither] then
  627.     begin
  628.       if DitherStyle = dsBlendDither then BlendColor := clNone else BlendColor := clSilver;
  629.       fcDither(DestBitmap.Canvas, Rect(0, 0, Width, Height), BlendColor, DitherColor);
  630.     end else begin
  631.       DestBitmap.Canvas.Brush.Color := DitherColor;
  632.       DestBitmap.Canvas.FillRect(Rect(0, 0, Width, Height));
  633.     end;
  634.   end;
  635.   if Rgn <> 0 then
  636.   begin
  637.     SelectClipRgn(DestBitmap.Canvas.Handle, 0);
  638.     DeleteObject(Rgn);
  639.   end;
  640. end;
  641. procedure TfcCustomImageBtn.ImageChanged(Sender: TObject);
  642. var ARgnData: PfcRegionData;
  643.     r: TRect;
  644. begin
  645.   //3/27/2002 - This can get called during destroy in which time the RegionData is invalid so exit.
  646.   if csDestroying in componentstate then exit;
  647.   ARgnData := nil;
  648.   if Sender = ObtainImage(False) then ARgnData := @FRegionData
  649.   else if Sender = ObtainImage(True) then ARgnData := @FDownRegionData;
  650.   if ARgnData <> nil then ClearRegion(ARgnData);
  651.   (Sender as TfcBitmap).IgnoreChange := True;
  652.   ApplyRegion;
  653.   (Sender as TfcBitmap).IgnoreChange := False;
  654.   r := BoundsRect;
  655.   if Parent <> nil then InvalidateRect(Parent.Handle, @r, True);
  656.   Invalidate;
  657. end;
  658. procedure TfcCustomImageBtn.ExtImageDestroying(Sender: TObject);
  659. begin
  660.   if Sender = FExtImage then FExtImage := nil;
  661. end;
  662. procedure TfcCustomImageBtn.Notification(AComponent: TComponent; Operation: TOperation);
  663. begin
  664.   inherited;
  665.   if (Operation = opRemove) then
  666.   begin
  667.     if (AComponent = FExtImage) then FExtImage := nil
  668.     else if (AComponent = FExtImageDown) then FExtImageDown := nil;
  669.   end;
  670. end;
  671. function TfcCustomImageBtn.GetOffsets: TfcImgDownOffsets;
  672. begin
  673.   result := TfcImgDownOffsets(inherited Offsets);
  674. end;
  675. function TfcCustomImageBtn.GetParentClipping: Boolean;
  676. begin
  677.   result := False;
  678.   if Parent <> nil then
  679.     result := GetWindowLong(Parent.Handle, GWL_STYLE) and WS_CLIPCHILDREN = WS_CLIPCHILDREN;
  680. end;
  681. function TfcCustomImageBtn.GetRespectPalette: Boolean;
  682. begin
  683.   result := ObtainImage(False).RespectPalette;
  684. end;
  685. procedure TfcCustomImageBtn.SetOffsets(Value: TfcImgDownOffsets);
  686. begin
  687.   inherited Offsets := Value;
  688. end;
  689. procedure TfcCustomImageBtn.SetParentClipping(Value: Boolean);
  690. begin
  691.   // 9/20/01
  692.   if (Parent <> nil) and not (csDesigning in ComponentState) then
  693.   begin
  694. //    if Value then
  695. //      SetWindowLong(Parent.Handle, GWL_STYLE,
  696. //       GetWindowLong(Parent.Handle, GWL_STYLE) or WS_CLIPCHILDREN)
  697. //    else
  698.       // 6/25/01 - Only disable clipping
  699.       SetWindowLong(Parent.Handle, GWL_STYLE,
  700.         GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
  701.   end;
  702. end;
  703. procedure TfcCustomImageBtn.SetRespectPalette(Value: Boolean);
  704. begin
  705.   ObtainImage(False).RespectPalette := Value;
  706.   ObtainImage(True).RespectPalette := Value;
  707.   Invalidate;
  708. end;
  709. procedure TfcCustomImageBtn.SetTransparentColor(Value: TColor);
  710. var Rect: TRect;
  711. begin
  712.   if FTransparentColor <> Value then
  713.   begin
  714.     FTransparentColor := Value;
  715.     RecreateWnd;
  716.     Rect := BoundsRect;
  717.     if Parent <> nil then InvalidateRect(Parent.Handle, @Rect, True);
  718.   end;
  719. end;
  720. function TfcCustomImageBtn.UseRegions: boolean;
  721. begin
  722.    result:= (FTransparentColor<>clNullColor)
  723. end;
  724. procedure TfcCustomImageBtn.WndProc(var Message: TMessage);
  725. begin
  726.   inherited;
  727. end;
  728. {$r+}
  729. end.