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

Delphi控件源码

开发平台:

Delphi

  1. unit fcButton;
  2. {
  3. //
  4. // Components : TfcButton
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. //
  8. // Changes:
  9. // RSW - 3/9/99 - Process default button when carriage return or Cancel entered
  10. // 6/6/99 - Respect windows smooth font settings when painting text of buttons
  11. // 6/8/99 - Improved support for painting flat style if dialog is shown in button's OnClick
  12. // 7/13/99 - PYW - Changed to always process mouse up in fcoutlookbar
  13. // 7/26/99 - Call click on space key
  14. // 7/26/99 - setfocus when mouse clicked on button if focusable is true
  15. // 11/17/99 - PYW - Don't HotTrack if form is not the active form.
  16. // 2/22/00 - Disregard parent test if MDI form
  17. // PYW - 5/1/00 - Added flag because sendmessage causes some recursion when using the OnMouseDown.  Specifically the MenuForm example project.
  18. // PYW - 5/18/2000 - Don't exit if ParentForm was created using CreateParented.
  19. // PYW - 6/2/2000 - Fix bug when using Raised ShadeStyle and the button's OnClick event to show a dialog.
  20. // PYW - 6/19/2000 - Solve mousedown problems with nonfocusable buttons. Set BasePatch[1] := True to preserve old behavior.
  21. // RSW - 7/6/00 - Resolve redline problem with some environments
  22. // 7/31/00 - Disregard parent test for ActiveX forms
  23. // 8/18/00 - Remove default as inconsistent with constructor
  24. // 1/3/01 - Use SetButtonDown procedure so AllowAllUp is considered. -PYW
  25. // 10/15/2001- Only set this if groupindex > 0.
  26. // 12/20/2001 - Skip invisible controls. -PYW
  27. // 6/17/02 - Support button painting in grid
  28. }
  29. interface
  30. {$i fcIfDef.pas}
  31. uses Windows, Messages, Classes, Controls, Forms, Graphics, StdCtrls,
  32.   CommCtrl, Buttons, Dialogs, Math, Consts, SysUtils, fccommon, fcBitmap, fcChangeLink,
  33.   TypInfo, dbctrls, db,
  34.   {$ifdef fcDelphi7Up}
  35.   Themes,
  36.   {$endif}
  37.   {$ifdef ThemeManager}
  38.   thememgr, themesrv, uxtheme,
  39.   {$endif}
  40.   {$ifdef fcDelphi4Up}
  41.   ImgList, ActnList,
  42.   {$endif}
  43.   {$ifdef fcdelphi6Up}
  44.   variants,
  45.   {$endif}
  46.   fcText;
  47. const DESIGN_KEY = VK_MENU;
  48. type
  49.   TfcShadeStyle = (fbsNormal, fbsRaised, fbsHighlight, fbsFlat);
  50.   TfcButtonOption = (boFocusable, boOverrideActionGlyph, boToggleOnUp,
  51.     boFocusRect, boAutoBold);
  52.   TfcButtonOptions = set of TfcButtonOption;
  53.   TfcCustomBitBtn = class;
  54.   TfcCustomBitBtnClass = class of TfcCustomBitBtn;
  55.   TfcRegionData = record
  56.     dwSize: Integer;
  57.     rgnData: PRgnData;
  58.   end;
  59.   PfcRegionData = ^TfcRegionData;
  60.   TfcOffsets =  class(TPersistent)
  61.   private
  62.     // Property Storage Variables
  63.     FControl: TWinControl;
  64.     FGlyphX: Integer;
  65.     FGlyphY: Integer;
  66.     FTextX: Integer;
  67.     FTextY: Integer;
  68.     FTextDownX: Integer;
  69.     FTextDownY: Integer;
  70.     procedure SetGlyphX(Value: Integer);
  71.     procedure SetGlyphY(Value: Integer);
  72.     procedure SetTextX(Value: Integer);
  73.     procedure SetTextY(Value: Integer);
  74.   protected
  75.     procedure AssignTo(Dest: TPersistent); override;
  76.     property Control: TWinControl read FControl;
  77.   public
  78.     constructor Create(Button: TfcCustomBitBtn);
  79.   published
  80.     property GlyphX: Integer read FGlyphX write SetGlyphX default 0;
  81.     property GlyphY: Integer read FGlyphY write SetGlyphY default 0;
  82.     property TextX: Integer read FTextX write SetTextX default 0;
  83.     property TextY: Integer read FTextY write SetTextY default 0;
  84.     property TextDownX: Integer read FTextDownX write FTextDownX default 1;
  85.     property TextDownY: Integer read FTextDownY write FTextDownY default 1;
  86.   end;
  87.   TfcShadeColors = class(TPersistent)
  88.   private
  89.     FButton: TfcCustomBitBtn;
  90.     FBtnHighlight: TColor;
  91.     FBtn3dLight: TColor;
  92.     FBtnShadow: TColor;
  93.     FBtnBlack: TColor;
  94.     FBtnFocus: TColor;
  95.     FShadow: TColor;
  96.     procedure SetBtn3DLight(Value: TColor);
  97.     procedure SetBtnBlack(Value: TColor);
  98.     procedure SetBtnHighlight(Value: TColor);
  99.     procedure SetBtnShadow(Value: TColor);
  100.     procedure SetBtnFocus(Value: TColor);
  101.     procedure SetShadow(Value: TColor);
  102.   protected
  103.     procedure AssignTo(Dest: TPersistent); override;
  104.   public
  105.     constructor Create(Button: TfcCustomBitBtn);
  106.   published
  107.     property Btn3DLight: TColor read FBtn3DLight write SetBtn3DLight default cl3DLight;
  108.     property BtnHighlight: TColor read FBtnHighlight write SetBtnHighlight default clBtnHighlight;
  109.     property BtnShadow: TColor read FBtnShadow write SetBtnShadow default clBtnShadow;
  110.     property BtnBlack: TColor read FBtnBlack write SetBtnBlack default clBlack;
  111.     property BtnFocus: TColor read FBtnFocus write SetBtnFocus default clBlack;
  112.     property Shadow: TColor read FShadow write SetShadow default clBlack;
  113.   end;
  114.   TfcCustomBitBtn = class(TWinControl)
  115.   private
  116.     // Property Storage Variables
  117.     FActive: Boolean;
  118.     FAllowAllUp: Boolean;
  119.     FCancel: Boolean;
  120.     FDefault: Boolean;
  121.     FDown: Boolean;
  122.     FGlyph: TBitmap;
  123.     FGroupIndex: Integer;
  124.     FInMouseSendForMouseActivate:Boolean;
  125.     FKind: TBitBtnKind;
  126.     FLayout: TButtonLayout;
  127.     FMargin: Integer;
  128.     FModalResult: TModalResult;
  129.     FNumGlyphs: TNumGlyphs;
  130.     FRegion, FLastRegion: HRgn;
  131.     FShadeColors: TfcShadeColors;
  132.     FShadeStyle: TfcShadeStyle;  // Published
  133.     FShowFocusRect: Boolean;
  134.     FSpacing: Integer;
  135.     FStyle: TButtonStyle;
  136.     FTextOptions: TfcCaptionText;
  137.     {$ifdef fcDelphi4Up}
  138.     FSmoothFont: boolean;
  139.     {$endif}
  140.     FGlyphRect: TRect;
  141.     FTextRect: TRect;
  142.     FOnMouseEnter: TNotifyEvent;
  143.     FOnMouseLeave: TNotifyEvent;
  144.     FOnSelChange: TNotifyEvent;
  145.     FOnSetName: TNotifyEvent;
  146.     FCanvas: TCanvas;
  147.     FOffsets: TfcOffsets;
  148.     FModifiedGlyph: Boolean;
  149.     FOptions: TfcButtonOptions;
  150.     FChangeLinks: TList;
  151.     FChangeLink: TfcChangeLink;
  152.     FClicked: Boolean;
  153.     FInitialDown: Boolean;
  154.     FEvents: TStringList;
  155.     FUseHalftonePalette: boolean;
  156.     FShowDownAsUp:boolean;
  157.     FHot: boolean;
  158.     FDataLink: TFieldDataLink;
  159.     FDisableThemes: boolean;
  160.     FStaticCaption: boolean;
  161.     // Property Access Methods
  162.     function GetKind: TBitBtnKind;
  163.     procedure SetAllowAllUp(Value: Boolean);
  164.     procedure SetButtonDown(Value: Boolean; CheckAllowAllUp: Boolean; DoUpdateExclusive: Boolean; DoInvalidate: Boolean);
  165.     procedure SetDefault(Value: Boolean);
  166.     procedure SetDown(Value: Boolean);
  167.     procedure SetGlyph(Value: TBitmap);
  168.     procedure SetGroupIndex(Value: Integer);
  169.     procedure SetKind(Value: TBitBtnKind);
  170.     procedure SetLayout(Value: TButtonLayout);
  171.     procedure SetMargin(Value: Integer);
  172.     procedure SetNumGlyphs(Value: TNumGlyphs);
  173.     procedure SetOptions(Value: TfcButtonOptions);
  174.     procedure SetSpacing(Value: Integer);
  175.     procedure SetShadeStyle(Value: TfcShadeStyle);
  176.     procedure SetStyle(Value: TButtonStyle);
  177.     // Message Handlers
  178.     procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE;
  179.     procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK;
  180.     procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
  181.     procedure CMButtonPressed(var Message: TMessage); message CM_BUTTONPRESSED;
  182.     procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
  183.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  184.     procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
  185.     procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  186.     procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  187.     procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
  188.     procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
  189.     procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  190.     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  191.     procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE;
  192.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  193.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  194.     procedure ProcessMouseUp(X, Y: Integer; AMouseInControl: Boolean; AClicked: Boolean);
  195.     procedure ProcessMouseDown;
  196.     function GetDataField: string;
  197.     function GetDataSource: TDataSource;
  198.     procedure SetDataField(const Value: string);
  199.     procedure SetDataSource(Value: TDataSource);
  200.   protected
  201.     FDownRegionData: TfcRegionData;
  202.     FRegionData: TfcRegionData;
  203.     FSelected: Boolean;
  204.     DisableButton: boolean;
  205.     function GetField: TField;
  206.     function GetDBCaption: string; virtual;
  207. //    procedure SetCaption(val: string); virtual;
  208.     // Overriden Methods
  209.     function GetPalette: HPALETTE; override;
  210.     {$ifdef fcDelphi4Up}
  211.     procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
  212.     {$endif}
  213.     procedure AssignTo(Dest: TPersistent); override;
  214.     procedure CreateParams(var Params: TCreateParams); override;
  215.     procedure CreateWnd; override;
  216.     procedure DestroyWnd; override;
  217.     procedure DefineProperties(Filer: TFiler); override;
  218.     procedure Loaded; override;
  219.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  220.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  221.       X, Y: Integer); override;
  222.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  223.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  224.       X, Y: Integer); override;
  225.     procedure SetName(const Value: TComponentName); override;
  226.     // Virtual Methods
  227.     procedure GetEvents(const s: string);
  228.     function CreateOffsets: TfcOffsets; virtual;
  229.     function CreateRegion(DoImplementation: Boolean; Down: Boolean): HRgn; virtual;
  230.     function CalcButtonLayout(Canvas: TCanvas; Client: TRect; var TextRect: TRect;
  231.       var GlyphRect: TRect; TextSize: TSize): TRect; virtual;
  232.     function GlyphWidth: Integer; virtual;
  233.     function IsCustom: Boolean; virtual;
  234.     function IsCustomCaption: Boolean; virtual;
  235.     function MouseInControl(X, Y: Integer; AndClicked: Boolean): Boolean;
  236.     function StoreRegionData: Boolean; virtual;
  237.     procedure ChangeButtonDown; virtual;
  238.     procedure CleanUp; virtual;
  239.     procedure ClearRegion(ARgnData: PfcRegionData); virtual;
  240.     procedure DrawButtonGlyph(Canvas: TCanvas; const GlyphPos: TPoint); virtual;
  241.     procedure DrawButtonText(Canvas: TCanvas; TextBounds: TRect); virtual;
  242.     procedure DrawItem(const DrawItemStruct: TDrawItemStruct); virtual;
  243.     procedure GetDrawBitmap(DrawBitmap: TfcBitmap; ForRegion: Boolean;
  244.       ShadeStyle: TfcShadeStyle; Down: Boolean); virtual;
  245.     procedure GlyphChanged(Sender: TObject); virtual;
  246.     procedure NotifyChange; virtual;
  247.     procedure NotifyChanging; virtual;
  248.     procedure NotifyLoaded; virtual;
  249.     procedure Paint; virtual;
  250.     procedure Redraw; virtual;
  251.     procedure ReadRegionData(Stream: TStream); virtual;
  252.     procedure ReadDownRegionData(Stream: TStream); virtual;
  253.     procedure SaveRegion(NewRegion: Longword; Down: Boolean); virtual;
  254.     procedure SelChange; virtual;
  255. //    procedure WriteState(Writer: TWriter); override;
  256.     procedure WndProc(var Message: TMessage); override;
  257.     procedure WriteRegionData(Stream: TStream); virtual;
  258.     procedure WriteDownRegionData(Stream: TStream); virtual;
  259.     procedure UpdateExclusive; virtual;
  260.     function UseRegions: boolean; virtual;
  261.     // Protected Properties
  262.     property Active: Boolean read FActive;
  263.     property Canvas: TCanvas read FCanvas;
  264.     property GlyphRect: TRect read FGlyphRect;
  265.     property TextRect: TRect read FTextRect;
  266.     property InitalDown: Boolean read FInitialDown;
  267.     property Clicked: Boolean read FClicked;
  268.     procedure DataChange(Sender: TObject); virtual;
  269.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  270.   public
  271.     BasePatch: Variant;
  272.     property Region: HRGN read FRegion;
  273.     constructor Create(AOwner: TComponent); override;
  274.     destructor Destroy; override;
  275.     // Virtual Methods
  276.     procedure ApplyRegion; virtual;
  277.     procedure InvalidateNotRegion(const Erase: Boolean); virtual;
  278.     function Draw(Canvas: TCanvas): TRect; virtual;
  279.     function IsMultipleRegions: Boolean; virtual;
  280.     procedure Click; override;
  281.     procedure SizeToDefault; virtual;
  282.     procedure UpdateShadeColors(Color: TColor); virtual;
  283.     procedure RegisterChanges(Value: TfcChangeLink); virtual;
  284.     procedure UnRegisterChanges(Value: TfcChangeLink); virtual;
  285.     function GetTextEnabled: Boolean; virtual;
  286.     procedure AdjustBounds; virtual;
  287.     // Public Properties
  288.     property ShowDownAsUp: Boolean read FShowDownAsUp write FShowDownAsUp default False;
  289.     property StaticCaption: boolean read FStaticCaption write FStaticCaption default False;
  290.     property AllowAllUp: Boolean read FAllowAllUp write SetAllowAllUp default False;
  291.     property Cancel: Boolean read FCancel write FCancel default False;
  292.     property Caption {: string read GetCaption write SetCaption }stored IsCustomCaption;
  293.     property Color;
  294.     property Default: Boolean read FDefault write SetDefault default False;
  295.     property Down: Boolean read FDown write SetDown default False;
  296.     property Font;
  297.     property Offsets: TfcOffsets read FOffsets write FOffsets;
  298.     property Glyph: TBitmap read FGlyph write SetGlyph stored IsCustom;
  299.     property GroupIndex: Integer read FGroupIndex write SetGroupIndex default 0;
  300.     property Kind: TBitBtnKind read GetKind write SetKind default bkCustom;
  301.     property Layout: TButtonLayout read FLayout write SetLayout default blGlyphLeft;
  302.     property Margin: Integer read FMargin write SetMargin default -1;
  303.     property ModalResult: TModalResult read FModalResult write FModalResult default 0;
  304.     property NumGlyphs: TNumGlyphs read FNumGlyphs write SetNumGlyphs stored IsCustom default 1;
  305.     property Options: TfcButtonOptions read FOptions write SetOptions default [];
  306.     property Selected: Boolean read FSelected;
  307.     property ShadeColors: TfcShadeColors read FShadeColors write FShadeColors;
  308.     property ShadeStyle: TfcShadeStyle read FShadeStyle write SetShadeStyle;
  309.     {$ifdef fcDelphi4Up}
  310.     property SmoothFont: boolean read FSmoothFont write FSmoothFont default false;
  311.     {$endif}
  312.     property Style: TButtonStyle read FStyle write SetStyle default bsAutoDetect;
  313.     property Spacing: Integer read FSpacing write SetSpacing default 4;
  314.     property TabStop; // 8/18/00 - Remove default as inconsistent with constructor
  315.     property TextOptions: TfcCaptionText read FTextOptions write FTextOptions;
  316.     property OnClick;
  317.     property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
  318.     property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  319.     property OnSelChange: TNotifyEvent read FOnSelChange write FOnSelChange;
  320.     property OnSetName: TNotifyEvent read FOnSetName write FOnSetName;
  321.     property UseHalftonePalette: Boolean read FUseHalftonePalette write FUseHalftonePalette;
  322.     property Hot : boolean read FHot write FHot;
  323.     property DataField: string read GetDataField write SetDataField;
  324.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  325.     property DataLink: TFieldDataLink read FDataLink;
  326.     property Field: TField read GetField;
  327.     property DisableThemes : boolean read FDisableThemes write FDisableThemes default False;
  328.   end;
  329. implementation
  330. {$r fcButtns.RES}
  331. const
  332.   BITBTNMODALRESULTS: array[TBitBtnKind] of TModalResult = (
  333.     0, mrOk, mrCancel, 0, mrYes, mrNo, 0, mrAbort, mrRetry, mrIgnore,
  334.     mrAll);
  335. var
  336.   BitBtnResNames: array[TBitBtnKind] of PChar = (
  337.     nil, 'WWOK', 'WWCANCEL', 'WWHELP', 'WWYES', 'WWNO', 'WWCLOSE',
  338.     'WWABORT', 'WWRETRY', 'WWIGNORE', 'WWALL');
  339.   BitBtnCaptions: array[TBitBtnKind] of Pointer = (nil, nil, nil,
  340.     nil, nil, nil, nil, nil, nil, nil, nil);
  341.   BitBtnGlyphs: array[TBitBtnKind] of TBitmap;
  342. procedure GetBitBtnGlyph(Kind: TBitBtnKind; Bitmap: TBitmap);
  343. begin
  344.   if BitBtnGlyphs[Kind] = nil then
  345.   begin
  346.     BitBtnGlyphs[Kind] := TBitmap.Create;
  347.     BitBtnGlyphs[Kind].LoadFromResourceName(HInstance, BitBtnResNames[Kind]);
  348.   end;
  349.   Bitmap.Assign(BitBtnGlyphs[Kind]);
  350. end;
  351. // TfcDownOffsets
  352. constructor TfcOffsets.Create(Button: TfcCustomBitBtn);
  353. begin
  354.   inherited Create;
  355.   FControl := Button;
  356.   FTextDownX := 1;
  357.   FTextDownY := 1;
  358. end;
  359. procedure TfcOffsets.AssignTo(Dest: TPersistent);
  360. begin
  361.   if Dest is TfcOffsets then
  362.     with Dest as TfcOffsets do
  363.   begin
  364.     GlyphX := self.GlyphX;
  365.     GlyphY := self.GlyphY;
  366.     TextX := self.TextX;
  367.     TextY := self.TextY;
  368.     TextDownX := self.TextDownX;
  369.     TextDownY := self.TextDownY;
  370.   end else inherited;
  371. end;
  372. procedure TfcOffsets.SetGlyphX(Value: Integer);
  373. begin
  374.   if FGlyphX <> Value then
  375.   begin
  376.     FGlyphX := Value;
  377.     Control.Invalidate;
  378.   end;
  379. end;
  380. procedure TfcOffsets.SetGlyphY(Value: Integer);
  381. begin
  382.   if FGlyphY <> Value then
  383.   begin
  384.     FGlyphY := Value;
  385.     Control.Invalidate;
  386.   end;
  387. end;
  388. procedure TfcOffsets.SetTextX(Value: Integer);
  389. begin
  390.   if FTextX <> Value then
  391.   begin
  392.     FTextX := Value;
  393.     Control.Invalidate;
  394.   end;
  395. end;
  396. procedure TfcOffsets.SetTextY(Value: Integer);
  397. begin
  398.   if FTextY <> Value then
  399.   begin
  400.     FTextY := Value;
  401.     Control.Invalidate;
  402.   end;
  403. end;
  404. // TfcShadeColors
  405. constructor TfcShadeColors.Create(Button: TfcCustomBitBtn);
  406. begin
  407.   inherited Create;
  408.   FButton := Button;
  409.   FBtnHighlight := clBtnHighlight;
  410.   FBtn3DLight := cl3DLight;
  411.   FBtnShadow := clBtnShadow;
  412. end;
  413. procedure TfcShadeColors.AssignTo(Dest: TPersistent);
  414. begin
  415.   if Dest is TfcShadeColors then
  416.     with Dest as TfcShadeColors do
  417.   begin
  418.     Btn3dLight := self.Btn3dLight;
  419.     BtnHighlight := self.BtnHighlight;
  420.     BtnShadow := self.BtnShadow;
  421.     BtnBlack := self.BtnBlack;
  422.     BtnFocus := self.BtnFocus;
  423.     Shadow := self.Shadow;
  424.   end else inherited;
  425. end;
  426. procedure TfcShadeColors.SetBtn3DLight(Value: TColor);
  427. begin
  428.   if Value <> FBtn3DLight then
  429.   begin
  430.     FBtn3DLight := Value;
  431.     FButton.Invalidate;
  432.   end;
  433. end;
  434. procedure TfcShadeColors.SetBtnBlack(Value: TColor);
  435. begin
  436.   if FBtnBlack <> Value then
  437.   begin
  438.     FBtnBlack := Value;
  439.     FButton.Invalidate;
  440.   end;
  441. end;
  442. procedure TfcShadeColors.SetBtnHighlight(Value: TColor);
  443. begin
  444.   if Value <> FBtnHighlight then
  445.   begin
  446.     FBtnHighlight := Value;
  447.     FButton.Invalidate;
  448.   end;
  449. end;
  450. procedure TfcShadeColors.SetBtnShadow(Value: TColor);
  451. begin
  452.   if Value <> FBtnShadow then
  453.   begin
  454.     FBtnShadow := Value;
  455.     FButton.Invalidate;
  456.   end;
  457. end;
  458. procedure TfcShadeColors.SetBtnFocus(Value: TColor);
  459. begin
  460.   if Value <> FBtnFocus then
  461.   begin
  462.     FBtnFocus := Value;
  463.     FButton.Invalidate;
  464.   end;
  465. end;
  466. procedure TfcShadeColors.SetShadow(Value: TColor);
  467. begin
  468.   if FShadow <> Value then
  469.   begin
  470.     FShadow := Value;
  471.     FButton.Invalidate;
  472.   end;
  473. end;
  474. // TfcCustomBitBtn
  475. function TfcCustomBitBtn.GetTextEnabled: Boolean;
  476. begin
  477.   result := Enabled;
  478. end;
  479. procedure TfcCustomBitBtn.AdjustBounds;
  480. begin
  481. end;
  482. constructor TfcCustomBitBtn.Create(AOwner: TComponent);
  483. begin
  484.   inherited Create(AOwner);
  485.   ControlStyle := [csSetCaption, csOpaque, csReflector];
  486.   FShowDownAsUp:=False;
  487.   FCanvas := TCanvas.Create;
  488.   FChangeLinks := TList.Create;
  489.   Color := clBtnFace;
  490.   FChangeLink := TfcChangeLink.Create;
  491.   FGlyph := TBitmap.Create;
  492.   FGlyph.OnChange := GlyphChanged;
  493.   Height := 25;
  494.   FKind := bkCustom;
  495.   FLayout := blGlyphLeft;
  496.   FMargin := -1;
  497.   FOffsets := CreateOffsets;
  498.   FShadeColors := TfcShadeColors.Create(self);
  499.   FShowFocusRect := True;
  500.   FSpacing := 4;
  501.   FShadeStyle := fbsNormal;
  502.   FStyle := bsAutoDetect;
  503.   TabStop := True;
  504.   FTextOptions := TfcCaptionText.Create(MakeCallbacks(Invalidate, AdjustBounds, GetTextEnabled),
  505.     FCanvas, Font);
  506.   FTextOptions.Alignment := taCenter;
  507.   FTextOptions.VAlignment := vaVCenter;
  508.   FEvents := TStringList.Create;
  509.   Width := 75;
  510.   BasePatch:= VarArrayCreate([0, 1], varVariant);
  511.   BasePatch[0]:= False; { 6/8/99 - Internal use to support painting issues with flat buttons }
  512.   BasePatch[1]:= False; { 6/19/2000 - PYW - Internal use to solve MouseDown problems with nonfocus buttons.  Set to True to preserve old behavior.}
  513.   FUseHalftonePalette:= False;
  514.   FDataLink := TFieldDataLink.Create;
  515.   FDataLink.Control := Self;
  516.   FDataLink.OnDataChange := DataChange;
  517. end;
  518. destructor TfcCustomBitBtn.Destroy;
  519. begin
  520.   FDataLink.OnDataChange := nil;
  521.   FDataLink.Free;
  522.   FDataLink := nil;
  523.   CleanUp;
  524.   if FRegionData.rgnData <> nil then FreeMem(FRegionData.rgnData);
  525.   if FDownRegionData.rgnData <> nil then FreeMem(FDownRegionData.rgnData);
  526.   FCanvas.Free;
  527.   FChangeLinks.Free;
  528.   FChangeLinks:= nil;
  529.   FChangeLink.Free;
  530.   FGlyph.Free;
  531.   FOffsets.Free;
  532.   FShadeColors.Free;
  533.   FTextOptions.Free;
  534.   FEvents.Free;
  535.   inherited Destroy;
  536. end;
  537. procedure TfcCustomBitBtn.CleanUp;
  538. begin
  539.   if FRegion <> 0 then
  540.   begin
  541.     if not (csDestroying in ComponentState) and HandleAllocated then SetWindowRgn(Handle, 0, False);
  542.     DeleteObject(FRegion);
  543.     DeleteObject(FLastRegion);
  544.     FRegion := 0;
  545.     FLastRegion := 0;
  546.   end;
  547. end;
  548. //{$ifdef fcDelphi4Up}
  549. //type TFormDesigner = IFormDesigner;
  550. //{$endif}
  551. procedure TfcCustomBitBtn.WndProc(var Message: TMessage);
  552. var
  553. //    Selections: TComponentList;
  554. //    SelPosition: Integer;
  555.     ButtonGroup: TWinControl;
  556. {  function IsSelected: Boolean;
  557.   var CompList: TComponentList;
  558.       i: Integer;
  559.   begin
  560.     CompList := TComponentList.Create;
  561.     TFormDesigner(GetParentForm(ButtonGroup).Designer).GetSelections(CompList);
  562.     result := False;
  563.     for i := 0 to CompList.Count - 1 do if Selections[i] = self then
  564.       result := True;
  565.     CompList.Free;
  566.   end;
  567.   function InList: Integer;
  568.   var i: Integer;
  569.   begin
  570.     for i := 0 to Selections.Count - 1 do if Selections[i] = ButtonGroup then
  571.     begin
  572.       result := i;
  573.       Exit;
  574.     end;
  575.     result := -1;
  576.   end;
  577.   procedure RemoveButtonGroup;
  578.   var NewSelections: TComponentList;
  579.       i: Integer;
  580.   begin
  581.     NewSelections := TComponentList.Create;
  582.     for i := 0 to Selections.Count - 1 do
  583.       if i <> SelPosition then NewSelections.Add(Selections[i]);
  584.     Selections.Free;
  585.     Selections := NewSelections;
  586.   end;}
  587. begin
  588.   if (csDesigning in ComponentState) and (Parent <> nil) and fcIsClass(Parent.ClassType, 'TfcCustomButtonGroup') then
  589.   begin
  590.     ButtonGroup := Parent;
  591.     case Message.Msg of
  592.       // If the user right-clicks on the control then
  593.       // this code will select the buttonGroup (instead of
  594.       // having this button be selected) and then pass the
  595.       // message along to the ButtonGroup.
  596.       WM_RBUTTONDOWN: begin
  597.         ButtonGroup.Perform(WM_LBUTTONDOWN, Message.wParam, MakeLParam(LoWord(Message.lParam) + Left, HiWord(Message.lParam) + Top));
  598.         ButtonGroup.Dispatch(Message);
  599.       end;
  600. {      WM_RBUTTONDOWN: begin
  601.         TFormDesigner(GetParentForm(ButtonGroup).Designer).SelectComponent(ButtonGroup);
  602.         ButtonGroup.Dispatch(Message);
  603.       end;
  604. }
  605.       WM_LBUTTONDOWN: begin
  606.         if (GetKeyState(DESIGN_KEY) < 0) then
  607.           inherited
  608.         else begin
  609.             ButtonGroup.Dispatch(Message);
  610.             ButtonGroup.Perform(Message.Msg, Message.wParam, MakeLParam(LoWord(Message.lParam) + Left, HiWord(Message.lParam) + Top));
  611.             { 2/21/99 -ksw - LockedWindow fix }
  612.             if GetCapture = ButtonGroup.Handle then ReleaseCapture;
  613.         end
  614.       end;
  615.       // Prevent the default ComponentEditor to occur if
  616.       // the space key isn't pressed down. -ksw (6/24/98)
  617.       WM_LBUTTONDBLCLK:
  618.         if (GetKeyState(DESIGN_KEY) < 0) then
  619.           inherited
  620.         else begin
  621.           // This line is a tweak that prevents an annoyance
  622.           // in which after double-clicking on the Navigator,
  623.           // clicking again would move attempt to move it, event
  624.           // if you weren't clicking in the navigator.  -ksw (6/24/98)
  625.           ButtonGroup.Perform(WM_LBUTTONDOWN, Message.wParam, MakeLParam(LoWord(Message.lParam) + Left, HiWord(Message.lParam) + Top));
  626.           // These other two lines need to go together.  If the second line is called
  627.           // without the call to the first, Delphi will exit out rather
  628.           // ungracefully.  If the first one is called without the call to the
  629.           // second one, the double-click isn't processed by Delphi.
  630.           ButtonGroup.Dispatch(Message);
  631.           ButtonGroup.Perform(Message.Msg, Message.wParam, Message.lParam);
  632.         end;
  633.       else inherited;
  634.     end;
  635.   end else inherited;
  636. end;
  637. procedure TfcCustomBitBtn.AssignTo(Dest: TPersistent);
  638. begin
  639.   if Dest is TfcCustomBitBtn then
  640.     with Dest as TfcCustomBitBtn do
  641.   begin
  642.     Color := self.Color;
  643.     Offsets.Assign(self.Offsets);
  644. //    Glyph := self.Glyph;
  645.     Layout := self.Layout;
  646.     Margin := self.Margin;
  647.     NumGlyphs := self.NumGlyphs;
  648.     Options := self.Options;
  649.     ShadeColors.Assign(self.ShadeColors);
  650.     Spacing := self.Spacing;
  651.     TabStop := self.TabStop;
  652.     TextOptions.Assign(self.TextOptions);
  653.   end else inherited;
  654. end;
  655. procedure TfcCustomBitBtn.CreateParams(var Params: TCreateParams);
  656. const
  657.   ButtonStyles: array[Boolean] of UINT = (BS_PUSHBUTTON, BS_DEFPUSHBUTTON);
  658. begin
  659.   inherited CreateParams(Params);
  660.   CreateSubClass(Params, 'BUTTON');
  661. //  Params.Style := Params.Style or ButtonStyles[FDefault];
  662.   with Params do Style := Style or BS_OWNERDRAW;
  663. end;
  664. procedure TfcCustomBitBtn.Createwnd;
  665. begin
  666.   inherited;
  667.   FActive := FDefault;
  668.   ApplyRegion;
  669. end;
  670. procedure TfcCustomBitBtn.DestroyWnd;
  671. begin
  672.   CleanUp;
  673.   inherited;
  674. end;
  675. procedure TfcCustomBitBtn.DefineProperties(Filer: TFiler);
  676. begin
  677.   inherited;
  678.   Filer.DefineBinaryProperty('RegionData', ReadRegionData, WriteRegionData, StoreRegionData);
  679.   Filer.DefineBinaryProperty('DownRegionData', ReadDownRegionData, WriteDownRegionData, StoreRegionData);
  680. end;
  681. function TfcCustomBitBtn.GetPalette: HPALETTE;
  682. begin
  683.   result := Glyph.Palette;
  684. end;
  685. function TfcCustomBitBtn.CreateOffsets: TfcOffsets;
  686. begin
  687.   result := TfcOffsets.Create(self);
  688. end;
  689. function TfcCustomBitBtn.Draw(Canvas: TCanvas): TRect;
  690. var
  691.   TextSize: TSize;
  692.   r: TRect;
  693. //  Details: TThemedElementDetails;
  694. begin
  695. {  if ThemeServices.ThemesEnabled then
  696.   begin
  697.      if MouseInControl(-1, -1, False) then
  698.        Details := ThemeServices.GetElementDetails(tbPushButtonHot)
  699.      else
  700.        Details := ThemeServices.GetElementDetails(tbPushButtonNormal);
  701.      r:= Rect(-1, -1, Width+2, Height+2);
  702.      ThemeServices.DrawElement(Canvas.Handle, Details, r);
  703.   end;
  704. }
  705.   result := ClientRect;
  706.   InflateRect(result, -2, -2);
  707.   TextOptions.Canvas := Canvas;
  708.   TextOptions.Text := GetDBCaption;
  709.   TextOptions.TextRect := result;
  710.   with TextOptions.CalcDrawRect(True) do
  711.     TextSize := fcSize(Right - Left, Bottom - Top);
  712.   CalcButtonLayout(Canvas, result, FTextRect, FGlyphRect, TextSize);
  713.   with FTextRect do FTextRect := Rect(
  714.     fcMax(0, Left), fcMax(0, Top), fcMin(ClientWidth, Right), fcMin(ClientHeight, Bottom));
  715.   if not Glyph.Empty then DrawButtonGlyph(Canvas, FGlyphRect.TopLeft);
  716.   DrawButtonText(Canvas, FTextRect);
  717.   if (boFocusRect in Options) and (boFocusable in Options) and Focused then
  718.   begin
  719.     UnionRect(r, TextRect, GlyphRect);
  720.     InflateRect(r, 2, 2);
  721.     Canvas.Brush.Color := clWhite;
  722.     Canvas.Font.Color := clBlack;
  723.     Canvas.DrawFocusRect(r);
  724.   end;
  725. end;
  726. function TfcCustomBitBtn.CalcButtonLayout(Canvas: TCanvas; Client: TRect;
  727.   var TextRect: TRect; var GlyphRect: TRect; TextSize: TSize): TRect;
  728. var GlyphSize: TSize;
  729.     TopLeft: TPoint;
  730.     Spacing: Integer;
  731.     EffectiveMargin: Integer;
  732.     DownFlag:boolean;
  733. begin
  734.   DownFlag := Down and not (csPaintCopy in ControlState); // 6/17/02
  735.   if ShowDownAsUp then begin
  736.      if Down then DownFlag := False;
  737.      if FClicked and MouseInControl(-1,-1,False) and not Selected then
  738.         DownFlag := True;
  739.   end;
  740.   InflateRect(Client, -Margin, -Margin);
  741.   if Margin = -1 then EffectiveMargin := 4 else EffectiveMargin := Margin;
  742.   SetRectEmpty(GlyphRect);
  743.   GlyphSize := fcSize(0, 0);
  744.   if not Glyph.Empty then GlyphSize := fcSize(GlyphWidth, Glyph.Height);
  745.   Spacing := 0;
  746.   if (GetDBCaption <> '') and (not Glyph.Empty) then Spacing := self.Spacing;
  747.   case TextOptions.Alignment of
  748.     taLeftJustify: TopLeft := Point(EffectiveMargin + (TextSize.cx + GlyphSize.cx + Spacing) div 2, Height div 2);
  749.     taRightJustify: TopLeft := Point(-EffectiveMargin + Width - (TextSize.cx + GlyphSize.cx + Spacing) div 2, Height div 2);
  750.     taCenter: TopLeft := Point(Width div 2, Height div 2);
  751.   end;
  752.   fcCalcButtonLayout(TopLeft, @TextRect, @GlyphRect, TextSize, GlyphSize, Layout, Spacing);
  753.   OffsetRect(TextRect, Offsets.TextX, Offsets.TextY);
  754.   OffsetRect(GlyphRect, Offsets.GlyphX, Offsets.GlyphY);
  755.   // Offset if down
  756.   if DownFlag then
  757.   begin
  758.     OffsetRect(TextRect, Offsets.TextDownX, Offsets.TextDownY);
  759.     OffsetRect(GlyphRect, Offsets.TextDownX, Offsets.TextDownY);
  760.   end;
  761.   result := Client;
  762. end;
  763. procedure TfcCustomBitBtn.ReadRegionData(Stream: TStream);
  764. begin
  765.   Stream.ReadBuffer(FRegionData.dwSize, SizeOf(FRegionData.dwSize));
  766.   if FRegionData.dwSize <> 0 then
  767.   begin
  768.     GetMem(FRegionData.rgnData, FRegionData.dwSize);
  769.     Stream.ReadBuffer(FRegionData.rgnData^, FRegionData.dwSize);
  770.   end;
  771. end;
  772. procedure TfcCustomBitBtn.ReadDownRegionData(Stream: TStream);
  773. begin
  774.   Stream.ReadBuffer(FDownRegionData.dwSize, SizeOf(FDownRegionData.dwSize));
  775.   if FDownRegionData.dwSize <> 0 then
  776.   begin
  777.     GetMem(FDownRegionData.rgnData, FDownRegionData.dwSize);
  778.     Stream.ReadBuffer(FDownRegionData.rgnData^, FDownRegionData.dwSize);
  779.   end;
  780. end;
  781. procedure TfcCustomBitBtn.WriteRegionData(Stream: TStream);
  782. begin
  783.   if FRegionData.rgnData <> nil then
  784.   begin
  785.     Stream.WriteBuffer(FRegionData.dwSize, SizeOf(FRegionData.dwSize));
  786.     Stream.WriteBuffer(FRegionData.rgnData^, FRegionData.dwSize);
  787.   end else begin
  788.     FRegionData.dwSize := 0;
  789.     Stream.WriteBuffer(FRegionData.dwSize, SizeOf(FRegionData.dwSize));
  790.   end;
  791. end;
  792. procedure TfcCustomBitBtn.WriteDownRegionData(Stream: TStream);
  793. begin
  794.   if FDownRegionData.rgnData <> nil then
  795.   begin
  796.     Stream.WriteBuffer(FDownRegionData.dwSize, SizeOf(FDownRegionData.dwSize));
  797.     Stream.WriteBuffer(FDownRegionData.rgnData^, FDownRegionData.dwSize);
  798.   end else begin
  799.     FDownRegionData.dwSize := 0;
  800.     Stream.WriteBuffer(FDownRegionData.dwSize, SizeOf(FDownRegionData.dwSize));
  801.   end;
  802. end;
  803. procedure TfcCustomBitBtn.ApplyRegion;
  804. var CurParent: TWinControl;
  805.     DownFlag:Boolean;
  806. begin
  807.   if not HandleAllocated then Exit;
  808.   if not UseRegions then exit;
  809.   DownFlag := Down and not (csPaintCopy in ControlState); // 6/17/02
  810.   if ShowDownAsUp then begin
  811.      if Down then DownFlag := False;
  812.      if FClicked and MouseInControl(-1,-1,False) and not Selected then
  813.         DownFlag := True;
  814.   end;
  815.   SetWindowRgn(Handle, 0, False);
  816.   if FRegion <> 0 then DeleteObject(FRegion);
  817.   FRegion := CreateRegion(True, DownFlag);
  818.   if (FLastRegion <> 0) and (FRegion <> 0) and IsMultipleRegions then
  819.   begin
  820.     CombineRgn(FLastRegion, FLastRegion, FRegion, RGN_XOR);
  821.     CurParent := self;
  822.     while (CurParent <> GetParentForm(self)) and (CurParent <> nil) do
  823.     begin
  824.       OffsetRgn(FLastRegion, CurParent.Left, CurParent.Top);
  825.       InvalidateRgn(CurParent.Parent.Handle, FLastRegion, True);
  826.       CurParent := CurParent.Parent;
  827.     end;
  828.   end;
  829.   if IsMultipleRegions then
  830.   begin
  831.     if FLastRegion <> 0 then DeleteObject(FLastRegion);
  832.     FLastRegion := CreateRectRgn(0, 0, 10, 10);
  833.     CombineRgn(FLastRegion, FRegion, 0, RGN_COPY);
  834.   end;
  835.   SetWindowRgn(Handle, FRegion, False);
  836.   if IsMultipleRegions and (Parent <> nil) then fcInvalidateOverlappedWindows(Parent.Handle, Handle);
  837. end;
  838. procedure TfcCustomBitBtn.ChangeButtonDown;
  839. begin
  840.   if IsMultipleRegions then ApplyRegion;
  841. end;
  842. procedure TfcCustomBitBtn.GetEvents(const s: string);
  843. begin
  844.   FEvents.Add(s);
  845. end;
  846. {
  847. procedure TfcCustomBitBtn.WriteState(Writer: TWriter);
  848. var
  849.     FormDesigner: IFormDesigner;
  850.     s: string;
  851. begin
  852.   if (csDesigning in ComponentState) and (GetParentForm(self) <> nil) and not (Owner is TCustomForm) then
  853.   begin
  854.     FormDesigner := IFormDesigner(GetParentForm(self).Designer);
  855.     FEvents.Clear;
  856.     FormDesigner.GetMethods(GetTypeData(TypeInfo(TNotifyEvent)), GetEvents);
  857.     s := FormDesigner.GetMethodName(TMethod(OnClick));
  858.     if FEvents.IndexOf(s) = -1 then OnClick := nil;
  859.   end;
  860.   inherited;
  861. end;
  862. }
  863. procedure TfcCustomBitBtn.SelChange;
  864. begin
  865.   FSelected := Down;
  866.   if Assigned(FOnSelChange) then FOnSelChange(self);
  867.   NotifyChange;
  868. end;
  869. procedure TfcCustomBitBtn.SaveRegion(NewRegion: Longword; Down: Boolean);
  870. var ARgnData: ^TfcRegionData;
  871. begin
  872.   if not Down then ARgnData := @FRegionData else ARgnData := @FDownRegionData;
  873.   if ARgnData^.rgnData <> nil then FreeMem(ARgnData^.rgnData);
  874.   ARgnData^.rgnData := nil;
  875.   ARgnData^.dwSize := GetRegionData(NewRegion, 0, nil);
  876.   GetMem(ARgnData^.rgnData, ARgnData^.dwSize);
  877.   GetRegionData(NewRegion, ARgnData^.dwSize, ARgnData^.rgnData);
  878. end;
  879. function TfcCustomBitBtn.CreateRegion(DoImplementation: Boolean; Down: Boolean): HRgn;
  880. var ARgnData: PRgnData;
  881. begin
  882.   if (not Down and (FRegionData.rgnData <> nil)) or (Down and (FDownRegionData.rgnData <> nil)) then
  883.   begin
  884.     if Down then ARgnData := FDownRegionData.rgnData else ARgnData := FRegionData.rgnData;
  885.     result := ExtCreateRegion(nil, ARgnData.rdh.dwSize + ARgnData.rdh.nRgnSize, ARgnData^);
  886.   end else result := 0;
  887. end;
  888. procedure TfcCustomBitBtn.ClearRegion(ARgnData: PfcRegionData);
  889. begin
  890.   if ARgnData^.rgnData <> nil then
  891.   begin
  892.     FreeMem(ARgnData^.rgnData);
  893.     ARgnData^.rgnData := nil;
  894.   end;
  895. end;
  896. procedure TfcCustomBitBtn.DrawButtonGlyph(Canvas: TCanvas; const GlyphPos: TPoint);
  897. var
  898.   ImageList: TImageList;
  899.   TempGlyph: TBitmap;
  900.   Offset: Integer;
  901.   DownFlag:Boolean;
  902. begin
  903.   Offset := 0;
  904.   DownFlag := Down and not (csPaintCopy in ControlState); // 6/17/02
  905.   if ShowDownAsUp then begin
  906.      if Down then DownFlag := False;
  907.      if FClicked and MouseInControl(-1,-1,False) and not Selected then
  908.         DownFlag := True;
  909.   end;
  910.   if not Enabled and (NumGlyphs > 1) then Offset := GlyphWidth
  911.   else if Downflag and (NumGlyphs > 2) then Offset := 2 * GlyphWidth
  912.   else if MouseInControl(-1, -1, False) and (NumGlyphs > 3) then Offset := 3 * GlyphWidth;
  913.   ImageList := TImageList.Create(self);
  914. // RSW - 7/6/00 - Resolve redline problem with some environments
  915.   if ((Enabled) or (NumGlyphs > 1)) and odd(GlyphPos.x) then
  916.     ImageList.Width := GlyphWidth+1
  917.   else
  918.     ImageList.Width := GlyphWidth;
  919.   ImageList.Height := Glyph.Height;
  920.   TempGlyph := TBitmap.Create;
  921.   try
  922.     TempGlyph.Width := ImageList.Width;
  923.     TempGlyph.Height := Glyph.Height;
  924.     if (not Enabled) and (NumGlyphs <= 1) then
  925.     begin
  926.        fcCreateDisabledBitmap(Glyph, TempGlyph);
  927.        TempGlyph.Transparent := True;
  928.        ImageList.AddMasked(TempGlyph, TempGlyph.TransparentColor);
  929.        with GlyphPos do begin
  930.          fcImageListDraw(ImageList, 0, Canvas, x, y, ILD_NORMAL, True)
  931.        end
  932.     end
  933.     else begin
  934.       if odd(GlyphPos.x) then begin
  935.         TempGlyph.Canvas.CopyRect(Rect(0, 0, GlyphWidth, Glyph.Height),
  936.            Glyph.Canvas, Rect(Offset, 0, Offset + GlyphWidth, Glyph.Height));
  937.         TempGlyph.Canvas.Brush.Color:= TempGlyph.TransparentColor;
  938.         TempGlyph.Canvas.FillRect(Rect(0, 0, 1, Glyph.Height));
  939.         TempGlyph.Canvas.CopyRect(Rect(1, 0, GlyphWidth+1, Glyph.Height),
  940.            Glyph.Canvas, Rect(Offset, 0, Offset + GlyphWidth, Glyph.Height));
  941.       end
  942.       else begin
  943.         TempGlyph.Canvas.CopyRect(Rect(0, 0, TempGlyph.Width, TempGlyph.Height),
  944.            Glyph.Canvas, Rect(Offset, 0, Offset + GlyphWidth, Glyph.Height));
  945.       end;
  946.       TempGlyph.Transparent := True;
  947.       ImageList.AddMasked(TempGlyph, TempGlyph.TransparentColor);
  948.       with GlyphPos do begin
  949.         fcImageListDrawFixBug(ImageList, 0, Canvas, x, y, ILD_NORMAL, True)
  950.       end
  951.     end;
  952.   finally
  953.     ImageList.Free;
  954.     TempGlyph.Free;
  955.   end;
  956. end;
  957. procedure TfcCustomBitBtn.DrawButtonText(Canvas: TCanvas; TextBounds: TRect);
  958. begin
  959.   Canvas.Brush.Style := bsClear;
  960.   TextOptions.TextRect := TextBounds;
  961.   TextOptions.Draw;
  962. end;
  963. procedure TfcCustomBitBtn.DrawItem(const DrawItemStruct: TDrawItemStruct);
  964. begin
  965.   if csDestroying in ComponentState then exit;  // 7/2/02 - Exit if destroying
  966.   if ( width < 1 ) or ( height < 1 ) then exit; // 7/3/02 - No space to draw
  967.   FCanvas.Handle := DrawItemStruct.hDC;
  968.   Paint;
  969.   FCanvas.Handle := 0;
  970. end;
  971. procedure TfcCustomBitBtn.GetDrawBitmap(DrawBitmap: TfcBitmap; ForRegion: Boolean;
  972.   ShadeStyle: TfcShadeStyle; Down: Boolean);
  973. begin
  974. end;
  975. procedure TfcCustomBitBtn.GlyphChanged(Sender: TObject);
  976. begin
  977.   Invalidate;
  978. end;
  979. function TfcCustomBitBtn.GlyphWidth: Integer;
  980. begin
  981.   result := Glyph.Width;
  982.   if NumGlyphs <> 0 then
  983.     result := Glyph.Width div NumGlyphs;
  984. end;
  985. function TfcCustomBitBtn.IsMultipleRegions: Boolean;
  986. begin
  987.   result := False;
  988. end;
  989. function TfcCustomBitBtn.StoreRegionData: Boolean;
  990. begin
  991.   result := False;
  992. end;
  993. procedure TfcCustomBitBtn.NotifyLoaded;
  994. var i: Integer;
  995. begin
  996.   for i := 0 to FChangeLinks.Count - 1 do
  997.     with TfcChangeLink(FChangeLinks[i]) do
  998.   begin
  999.     Sender := self;
  1000.     Loaded;
  1001.   end;
  1002. end;
  1003. procedure TfcCustomBitBtn.NotifyChange;
  1004. var i: Integer;
  1005. begin
  1006.   for i := 0 to FChangeLinks.Count - 1 do
  1007.     with TfcChangeLink(FChangeLinks[i]) do
  1008.   begin
  1009.     Sender := self;
  1010.     Change;
  1011.   end;
  1012. end;
  1013. procedure TfcCustomBitBtn.NotifyChanging;
  1014. var i: Integer;
  1015. begin
  1016.   for i := 0 to FChangeLinks.Count - 1 do
  1017.     with TfcChangeLink(FChangeLinks[i]) do
  1018.   begin
  1019.     Sender := self;
  1020.     Changing;
  1021.   end;
  1022. end;
  1023. procedure TfcCustomBitBtn.Paint;
  1024. var DrawBitmap: TfcBitmap;
  1025.     DownFlag:Boolean;
  1026. begin
  1027.   DownFlag := Down and not (csPaintCopy in ControlState); // 6/17/02
  1028.   if ShowDownAsUp then begin
  1029.      if Down then DownFlag := False;
  1030.      if MouseInControl(-1,-1,False) and (not Selected) and (FClicked) then
  1031.         DownFlag := True;
  1032.   end;
  1033.   DrawBitmap := TfcBitmap.Create;
  1034.   DrawBitmap.UseHalftonePalette:= FUseHalftonePalette;
  1035.   try
  1036.     if (ShadeStyle=fbsFlat) and (BasePatch[0]=True) then { 6/8/99 }  {6/2/2000}
  1037.        GetDrawBitmap(DrawBitmap, False, fbsNormal, DownFlag)
  1038.     else
  1039.        GetDrawBitmap(DrawBitmap, False, ShadeStyle, DownFlag);
  1040.     Draw(DrawBitmap.Canvas);
  1041.     Canvas.Draw(0, 0, DrawBitmap);       // Paint TempBitmap to Canvas
  1042.     {$ifdef fcDelphi4Up} { 6/6/99 - Add SmoothFont property }
  1043.     if SmoothFont then begin
  1044.        TextOptions.Canvas:= Canvas;
  1045.        DrawButtonText(Canvas, TextRect); { Repaint text of button }
  1046.     end
  1047.     {$endif}
  1048.   finally
  1049.     DrawBitmap.Free;
  1050.   end;
  1051. end;
  1052. procedure TfcCustomBitBtn.Redraw;
  1053. begin
  1054.   FCanvas.Handle := GetDC(Handle);
  1055.   Paint;
  1056.   ReleaseDC(Handle, FCanvas.Handle);
  1057.   FCanvas.Handle := 0;
  1058. end;
  1059. procedure TfcCustomBitBtn.SetButtonDown(Value: Boolean; CheckAllowAllUp: Boolean; DoUpdateExclusive: Boolean; DoInvalidate: Boolean);
  1060. begin
  1061.   if Value <> FDown then
  1062.   begin
  1063.     FDown := Value;
  1064.     ChangeButtonDown;
  1065.     if FDown then NotifyChanging;
  1066.     if DoUpdateExclusive then UpdateExclusive;
  1067.     if DoInvalidate then Invalidate;
  1068.   end;
  1069.   if (GroupIndex > 0) and (boAutoBold in Options) then
  1070.   begin
  1071.     if FDown then Font.Style := Font.Style + [fsBold] else Font.Style := Font.Style - [fsBold];
  1072.   end;
  1073. end;
  1074. procedure TfcCustomBitBtn.UpdateExclusive;
  1075. var
  1076.   Msg: TMessage;
  1077. begin
  1078.   if (FGroupIndex <> 0) and (Parent <> nil) then
  1079.   begin
  1080.     Msg.Msg := CM_BUTTONPRESSED;
  1081.     Msg.WParam := FGroupIndex;
  1082.     Msg.LParam := Longint(Self);
  1083.     Msg.Result := 0;
  1084.     Parent.Broadcast(Msg);
  1085.   end;
  1086. end;
  1087. procedure TfcCustomBitBtn.SizeToDefault;
  1088. begin
  1089. end;
  1090. procedure TfcCustomBitBtn.UpdateShadeColors(Color: TColor);
  1091. begin
  1092.   ShadeColors.BtnShadow := fcModifyColor(Color, -50, True);
  1093.   ShadeColors.BtnBlack := fcModifyColor(ShadeColors.BtnShadow, -50, True);
  1094.   ShadeColors.Btn3dLight := fcModifyColor(Color, 50, True);
  1095.   ShadeColors.BtnHighlight := fcModifyColor(ShadeColors.Btn3dLight, 50, True);
  1096. end;
  1097. procedure TfcCustomBitBtn.RegisterChanges(Value: TfcChangeLink);
  1098. begin
  1099.    if FChangeLinks<>nil then { RSW - 3/5/99 }
  1100.       FChangeLinks.Add(Value);
  1101. end;
  1102. procedure TfcCustomBitBtn.UnRegisterChanges(Value: TfcChangeLink);
  1103. begin
  1104.    if FChangeLinks<>nil then { RSW - 3/5/99 }
  1105.       FChangeLinks.Remove(Value);
  1106. end;
  1107. {$ifdef fcDelphi4Up}
  1108. procedure TfcCustomBitBtn.ActionChange(Sender: TObject; CheckDefaults: Boolean);
  1109.   procedure CopyImage(ImageList: TCustomImageList; Index: Integer);
  1110.   begin
  1111.     with Glyph do
  1112.     begin
  1113.       Width := ImageList.Width;
  1114.       Height := ImageList.Height;
  1115.       Canvas.Brush.Color := clFuchsia;  // !!! Why clFuchsia?  Is this going to cause problems? -ksw
  1116.       Canvas.FillRect(Rect(0,0, Width, Height));
  1117.       ImageList.Draw(Canvas, 0, 0, Index);
  1118.     end;
  1119.   end;
  1120. begin
  1121.   inherited ActionChange(Sender, CheckDefaults);
  1122.   if Sender is TCustomAction then
  1123.     with TCustomAction(Sender) do
  1124.     begin
  1125.       if not (Glyph.Empty) then begin
  1126.         // Put Somethign Here
  1127.       end;
  1128.       // Copy image from action's imagelist
  1129.       if (Glyph.Empty) and (ActionList <> nil) and (ActionList.Images <> nil) and
  1130.         (ImageIndex >= 0) and (ImageIndex < ActionList.Images.Count) then
  1131.         CopyImage(ActionList.Images, ImageIndex);
  1132.     end;
  1133. end;
  1134. {$endif}
  1135. procedure TfcCustomBitBtn.Click;
  1136. var
  1137.   Form: TCustomForm;
  1138.   Control: TWinControl;
  1139. begin
  1140.   if DisableButton then exit;
  1141.   BasePatch[0]:= True;
  1142.   case FKind of
  1143.     bkClose: begin
  1144.       Form := GetParentForm(Self);
  1145.       if Form <> nil then Form.Close
  1146.       else inherited Click;
  1147.     end;
  1148.     bkHelp: begin
  1149.       Control := Self;
  1150.       while (Control <> nil) and (Control.HelpContext = 0) do
  1151.         Control := Control.Parent;
  1152.       if Control <> nil then Application.HelpContext(Control.HelpContext)
  1153.       else inherited Click;
  1154.     end;
  1155.     else begin
  1156.       Form := GetParentForm(Self);
  1157.       if Form <> nil then Form.ModalResult := ModalResult;
  1158.       inherited Click;
  1159.     end;
  1160.   end;
  1161.   BasePatch[0]:= False;
  1162.   invalidate;
  1163. end;
  1164. procedure TfcCustomBitBtn.Loaded;
  1165. begin
  1166.   inherited;
  1167.   if not (boFocusable in Options) then TabStop := False;
  1168.   ApplyRegion;
  1169.   NotifyLoaded;
  1170. end;
  1171. procedure TfcCustomBitBtn.KeyDown(var Key: Word; Shift: TShiftState);
  1172. begin
  1173.   inherited;
  1174.   if Key = VK_SPACE then
  1175.   begin
  1176.     ProcessMouseDown;
  1177.     ProcessMouseUp(-1, -1, True, True);
  1178.     Click; { 7/26/99 - Call click on space }
  1179.   end;
  1180. end;
  1181. procedure TfcCustomBitBtn.ProcessMouseDown;
  1182. begin
  1183.   if DisableButton then exit;
  1184.   FInitialDown := Down;
  1185.   if not (boToggleOnUp in Options) or (GroupIndex = 0) then
  1186.   begin
  1187.     if (boFocusable in Options) then SetFocus; { 7/26/99 - Set focus when mouse is pressed on button }
  1188.     SetButtonDown(True, True, False, False);
  1189.   end;
  1190.   if FInitialDown <> Down then Redraw;
  1191. end;
  1192. procedure TfcCustomBitBtn.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1193. begin
  1194.   { 3/9/00 - Don't check key state as mouse could already be released }
  1195.   if (Button = mbLeft) {and (GetKeyState(VK_LBUTTON) < 0) }then
  1196.   begin
  1197.     FClicked := True;
  1198.     SetCaptureControl(self);
  1199. //    MouseCapture:= True; { Equivalent - Perhaps change to this in the future }
  1200.     ProcessMouseDown;
  1201.   end;
  1202.   { 5/1/00 - Added flag because sendmessage in MouseActivate causes some recursion when using the OnMouseDown.  Specifically the MenuForm example project}
  1203.   if (not FInMouseSendForMouseActivate) or (BasePatch[1] = True) then
  1204.      inherited;
  1205. //  else inherited
  1206. end;
  1207. procedure TfcCustomBitBtn.MouseMove(Shift: TShiftState; X, Y: Integer);
  1208. var IsMouseInControl: Boolean;
  1209. begin
  1210.   if DisableButton then exit;
  1211.   inherited;
  1212.   if ((boToggleOnUp in Options)) or not FClicked or (GetKeyState(VK_LBUTTON) >= 0) then Exit;
  1213.   IsMouseInControl := MouseInControl(x, y, True);
  1214.   if (IsMouseInControl and not Down) or
  1215.      ((not IsMouseInControl and Down) and not FInitialDown) then
  1216.   begin
  1217.     SetButtonDown(IsMouseInControl, False, False, False);
  1218.     Redraw;
  1219.   end;
  1220. end;
  1221. procedure TfcCustomBitBtn.ProcessMouseUp(X, Y: Integer; AMouseInControl: Boolean; AClicked: Boolean);
  1222. begin
  1223.   if DisableButton then exit;
  1224.   if (GroupIndex = 0) then
  1225.   begin
  1226.     SetButtonDown(False, False, False, False);
  1227.     Redraw;
  1228.   end else begin
  1229.     UpdateExclusive;
  1230.     if AMouseInControl or (boToggleOnUp in Options) then
  1231.     begin
  1232.       if ((FInitialDown and AllowAllUp) or (not FInitialDown)) then
  1233.       begin
  1234.         SetButtonDown(not FInitialDown, True, True, False);
  1235.         Redraw;
  1236.         SelChange;
  1237.       end;
  1238.     end;
  1239.   end;
  1240. end;
  1241. procedure TfcCustomBitBtn.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1242.   X, Y: Integer);
  1243. begin
  1244.   inherited;
  1245.   {7/13/99 - PYW - Changed to always process mouse up in fcoutlookbar}
  1246.   if (not ShowDownAsUp) and fcIsClass(Parent.ClassType, 'TfcCustomOutlookBar') then
  1247.      ProcessMouseUp(x, y, True, FClicked)
  1248.   else
  1249.      ProcessMouseUp(x, y, MouseInControl(x, y, True), FClicked);
  1250. //  MouseCapture:= False; { 4/2/99  Equivalent - Perhaps change to this in the future }
  1251.   SetCaptureControl(nil);
  1252.   //2/26/99 - Check for ToggleOnUp so that Click will be fired when button has
  1253.   //          different up/down regions.
  1254.   if MouseInControl(x, y, True) or (boToggleOnUp in Options) then Click;
  1255.   FClicked := False;
  1256. end;
  1257. procedure TfcCustomBitBtn.SetName(const Value: TComponentName);
  1258. begin
  1259.   inherited;
  1260.   if Assigned(FOnSetName) then FOnSetName(self);
  1261. end;
  1262. procedure TfcCustomBitBtn.CMButtonPressed(var Message: TMessage);
  1263. var
  1264.   Sender: TfcCustomBitBtn;
  1265. begin
  1266.   if Message.WParam = FGroupIndex then
  1267.   begin
  1268.     if not (TObject(Message.LParam) is TfcCustomBitBtn) then Exit;
  1269.     Sender := TfcCustomBitBtn(Message.LParam);
  1270.     if (Sender.Down) then
  1271.     begin
  1272.        if Sender<>Self then
  1273.           SetButtonDown(False, False, False, True);
  1274.        if Sender<>Self then
  1275.           SelChange // 7/22/01 Call SelChange so that is selected
  1276.        else
  1277.           FSelected := Down; // 9/20/01 - Don't call SelChange if Sender=Self, but just set FSelected
  1278.                              // This corrects slowness when outlookbar is changning pages
  1279.     end;
  1280.   end;
  1281. end;
  1282. procedure TfcCustomBitBtn.CMDialogChar(var Message: TCMDialogChar);
  1283. begin
  1284.   with Message do
  1285.   begin
  1286.     if  (((CharCode = VK_RETURN) and FActive) or
  1287.       ((CharCode = VK_ESCAPE) and FCancel)) and
  1288.       (KeyDataToShiftState(Message.KeyData) = []) and CanFocus then
  1289.     begin
  1290.       Click;
  1291.       Result := 1;
  1292.     end else if IsAccel(CharCode, GetDBCaption) and CanFocus then begin
  1293.       //Down := not Down;
  1294.       // 1/3/2000 - Use SetButtonDown procedure so AllowAllUp is considered.
  1295.       if GroupIndex > 0 then  // 10/15/2001- Only set this if groupindex > 0.
  1296.          SetButtonDown(True, True, True, False);
  1297.       Click;
  1298.       Invalidate;
  1299.       Result := 1;
  1300.     end else inherited;
  1301.   end;
  1302. end;
  1303. procedure TfcCustomBitBtn.CMEnabledChanged(var Message: TMessage);
  1304. begin
  1305.   inherited;
  1306.   Invalidate;
  1307. end;
  1308. procedure TfcCustomBitBtn.CMFocusChanged(var Message: TCMFocusChanged);
  1309. begin
  1310.   with Message do
  1311.     if Sender is TfcCustomBitBtn then
  1312.       FActive := Sender = Self
  1313.     else
  1314.       FActive := FDefault;
  1315.   inherited;
  1316. end;
  1317. procedure TfcCustomBitBtn.CMMouseEnter(var Message: TMessage);
  1318. begin
  1319.   inherited;
  1320.   if (ShadeStyle = fbsFlat) or (NumGlyphs = 4) then Invalidate;
  1321.   if fcUseThemes(self) then Invalidate;
  1322. //  if ThemeServices.ThemesEnabled then Invalidate;
  1323.   if Assigned(FOnMouseEnter) then FOnMouseEnter(self);
  1324.   FHot:= True;
  1325. end;
  1326. procedure TfcCustomBitBtn.CMMouseLeave(var Message: TMessage);
  1327. begin
  1328.   inherited;
  1329.   if (ShadeStyle = fbsFlat) or (NumGlyphs = 4) then Invalidate;
  1330.   if fcUseThemes(self) then Invalidate;
  1331. //  if ThemeServices.ThemesEnabled then Invalidate;
  1332.   if Assigned(FOnMouseLeave) then FOnMouseLeave(self);
  1333.   FHot:= False;
  1334. end;
  1335. procedure TfcCustomBitBtn.CNMeasureItem(var Message: TWMMeasureItem);
  1336. begin
  1337.   with Message.MeasureItemStruct^ do
  1338.   begin
  1339.     ItemWidth := Width;
  1340.     ItemHeight := Height;
  1341.   end;
  1342. end;
  1343. procedure TfcCustomBitBtn.CNDrawItem(var Message: TWMDrawItem);
  1344. begin
  1345.   DrawItem(Message.DrawItemStruct^);
  1346. end;
  1347. procedure TfcCustomBitBtn.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  1348. begin
  1349.   Message.Result := 1;
  1350. end;
  1351. procedure TfcCustomBitBtn.WMLButtonDown(var Message: TWMLButtonDown);
  1352. begin
  1353.   SendCancelMode(Self);
  1354.   if csCaptureMouse in ControlStyle then MouseCapture := True;
  1355.   if csClickEvents in ControlStyle then ControlState := ControlState + [csClicked];
  1356.   with Message do
  1357.     MouseDown(mbLeft, KeysToShiftState(Keys) + [], XPos, YPos);
  1358. end;
  1359. procedure TfcCustomBitBtn.WMMouseActivate(var Message: TWMMouseActivate);
  1360. var Button: TMouseButton;
  1361.     Shift: TShiftState;
  1362.   function GetShiftState: TShiftState;
  1363.   begin
  1364.     Result := [];
  1365.     if GetKeyState(VK_SHIFT) < 0 then Include(Result, ssShift);
  1366.     if GetKeyState(VK_CONTROL) < 0 then Include(Result, ssCtrl);
  1367.   end;
  1368.   function ShiftStateToKeys(State: TShiftState): Word;
  1369.   begin
  1370.      Result := 0;
  1371.      if ssShift in State then Result:= Result + MK_SHIFT;
  1372.      if ssCtrl in State then Result:= Result + MK_CONTROL;
  1373.      if ssLeft in State then Result:= Result + MK_LBUTTON;
  1374.      if ssRight in State then Result:= Result + MK_RBUTTON;
  1375.   end;
  1376. begin
  1377.   { 6/19/2000 - PYW -  Solve mousedown problems with nonfocusable buttons.}
  1378.   if BasePatch[1] = False then begin
  1379.      inherited;
  1380.      exit;
  1381.   end;
  1382.   if (csDesigning in ComponentState) or (boFocusable in Options) then inherited
  1383.   else begin
  1384.     Message.result := MA_NOACTIVATEANDEAT;
  1385.     if Message.MouseMsg = WM_LBUTTONDOWN then Button := mbLeft else Button := mbRight;
  1386.     Shift := GetShiftState;
  1387.     if Button = mbLeft then include(Shift, ssLeft) else include(Shift, ssRight);
  1388.     GetParentForm(self).BringToFront; // Added to make sure form is shown when user clicks on button. (Avoid IE5 scroll button problems) -ksw (2/19/99)
  1389.     with ScreenToClient(fcGetCursorPos) do
  1390.       if (x>=0) and (y>=0) then { RSW - 4/16/99 }
  1391.       begin
  1392.          if Button=mbLeft then begin
  1393.             { 3/9/00 - Changed to SendMessage to ensure button down processed before button up }
  1394.             { 5/1/00 - Added flag because sendmessage causes some recursion when using the OnMouseDown.  Specifically the MenuForm example project}
  1395.             FInMouseSendForMouseActivate := True;
  1396.             SendMessage(Handle, WM_LBUTTONDOWN, ShiftStateToKeys(Shift), MAKELPARAM(x, y));
  1397.             FInMouseSendForMouseActivate := False;
  1398. //             {4/12/00 - Added back the postmessage because sendmessage causes some recursion when using the OnMouseDown.  Specifically the MenuForm example project}
  1399. //              PostMessage(Handle, WM_LBUTTONDOWN, ShiftStateToKeys(Shift), MAKELPARAM(x, y))
  1400.          end
  1401.          else
  1402.             PostMessage(Handle, WM_RBUTTONDOWN, ShiftStateToKeys(Shift), MAKELPARAM(x, y))
  1403.       end
  1404.   end;
  1405. end;
  1406. function TfcCustomBitBtn.GetKind: TBitBtnKind;
  1407. begin
  1408.   if FKind <> bkCustom then
  1409.     if ((FKind in [bkOK, bkYes]) xor Default) or
  1410.        ((FKind in [bkCancel, bkNo]) xor Cancel) or
  1411.        (ModalResult <> BITBTNMODALRESULTS[FKind]) or
  1412.        FModifiedGlyph then
  1413.       FKind := bkCustom;
  1414.   Result := FKind;
  1415. end;
  1416. procedure TfcCustomBitBtn.SetAllowAllUp(Value: Boolean);
  1417. begin
  1418.   if FAllowAllUp <> Value then
  1419.   begin
  1420.     FAllowAllUp := Value;
  1421.     UpdateExclusive;
  1422.   end;
  1423. end;
  1424. procedure TfcCustomBitBtn.SetDefault(Value: Boolean);
  1425. var
  1426.   Form: TCustomForm;
  1427. begin
  1428.   FDefault := Value;
  1429.   if HandleAllocated then
  1430.   begin
  1431.     Form := GetParentForm(Self);
  1432.     if Form <> nil then
  1433.       Form.Perform(CM_FOCUSCHANGED, 0, Longint(Form.ActiveControl));
  1434.   end;
  1435. end;
  1436. procedure TfcCustomBitBtn.SetDown(Value: Boolean);
  1437. begin
  1438.   if (FGroupIndex = 0) and (not (csLoading in ComponentState)) then Value := False;
  1439.   if FDown <> Value then
  1440.   begin
  1441.     SetButtonDown(Value, True, True, True);
  1442.     if FDown = Value then SelChange;
  1443.   end;
  1444. end;
  1445. procedure TfcCustomBitBtn.SetGlyph(Value: TBitmap);
  1446. begin
  1447.   Glyph.Assign(Value);
  1448.   Invalidate;
  1449. end;
  1450. procedure TfcCustomBitBtn.SetGroupIndex(Value: Integer);
  1451. begin
  1452.   if FGroupIndex <> Value then
  1453.   begin
  1454.     FGroupIndex := Value;
  1455.     UpdateExclusive;
  1456.   end;
  1457. end;
  1458. procedure TfcCustomBitBtn.SetKind(Value: TBitBtnKind);
  1459. begin
  1460.   if Value <> FKind then
  1461.   begin
  1462.     if Value <> bkCustom then
  1463.     begin
  1464.       Default := Value in [bkOK, bkYes];
  1465.       Cancel := Value in [bkCancel, bkNo];
  1466.       if ((csLoading in ComponentState) and (GetDBCaption = '')) or
  1467.         (not (csLoading in ComponentState)) then
  1468.       begin
  1469.         if BitBtnCaptions[Value] <> nil then
  1470.           Caption := LoadResString(BitBtnCaptions[Value]);
  1471.       end;
  1472.       ModalResult := BITBTNMODALRESULTS[Value];
  1473.       GetBitBtnGlyph(Value, FGlyph);
  1474.       NumGlyphs := 2;
  1475.       FModifiedGlyph := False;
  1476.     end;
  1477.     FKind := Value;
  1478.     Invalidate;
  1479.   end;
  1480. end;
  1481. procedure TfcCustomBitBtn.SetLayout(Value: TButtonLayout);
  1482. begin
  1483.   if FLayout <> Value then
  1484.   begin
  1485.     FLayout := Value;
  1486.     Invalidate;
  1487.   end;
  1488. end;
  1489. procedure TfcCustomBitBtn.SetMargin(Value: Integer);
  1490. begin
  1491.   if (Value <> FMargin) and (Value >= - 1) then
  1492.   begin
  1493.     FMargin := Value;
  1494.     Invalidate;
  1495.   end;
  1496. end;
  1497. procedure TfcCustomBitBtn.SetNumGlyphs(Value: TNumGlyphs);
  1498. begin
  1499.   Value := fcMin(fcMax(Value, 1), 4);
  1500.   if Value <> FNumGlyphs then
  1501.   begin
  1502.     FNumGlyphs := Value;
  1503.     Invalidate;
  1504.   end;
  1505. end;
  1506. procedure TfcCustomBitBtn.SetOptions(Value: TfcButtonOptions);
  1507. var ChangedOptions: TfcButtonOptions;
  1508. begin
  1509.   if FOptions <> Value then
  1510.   begin
  1511.     ChangedOptions := (FOptions - Value) + (Value - FOptions);
  1512.     FOptions := Value;
  1513.     if not (boFocusable in FOptions) then TabStop := False;
  1514.     if boAutoBold in ChangedOptions then SetButtonDown(Down, False, False, True);
  1515.   end;
  1516. end;
  1517. procedure TfcCustomBitBtn.SetShadeStyle(Value: TfcShadeStyle);
  1518. begin
  1519.   if FShadeStyle <> Value then
  1520.   begin
  1521.     FShadeStyle := Value;
  1522.     Recreatewnd;
  1523.   end;
  1524. end;
  1525. procedure TfcCustomBitBtn.SetSpacing(Value: Integer);
  1526. begin
  1527.   if FSpacing <> Value then
  1528.   begin
  1529.     FSpacing := Value;
  1530.     Invalidate;
  1531.   end;
  1532. end;
  1533. procedure TfcCustomBitBtn.SetStyle(Value: TButtonStyle);
  1534. begin
  1535.   if Value <> FStyle then
  1536.   begin
  1537.     FStyle := Value;
  1538.     Invalidate;
  1539.   end;
  1540. end;
  1541. function TfcCustomBitBtn.IsCustom: Boolean;
  1542. begin
  1543.   Result := Kind = bkCustom;
  1544. end;
  1545. function TfcCustomBitBtn.IsCustomCaption: Boolean;
  1546. begin
  1547.   Result := CompareStr(Caption, LoadResString(BitBtnCaptions[FKind])) <> 0;
  1548. end;
  1549. function TfcCustomBitBtn.MouseInControl(X, Y: Integer; AndClicked: Boolean): Boolean;
  1550. var p: TPoint;
  1551.     AHandle: HWND;
  1552.     TmpRgn: HRGN;
  1553.     Control: TWinControl;
  1554.     ParentForm:TCustomForm;
  1555. begin
  1556.   //11/17/99 - Make sure that only active window is hot-tracked.
  1557.   //2/22/00 - Disregard parent test if MDI form }
  1558.   ParentForm := GetParentForm(self);
  1559.   if (ParentForm<>nil) and (ParentForm.handle<>GetActiveWindow) then begin
  1560.     if not (TForm(ParentForm).formstyle in [fsMDIChild, fsMDIForm]) and
  1561.        not (fcIsClass(ParentForm.classType, 'TActiveForm')) then // 7/31/00 - Disregard parent test for ActiveX forms
  1562.       // 5/18/2000 - PYW - Don't exit if ParentForm was created using CreateParented.
  1563.       if (ParentForm.ParentWindow = 0) or (GetParent(ParentForm.ParentWindow) <> GetActiveWindow) then
  1564.       begin
  1565.         result := False;
  1566.         exit;
  1567.       end;
  1568.   end;
  1569.   if IsMultipleRegions then Control := self else Control := Parent;
  1570.   if (x = -1) and (y = -1) then p := Control.ScreenToClient(fcGetCursorPos)
  1571.   else p := Control.ScreenToClient(ClientToScreen(Point(x, y)));
  1572.   if IsMultipleRegions then
  1573.   begin
  1574.     TmpRgn := CreateRegion(True, not Down);
  1575.     CombineRgn(TmpRgn, TmpRgn, FLastRegion, RGN_OR);
  1576.     result := PtInRegion(TmpRgn, p.x, p.y);
  1577.     DeleteOBject(TmpRgn);
  1578.   end else begin
  1579.     //12/20/2001 - Skip invisible controls. {PYW}
  1580.     AHandle := ChildWindowFromPointEx(Parent.Handle, p, CWP_SKIPINVISIBLE);
  1581.     result := FindControl(AHandle) = self;
  1582.   end;
  1583.   if AndClicked then result := result and FClicked;
  1584. end;
  1585. procedure Initialize;
  1586. begin
  1587.   FillChar(BitBtnGlyphs, SizeOf(BitBtnGlyphs), 0);
  1588.   BitBtnCaptions[bkOK] := @SOKButton;
  1589.   BitBtnCaptions[bkCancel] := @SCancelButton;
  1590.   BitBtnCaptions[bkHelp] := @SHelpButton;
  1591.   BitBtnCaptions[bkYes] := @SYesButton;
  1592.   BitBtnCaptions[bkNo] := @SNoButton;
  1593.   BitBtnCaptions[bkClose] := @SCloseButton;
  1594.   BitBtnCaptions[bkAbort] := @SAbortButton;
  1595.   BitBtnCaptions[bkRetry] := @SRetryButton;
  1596.   BitBtnCaptions[bkIgnore] := @SIgnoreButton;
  1597.   BitBtnCaptions[bkAll] := @SAllButton;
  1598. end;
  1599. procedure Finalize;
  1600. var i: TBitBtnKind;
  1601. begin
  1602.   for i := Low(TBitBtnKind) to High(TBitBtnKind) do
  1603.     BitBtnGlyphs[I].Free;
  1604. end;
  1605. procedure TfcCustomBitBtn.WMSize(var Message: TWMSize);
  1606. var r: TRect;
  1607. begin
  1608.   inherited;
  1609.   ClearRegion(@FRegionData);
  1610.   ClearRegion(@FDownRegionData);
  1611.   SetWindowRgn(Handle, 0, True);
  1612.   ApplyRegion;
  1613.   Invalidate;
  1614.   r := BoundsRect;
  1615.   if Parent <> nil then InvalidateRect(Parent.Handle, @r, True);
  1616. end;
  1617. { RSW - 3/9/99 - Process default button when carriage return or Cancel entered }
  1618. procedure TfcCustomBitBtn.CMDialogKey(var Message: TCMDialogKey);
  1619. begin
  1620.   with Message do
  1621.     if  (((CharCode = VK_RETURN) and FActive) or
  1622.       ((CharCode = VK_ESCAPE) and FCancel)) and
  1623.       (KeyDataToShiftState(Message.KeyData) = []) and CanFocus then
  1624.     begin
  1625.       Click;
  1626.       Result := 1;
  1627.     end else
  1628.       inherited;
  1629. end;
  1630. procedure TfcCustomBitBtn.WMCancelMode(var Message: TWMCancelMode);
  1631. begin
  1632.   inherited;
  1633.   if csLButtonDown in ControlState then Perform(WM_LBUTTONUP, 0, Integer($FFFFFFFF));
  1634. end;
  1635. procedure TfcCustomBitBtn.InvalidateNotRegion(const Erase: Boolean);
  1636. var Rgn, TmpRgn: HRGN;
  1637.   DownFlag:Boolean;
  1638. begin
  1639.   DownFlag := Down and not (csPaintCopy in ControlState); // 6/17/02
  1640.   if False and ShowDownAsUp then begin
  1641.      if Down then DownFlag := False;
  1642.      if FClicked and MouseInControl(-1,-1,False) and not Selected then
  1643.         DownFlag := True;
  1644.   end;
  1645.   with ClientRect do Rgn := CreateRectRgn(Left, Top, Right, Bottom);
  1646.   with ClientRect do TmpRgn := CreateRegion(False, DownFlag);
  1647.   try
  1648.     CombineRgn(Rgn, Rgn, TmpRgn, RGN_DIFF);
  1649.     OffsetRgn(Rgn, Left, Top);
  1650.     InvalidateRgn(Parent.Handle, Rgn, Erase);
  1651.   finally
  1652.     DeleteObject(Rgn);
  1653.     DeleteObject(TmpRgn);
  1654.   end;
  1655. end;
  1656. function TfcCustomBitBtn.UseRegions: boolean;
  1657. begin
  1658.    result:= False;
  1659. end;
  1660. // 6/17/02 - Support button painting in grid
  1661. procedure TfcCustomBitBtn.WMPaint(var Message: TWMPaint);
  1662. var tc: TColor;
  1663.   procedure CanvasNeeded;
  1664.   begin
  1665.     if FCanvas = nil then
  1666.     begin
  1667.       FCanvas := TControlCanvas.Create;
  1668.       TControlCanvas(FCanvas).Control := Self;
  1669.     end;
  1670.   end;
  1671. begin
  1672.   if not (csPaintCopy in ControlState) then
  1673.   begin
  1674.      inherited;
  1675.   end
  1676.   else begin
  1677.      tc:= Font.Color;
  1678.      if fcIsInwwGridPaint(self) and (message.dc<>0) then tc:= GetTextColor(message.dc);
  1679.      CanvasNeeded;
  1680.      FCanvas.Handle := Message.dc;
  1681.      FCanvas.Font:= Font;
  1682.      if fcIsInwwGridPaint(self) and (message.dc<>0) then FCanvas.Font.Color:= tc;
  1683.      Paint;
  1684.      FCanvas.Handle := 0;
  1685.   end;
  1686. end;
  1687. procedure TfcCustomBitBtn.CMGetDataLink(var Message: TMessage);
  1688. begin
  1689.   Message.Result := Integer(FDataLink);
  1690. end;
  1691. function TfcCustomBitBtn.GetDataSource: TDataSource;
  1692. begin
  1693.   if (FDataLink<>Nil) and (FDataLink.DataSource is TDataSource) then begin
  1694.      Result := FDataLink.DataSource as TDataSource
  1695.   end
  1696.   else Result:= Nil;
  1697. end;
  1698. procedure TfcCustomBitBtn.SetDataSource(Value: TDataSource);
  1699. begin
  1700.   FDataLink.DataSource := Value;
  1701. end;
  1702. function TfcCustomBitBtn.GetDataField: string;
  1703. begin
  1704.   Result := FDataLink.FieldName;
  1705. end;
  1706. procedure TfcCustomBitBtn.SetDataField(const Value: string);
  1707. begin
  1708.   FDataLink.FieldName := Value;
  1709. end;
  1710. {procedure TfcCustomBitBtn.SetCaption(val: string);
  1711. begin
  1712.    if FDataLink.Field<>nil then
  1713.    begin
  1714.       if (DataSource<>Nil) and (DataSource.autoEdit) then
  1715.          if not (DataSource.state in [dsEdit, dsInsert]) then
  1716.             FDataLink.Edit;
  1717.       FDataLink.Field.Text:= val;
  1718.    end
  1719.    else inherited Caption:= val
  1720. end;
  1721. }
  1722. function TfcCustomBitBtn.GetDBCaption: string;
  1723. begin
  1724.    if (not StaticCaption) and (csPaintCopy in ControlState) and (FDataLink.Field <> nil) then
  1725.    begin
  1726.       if (FDataLink.Field is TBlobField) then
  1727.          result:= FDataLink.Field.asString
  1728.       else
  1729.          result:= FDataLink.Field.DisplayText
  1730.    end
  1731.    else result:= inherited Caption
  1732. end;
  1733. procedure TfcCustomBitBtn.DataChange(Sender: TObject);
  1734. begin
  1735.   if (FDataLink.Field <> nil) and (not StaticCaption) then
  1736.   begin
  1737.     if (FDataLink.Field is TBlobField) then
  1738.        inherited Caption := FDataLink.Field.asString
  1739.     else inherited Caption := FDataLink.Field.DisplayText;
  1740.   end
  1741. end;
  1742. procedure TfcCustomBitBtn.Notification(AComponent: TComponent;
  1743.   Operation: TOperation);
  1744. begin
  1745.   inherited Notification(AComponent, Operation);
  1746.   if (Operation = opRemove) and (FDataLink <> nil) and
  1747.     (AComponent = DataSource) then DataSource := nil;
  1748. end;
  1749. function TfcCustomBitBtn.GetField: TField;
  1750. begin
  1751.   Result := FDataLink.Field;
  1752. end;
  1753. initialization
  1754.   Initialize;
  1755. finalization
  1756.   Finalize;
  1757. end.