Componentes.Terceros.jvcl/official/3.32/run/JvCtrls.pas

1130 lines
31 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvCtrls.PAS, released May 13, 2000.
The Initial Developer of the Original Code is Petr Vones (petr dott v att mujmail dott cz)
Portions created by Petr Vones are Copyright (C) 2000 Petr Vones.
Portions created by Microsoft are Copyright (C) 1998, 1999 Microsoft Corp.
All Rights Reserved.
Contributor(s): ______________________________________.
Current Version: 0.50
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvCtrls.pas 10783 2006-07-04 14:36:22Z obones $
unit JvCtrls;
{$I jvcl.inc}
interface
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
{$IFDEF HAS_UNIT_TYPES}
Types,
{$ENDIF HAS_UNIT_TYPES}
Windows, Messages, Classes, Graphics, Controls, StdCtrls, ImgList,
JvButton;
{$IFDEF VisualCLX}
const
ODS_DISABLED = 1;
ODS_SELECTED = 2;
ODS_FOCUS = 4;
type
TDrawItemStruct = record
itemState: Integer;
end;
{$ENDIF VisualCLX}
type
TJvImgBtnLayout = (blImageLeft, blImageRight);
TJvImgBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose,
bkAbort, bkRetry, bkIgnore, bkAll);
TJvCustomImageButton = class;
TJvImgBtnActionLink = class(TButtonActionLink)
protected
FClient: TJvCustomImageButton;
procedure AssignClient(AClient: TObject); override;
function IsImageIndexLinked: Boolean; override;
procedure SetImageIndex(Value: Integer); override;
end;
TJvImgBtnDrawEvent = procedure(Sender: TObject; const DrawItemStruct: TDrawItemStruct) of object;
TJvImgBtnAnimIndexEvent = procedure(Sender: TObject; CurrentAnimateFrame: Byte;
var ImageIndex: Integer) of object;
TJvCustomImageButton = class(TJvCustomButton)
private
FAlignment: TAlignment;
FAnimate: Boolean;
FAnimateFrames: Integer;
FAnimateInterval: Cardinal;
FAnimating: Boolean;
FCanvas: TCanvas;
FCurrentAnimateFrame: Byte;
FImageIndex: TImageIndex;
FImages: TCustomImageList;
FImageChangeLink: TChangeLink;
FIsFocused: Boolean;
FKind: TJvImgBtnKind;
FLayout: TJvImgBtnLayout;
FOwnerDraw: Boolean;
FSpacing: Integer;
FMargin: Integer;
FMouseInControl: Boolean;
FOnButtonDraw: TJvImgBtnDrawEvent;
FOnGetAnimateIndex: TJvImgBtnAnimIndexEvent;
FImageVisible: Boolean;
FFlat: Boolean;
procedure ImageListChange(Sender: TObject);
procedure SetAlignment(const Value: TAlignment);
procedure SetAnimate(const Value: Boolean);
procedure SetAnimateFrames(const Value: Integer);
procedure SetAnimateInterval(const Value: Cardinal);
procedure SetImageIndex(const Value: TImageIndex);
procedure SetImages(const Value: TCustomImageList);
procedure SetImageVisible(const Value: Boolean);
procedure SetKind(const Value: TJvImgBtnKind);
procedure SetLayout(const Value: TJvImgBtnLayout);
procedure SetOwnerDraw(const Value: Boolean);
procedure SetMargin(const Value: Integer);
procedure SetSpacing(const Value: Integer);
procedure SetFlat(const Value: Boolean);
{$IFDEF VCL}
procedure CNDrawItem(var Msg: TWMDrawItem); message CN_DRAWITEM;
procedure CNMeasureItem(var Msg: TWMMeasureItem); message CN_MEASUREITEM;
procedure WMDestroy(var Msg: TWMDestroy); message WM_DESTROY;
procedure WMLButtonDblClk(var Msg: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
{$ENDIF VCL}
procedure WMTimer(var Msg: TWMTimer); message WM_TIMER;
protected
{$IFDEF VisualCLX}
procedure DestroyWidget; override;
procedure Paint; override;
{$ENDIF VisualCLX}
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
procedure CalcButtonParts(ButtonRect: TRect; var RectText, RectImage: TRect); virtual;
{$IFDEF VCL}
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateWnd; override;
{$ENDIF VCL}
procedure DrawItem(const DrawItemStruct: TDrawItemStruct); dynamic;
function GetActionLinkClass: TControlActionLinkClass; override;
function GetCustomCaption: string; dynamic;
function GetImageIndex: Integer;
function GetImageList: TCustomImageList;
function GetKindImageIndex: Integer;
function GetRealCaption: string;override;
procedure InvalidateImage;
function IsImageVisible: Boolean;
procedure Loaded; override;
procedure SetButtonStyle(ADefault: Boolean); {$IFDEF VCL} override; {$ENDIF}
procedure ShowNextFrame;
procedure StartAnimate;
procedure StopAnimate;
procedure RestartAnimate;
procedure MouseEnter(Control: TControl); override;
procedure MouseLeave(Control: TControl); override;
procedure EnabledChanged; override;
procedure FontChanged; override;
class procedure InitializeDefaultImageList;
property Alignment: TAlignment read FAlignment write SetAlignment default taCenter;
property Animate: Boolean read FAnimate write SetAnimate default False;
property AnimateFrames: Integer read FAnimateFrames write SetAnimateFrames default 0;
property AnimateInterval: Cardinal read FAnimateInterval write SetAnimateInterval default 200;
property Color default clBtnFace;
property Images: TCustomImageList read FImages write SetImages;
property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1;
property ImageVisible: Boolean read FImageVisible write SetImageVisible default True;
property Kind: TJvImgBtnKind read FKind write SetKind default bkCustom;
property Flat: Boolean read FFlat write SetFlat default False;
property Layout: TJvImgBtnLayout read FLayout write SetLayout default blImageLeft;
property Margin: Integer read FMargin write SetMargin default -1;
property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw default False;
property Spacing: Integer read FSpacing write SetSpacing default 4;
property OnButtonDraw: TJvImgBtnDrawEvent read FOnButtonDraw write FOnButtonDraw;
property OnGetAnimateIndex: TJvImgBtnAnimIndexEvent read FOnGetAnimateIndex write FOnGetAnimateIndex;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Click; override;
procedure DrawButtonImage(ImageBounds: TRect); virtual;
procedure DrawButtonFocusRect(const RectContent: TRect); virtual;
procedure DrawButtonFrame(const DrawItemStruct: TDrawItemStruct; var RectContent: TRect); virtual;
procedure DrawButtonText(TextBounds: TRect; TextEnabled: Boolean); virtual;
property Canvas: TCanvas read FCanvas;
property CurrentAnimateFrame: Byte read FCurrentAnimateFrame;
property MouseInControl: Boolean read FMouseInControl;
end;
TJvImgBtn = class(TJvCustomImageButton)
published
property Alignment;
property Animate;
property AnimateFrames;
property AnimateInterval;
property Color;
property DropDownMenu;
property DropArrow;
property Flat;
property HotTrack;
property HotTrackFont;
property HotTrackFontOptions;
property HintColor;
property Images;
property ImageIndex;
property ImageVisible;
property Kind;
property Layout;
property Margin;
property Spacing;
property WordWrap;
property OnMouseEnter;
property OnMouseLeave;
property OnParentColorChange;
property OwnerDraw;
{$IFDEF VCL}
property OnButtonDraw;
{$ENDIF VCL}
property OnDropDownMenu;
property OnGetAnimateIndex;
end;
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvCtrls.pas $';
Revision: '$Revision: 10783 $';
Date: '$Date: 2006-07-04 16:36:22 +0200 (mar., 04 juil. 2006) $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
implementation
uses
Consts, SysUtils, Forms, ActnList, ExtCtrls,
JvJCLUtils, JvJVCLUtils, JvThemes;
{$R JvCtrls.res}
const
JvImgBtnModalResults: array [TJvImgBtnKind] of TModalResult =
(mrNone, mrOk, mrCancel, mrNone, mrYes, mrNo, mrNone,
mrAbort, mrRetry, mrIgnore, mrAll);
Alignments: array [TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
var
DefaultImgBtnImagesList: TImageList = nil;
//=== { TJvImgBtnActionLink } ================================================
procedure TJvImgBtnActionLink.AssignClient(AClient: TObject);
begin
inherited AssignClient(AClient);
FClient := AClient as TJvCustomImageButton;
end;
function TJvImgBtnActionLink.IsImageIndexLinked: Boolean;
begin
Result := inherited IsImageIndexLinked and
(FClient.ImageIndex = (Action as TCustomAction).ImageIndex);
end;
procedure TJvImgBtnActionLink.SetImageIndex(Value: Integer);
begin
if IsImageIndexLinked then
FClient.ImageIndex := Value;
end;
//=== { TJvCustomImageButton } ===============================================
constructor TJvCustomImageButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFlat := False;
FCanvas := TCanvas.Create;
FAlignment := taCenter;
FAnimateInterval := 200;
FImageChangeLink := TChangeLink.Create;
FImageChangeLink.OnChange := ImageListChange;
FImageIndex := -1;
FImageVisible := True;
FKind := bkCustom;
FLayout := blImageLeft;
FMargin := -1;
FSpacing := 4;
Color := clBtnFace;
InitializeDefaultImageList;
end;
destructor TJvCustomImageButton.Destroy;
begin
FreeAndNil(FImageChangeLink);
inherited Destroy;
// (rom) destroy Canvas AFTER inherited Destroy
FreeAndNil(FCanvas);
end;
procedure TJvCustomImageButton.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = Images) then
Images := nil;
end;
{$IFDEF VCL}
procedure TJvCustomImageButton.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
Style := Style or BS_OWNERDRAW;
end;
procedure TJvCustomImageButton.CreateWnd;
begin
inherited CreateWnd;
if FAnimate then
StartAnimate;
end;
{$ENDIF VCL}
procedure TJvCustomImageButton.ActionChange(Sender: TObject; CheckDefaults: Boolean);
begin
inherited ActionChange(Sender, CheckDefaults);
if Sender is TCustomAction then
with TCustomAction(Sender) do
begin
if ActionList <> nil then
Self.SetImages(ActionList.Images);
Self.SetImageIndex(ImageIndex);
Invalidate;
end;
end;
procedure TJvCustomImageButton.CalcButtonParts(ButtonRect: TRect; var RectText, RectImage: TRect);
var
BlockWidth, ButtonWidth, ButtonHeight, BlockMargin, InternalSpacing: Integer;
Flags: Integer;
begin
if IsImageVisible then
begin
with GetImageList do
SetRect(RectImage, 0, 0, Width - 1, Height - 1);
InternalSpacing := Spacing;
end
else
begin
SetRect(RectImage, 0, 0, 0, 0);
InternalSpacing := 0;
end;
// In order to take WordWrap into account, we MUST pass a non zero rectangle
// to DrawText and so we must calculate a original bounding rectangle
SetRect(RectText, 0, 0, 0, 0);
RectText.Right := ButtonRect.Right - ButtonRect.Left - (RectImage.Right - RectImage.Left);
RectText.Bottom := ButtonRect.Bottom;
if FAlignment <> taCenter then
begin
if RectText.Right < Width - RectImage.Right - 18 then
RectText.Right := Width - RectImage.Right - 18;
end;
Flags := DT_CALCRECT or Alignments[FAlignment];
if WordWrap then
Flags := Flags or DT_WORDBREAK;
{$IFDEF CLR}
DrawText(Canvas, GetRealCaption, -1, RectText, Flags);
{$ELSE}
DrawText(Canvas, PChar(GetRealCaption), -1, RectText, Flags);
{$ENDIF CLR}
// Now offset the rectangles according to layout and spacings
BlockWidth := RectImage.Right + InternalSpacing + RectText.Right;
ButtonWidth := ButtonRect.Right - ButtonRect.Left;
if (Margin = -1) or (Alignment = taCenter) then
begin
BlockMargin := (ButtonWidth - BlockWidth) div 2
end
else
begin
if Alignment = taRightJustify then
BlockMargin := ButtonWidth - BlockWidth - Margin
else
BlockMargin := Margin;
end;
case Layout of
blImageLeft:
begin
OffsetRect(RectImage, BlockMargin, 0);
OffsetRect(RectText, RectImage.Right + InternalSpacing, 0);
end;
blImageRight:
begin
OffsetRect(RectImage, ButtonWidth - BlockMargin - RectImage.Right, 0);
OffsetRect(RectText, ButtonWidth - BlockWidth - BlockMargin, 0);
end;
end;
ButtonHeight := ButtonRect.Bottom - ButtonRect.Top;
OffsetRect(RectImage, ButtonRect.Left, (ButtonHeight - RectImage.Bottom) div 2 + ButtonRect.Top);
OffsetRect(RectText, ButtonRect.Left, (ButtonHeight - RectText.Bottom) div 2 + ButtonRect.Top);
end;
procedure TJvCustomImageButton.Click;
var
Form: TCustomForm;
Control: TWinControl;
begin
case FKind of
bkClose:
begin
Form := GetParentForm(Self);
if Form <> nil then
Form.Close
else
inherited Click;
end;
bkHelp:
begin
Control := Self;
while (Control <> nil) and (Control.HelpContext = 0) do
Control := Control.Parent;
if Control <> nil then
{$IFDEF VCL}
Application.HelpContext(Control.HelpContext)
{$ENDIF VCL}
{$IFDEF VisualCLX}
Application.HelpSystem.ShowContextHelp(Control.HelpContext, Application.HelpFile)
{$ENDIF VisualCLX}
else
inherited Click;
end;
else
inherited Click;
end;
end;
procedure TJvCustomImageButton.EnabledChanged;
begin
inherited EnabledChanged;
Invalidate;
end;
procedure TJvCustomImageButton.FontChanged;
begin
inherited FontChanged;
Invalidate;
end;
procedure TJvCustomImageButton.MouseEnter(Control: TControl);
begin
if csDesigning in ComponentState then
Exit;
if not FMouseInControl and Enabled and (GetCapture = NullHandle) then
begin
FMouseInControl := True;
inherited MouseEnter(Control);
{$IFDEF JVCLThemesEnabled}
if ThemeServices.ThemesEnabled then
Repaint
else
{$ENDIF JVCLThemesEnabled}
if Flat then
Invalidate;
end;
end;
procedure TJvCustomImageButton.MouseLeave(Control: TControl);
begin
if csDesigning in ComponentState then
Exit;
if FMouseInControl and Enabled and not Dragging then
begin
FMouseInControl := False;
inherited MouseLeave(Control);
{$IFDEF JVCLThemesEnabled}
if ThemeServices.ThemesEnabled then
Repaint
else
{$ENDIF JVCLThemesEnabled}
if Flat then
Invalidate;
end;
end;
{$IFDEF VCL}
procedure TJvCustomImageButton.CNDrawItem(var Msg: TWMDrawItem);
begin
if csDestroying in ComponentState then
Exit;
FCanvas.Handle := Msg.DrawItemStruct.hDC;
try
FCanvas.Font := Font;
if FOwnerDraw and Assigned(FOnButtonDraw) then
FOnButtonDraw(Self, Msg.DrawItemStruct{$IFNDEF CLR}^{$ENDIF})
else
DrawItem(Msg.DrawItemStruct{$IFNDEF CLR}^{$ENDIF});
finally
FCanvas.Handle := 0;
end;
end;
procedure TJvCustomImageButton.CNMeasureItem(var Msg: TWMMeasureItem);
{$IFDEF CLR}
var
MeasureItemStruct: TMeasureItemStruct;
{$ENDIF CLR}
begin
{$IFDEF CLR}
MeasureItemStruct := Msg.MeasureItemStruct;
MeasureItemStruct.itemWidth := Width;
MeasureItemStruct.itemHeight := Height;
Msg.MeasureItemStruct := MeasureItemStruct;
{$ELSE}
with Msg.MeasureItemStruct^ do
begin
itemWidth := Width;
itemHeight := Height;
end;
{$ENDIF CLR}
end;
{$ENDIF VCL}
{$IFDEF VisualCLX}
procedure TJvCustomImageButton.Paint;
var
DrawItemStruct: TDrawItemStruct;
begin
if csDestroying in ComponentState then
Exit;
with DrawItemStruct do
begin
itemState := 0;
if Focused or Default then
itemState := ODS_FOCUS;
if not Enabled then
itemState := ODS_DISABLED;
if Down then
itemState := ODS_SELECTED;
end;
FCanvas.Handle := inherited Canvas.Handle;
FCanvas.Start(False);
try
FCanvas.Font := Font;
if FOwnerDraw and Assigned(FOnButtonDraw) then
FOnButtonDraw(Self, DrawItemStruct)
else
DrawItem(DrawItemStruct);
finally
FCanvas.Stop;
FCanvas.Handle := NullHandle;
end;
end;
{$ENDIF VisualCLX}
procedure TJvCustomImageButton.DrawButtonFocusRect(const RectContent: TRect);
begin
if FIsFocused and not (csDestroying in ComponentState) then
begin
FCanvas.Pen.Color := clWindowFrame;
FCanvas.Brush.Color := clBtnFace;
DrawFocusRect(FCanvas.Handle, RectContent);
end;
end;
procedure TJvCustomImageButton.DrawButtonFrame(const DrawItemStruct: TDrawItemStruct; var RectContent: TRect);
var
IsDown, IsEnabled, IsDefault: Boolean;
R: TRect;
Flags: DWORD;
{$IFDEF JVCLThemesEnabled}
Details: TThemedElementDetails;
Button: TThemedButton;
{$ENDIF JVCLThemesEnabled}
begin
if csDestroying in ComponentState then
Exit;
with DrawItemStruct do
begin
IsEnabled := itemState and ODS_DISABLED = 0;
IsDown := (itemState and ODS_SELECTED <> 0) and IsEnabled;
IsDefault := itemState and ODS_FOCUS <> 0;
end;
{$IFDEF JVCLThemesEnabled}
if ThemeServices.ThemesEnabled then
begin
if not IsEnabled then
Button := tbPushButtonDisabled
else
if IsDown then
Button := tbPushButtonPressed
else
if FMouseInControl then
Button := tbPushButtonHot
else
if IsDefault then
Button := tbPushButtonDefaulted
else
Button := tbPushButtonNormal;
Details := ThemeServices.GetElementDetails(Button);
// Parent background.
ThemeServices.DrawParentBackground(Handle, DrawItemStruct.hDC, @Details, True);
// Button shape.
ThemeServices.DrawElement(DrawItemStruct.hDC, Details, DrawItemStruct.rcItem);
// Return content rect
RectContent := ThemeServices.ContentRect(FCanvas.Handle, Details, DrawItemStruct.rcItem);
end
else
{$ENDIF JVCLThemesEnabled}
begin
R := ClientRect;
if Flat then
begin
FCanvas.Brush.Color := Color;
FCanvas.FillRect(R); // (p3) TWinControls don't support Transparent anyway
if FMouseInControl or FIsFocused or (csDesigning in ComponentState) then
begin
if IsDown then
Frame3D(FCanvas, R, clBtnShadow, clBtnHighlight, 1)
else
Frame3D(FCanvas, R, clBtnHighlight, clBtnShadow, 1);
end;
end
else
begin
Flags := DFCS_BUTTONPUSH or DFCS_ADJUSTRECT;
if IsDown then
Flags := Flags or DFCS_PUSHED;
if not IsEnabled then
Flags := Flags or DFCS_INACTIVE;
if FIsFocused or IsDefault then
begin
if not IsEnabled then
FCanvas.Pen.Color := clInactiveCaption
else
{$IFDEF VCL}
FCanvas.Pen.Color := clWindowFrame;
{$ENDIF VCL}
{$IFDEF VisualCLX}
FCanvas.Pen.Color := clActiveShadow;
{$ENDIF VisualCLX}
FCanvas.Pen.Width := 1;
FCanvas.Brush.Style := bsClear;
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
InflateRect(R, -1, -1);
end;
if IsDown then
begin
FCanvas.Pen.Color := clBtnShadow;
FCanvas.Pen.Width := 1;
FCanvas.Brush.Color := clBtnFace;
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
InflateRect(R, -1, -1);
end
else
begin
{$IFDEF VisualCLX}
FCanvas.Start;
try
{$ENDIF VisualCLX}
DrawFrameControl(FCanvas.Handle, R, DFC_BUTTON, Flags);
{$IFDEF VisualCLX}
finally
FCanvas.Stop;
end;
{$ENDIF VisualCLX}
end;
FCanvas.Brush.Color := Color;
FCanvas.FillRect(R);
end;
// Return content rect
RectContent := ClientRect;
InflateRect(RectContent, -4, -4);
end;
end;
procedure TJvCustomImageButton.DrawButtonImage(ImageBounds: TRect);
{$IFDEF VisualCLX}
var
Glyph: TBitmap;
{$ENDIF VisualCLX}
begin
if csDestroying in ComponentState then
Exit;
with ImageBounds do
if IsImageVisible then
{$IFDEF VCL}
if Assigned(FImages) then
FImages.Draw(FCanvas, Left, Top, GetImageIndex, Enabled)
else
DefaultImgBtnImagesList.Draw(FCanvas, Left, Top, GetKindImageIndex, Enabled);
{$ENDIF VCL}
{$IFDEF VisualCLX}
if Assigned(FImages) then
FImages.Draw(FCanvas, Left, Top, GetImageIndex, itImage, Enabled)
else
begin
Glyph := TBitmap.Create;
DefaultImgBtnImagesList.GetBitmap(GetKindImageIndex, Glyph);
Glyph.TransparentColor := clOlive;
FCanvas.Draw(Left, Top, Glyph);
Glyph.Free;
end;
{$ENDIF VisualCLX}
end;
procedure TJvCustomImageButton.DrawButtonText(TextBounds: TRect; TextEnabled: Boolean);
var
Flags: DWORD;
RealCaption: string;
begin
Flags := DrawTextBiDiModeFlags(DT_VCENTER or Alignments[FAlignment]);
if WordWrap then
Flags := Flags or DT_WORDBREAK;
RealCaption := GetRealCaption;
with Canvas do
begin
Brush.Style := bsClear;
if not TextEnabled then
begin
OffsetRect(TextBounds, 1, 1);
Font.Color := clBtnHighlight;
DrawText(Canvas, RealCaption, Length(RealCaption), TextBounds, Flags);
OffsetRect(TextBounds, -1, -1);
Font.Color := clBtnShadow;
DrawText(Canvas, RealCaption, Length(RealCaption), TextBounds, Flags);
end
else
DrawText(Canvas, RealCaption, Length(RealCaption), TextBounds, Flags);
end;
end;
procedure TJvCustomImageButton.DrawItem(const DrawItemStruct: TDrawItemStruct);
var
R, RectContent, RectText, RectImage, RectArrow: TRect;
begin
DrawButtonFrame(DrawItemStruct, RectContent);
//R := ClientRect;
//InflateRect(R, -4, -4);
R := RectContent;
if (DrawItemStruct.itemState and ODS_SELECTED <> 0) and Enabled then
begin
{$IFDEF JVCLThemesEnabled}
if ThemeServices.ThemesEnabled then
OffsetRect(R, 1, 0)
else
{$ENDIF JVCLThemesEnabled}
OffsetRect(R, 1, 1);
end;
CalcButtonParts(R, RectText, RectImage);
if DropArrow and Assigned(DropDownMenu) then
begin
RectArrow := Rect(Width - 16, Height div 2, Width - 9, Height div 2 + 7);
if (DrawItemStruct.itemState and ODS_SELECTED <> 0) then
OffsetRect(RectArrow, 1, 1);
DrawDropArrow(FCanvas, RectArrow);
if (DrawItemStruct.itemState and ODS_SELECTED <> 0) then
OffsetRect(RectContent, 1, -1)
end;
DrawButtonText(RectText, Enabled);
DrawButtonImage(RectImage);
DrawButtonFocusRect(RectContent);
end;
function TJvCustomImageButton.GetActionLinkClass: TControlActionLinkClass;
begin
Result := TJvImgBtnActionLink;
end;
function TJvCustomImageButton.GetCustomCaption: string;
const
Captions: array [TJvImgBtnKind] of string =
('', SOKButton, SCancelButton, SHelpButton, SYesButton, SNoButton,
SCloseButton, SAbortButton, SRetryButton, SIgnoreButton, SAllButton);
begin
Result := Captions[FKind];
end;
function TJvCustomImageButton.GetImageIndex: Integer;
begin
if FAnimating then
begin
Result := FImageIndex + FCurrentAnimateFrame - 1;
if Assigned(FOnGetAnimateIndex) then
FOnGetAnimateIndex(Self, FCurrentAnimateFrame, Result);
end
else
Result := FImageIndex;
end;
function TJvCustomImageButton.GetImageList: TCustomImageList;
begin
if Assigned(FImages) then
Result := FImages
else
Result := DefaultImgBtnImagesList;
end;
function TJvCustomImageButton.GetKindImageIndex: Integer;
const
ImageKindIndexes: array [TJvImgBtnKind] of Integer =
(-1, 2, 4, 0, 3, 1, 5, 8, 6, 9, 7);
begin
Result := ImageKindIndexes[FKind];
end;
function TJvCustomImageButton.GetRealCaption: string;
begin
if (FKind <> bkCustom) and (Caption = '') then
Result := GetCustomCaption
else
Result := inherited GetRealCaption;
end;
procedure TJvCustomImageButton.ImageListChange(Sender: TObject);
begin
InvalidateImage;
end;
class procedure TJvCustomImageButton.InitializeDefaultImageList;
{$IFDEF VisualCLX}
var
ResBmp: TBitmap;
{$ENDIF VisualCLX}
begin
if not Assigned(DefaultImgBtnImagesList) then
begin
DefaultImgBtnImagesList := TImageList.CreateSize(18, 18);
{$IFDEF VCL}
DefaultImgBtnImagesList.ResourceLoad(rtBitmap, 'JvCustomImageButtonDEFAULT', clOlive);
{$ENDIF VCL}
{$IFDEF VisualCLX}
ResBmp := TBitmap.Create;
try
ResBmp.LoadFromResourceName(HInstance, 'JvCustomImageButtonDEFAULT');
DefaultImgBtnImagesList.Add(ResBmp, nil);
finally
ResBmp.Free;
end;
{$ENDIF VisualCLX}
end;
end;
procedure TJvCustomImageButton.InvalidateImage;
begin
Invalidate;
end;
function TJvCustomImageButton.IsImageVisible: Boolean;
begin
Result := FImageVisible and
((Assigned(FImages) and (GetImageIndex <> -1)) or
(not Assigned(FImages) and (FKind <> bkCustom)));
end;
procedure TJvCustomImageButton.Loaded;
begin
inherited Loaded;
if FAnimate then
StartAnimate;
end;
procedure TJvCustomImageButton.RestartAnimate;
begin
if FAnimating then
begin
StopAnimate;
StartAnimate;
InvalidateImage;
end;
end;
procedure TJvCustomImageButton.SetAlignment(const Value: TAlignment);
begin
if FAlignment <> Value then
begin
FAlignment := Value;
// For the alignment to be taken into account, the Margin value must
// not be equal to -1. A change of Alignment indicates that the user
// does not want the -1 margin value to take precedence
if Margin = -1 then
FMargin := 0;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetAnimate(const Value: Boolean);
begin
if FAnimate <> Value then
begin
FAnimate := Value;
if Value then
StartAnimate
else
StopAnimate;
InvalidateImage;
end;
end;
procedure TJvCustomImageButton.SetAnimateFrames(const Value: Integer);
begin
if FAnimateFrames <> Value then
begin
FAnimateFrames := Value;
RestartAnimate;
end;
end;
procedure TJvCustomImageButton.SetAnimateInterval(const Value: Cardinal);
begin
if FAnimateInterval <> Value then
begin
FAnimateInterval := Value;
RestartAnimate;
end;
end;
procedure TJvCustomImageButton.SetButtonStyle(ADefault: Boolean);
begin
if ADefault <> FIsFocused then
begin
FIsFocused := ADefault;
Refresh;
end;
end;
procedure TJvCustomImageButton.SetImageIndex(const Value: TImageIndex);
begin
if FImageIndex <> Value then
begin
FImageIndex := Value;
InvalidateImage;
end;
end;
procedure TJvCustomImageButton.SetImages(const Value: TCustomImageList);
begin
if FImages <> nil then
FImages.UnRegisterChanges(FImageChangeLink);
FImages := Value;
if FImages <> nil then
begin
FImages.RegisterChanges(FImageChangeLink);
FImages.FreeNotification(Self);
end
else
SetImageIndex(-1);
InvalidateImage;
end;
procedure TJvCustomImageButton.SetImageVisible(const Value: Boolean);
begin
if FImageVisible <> Value then
begin
FImageVisible := Value;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetKind(const Value: TJvImgBtnKind);
begin
if FKind <> Value then
begin
if Value <> bkCustom then
begin
Default := Value in [bkOK, bkYes];
Cancel := Value in [bkCancel, bkNo];
if not (csLoading in ComponentState) and (FKind = bkCustom) then
begin
Caption := '';
Images := nil;
end;
end;
ModalResult := JvImgBtnModalResults[Value];
FKind := Value;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetLayout(const Value: TJvImgBtnLayout);
begin
if FLayout <> Value then
begin
FLayout := Value;
if (csDesigning in ComponentState) and (FAlignment <> taCenter) then
case FLayout of
blImageLeft: FAlignment := taLeftJustify;
blImageRight: FAlignment := taRightJustify;
end;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetMargin(const Value: Integer);
begin
if (FMargin <> Value) and (Value >= -1) then
begin
FMargin := Value;
// Setting the value to -1 indicates that the user wants the alignment
// to be centered, so we force the value. This ensure coherence between
// this property and the Alignment property.
if (Value = -1) and (Alignment <> taCenter) then
FAlignment := taCenter;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetOwnerDraw(const Value: Boolean);
begin
if FOwnerDraw <> Value then
begin
FOwnerDraw := Value;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetSpacing(const Value: Integer);
begin
if FSpacing <> Value then
begin
FSpacing := Value;
Invalidate;
end;
end;
procedure TJvCustomImageButton.SetFlat(const Value: Boolean);
begin
if FFlat <> Value then
begin
FFlat := Value;
Invalidate;
end;
end;
procedure TJvCustomImageButton.ShowNextFrame;
begin
Inc(FCurrentAnimateFrame);
if FCurrentAnimateFrame > FAnimateFrames then
FCurrentAnimateFrame := 1;
InvalidateImage;
end;
procedure TJvCustomImageButton.StartAnimate;
begin
if ComponentState * [csDesigning, csLoading] = [] then
begin
DoubleBuffered := True;
FCurrentAnimateFrame := 0;
ShowNextFrame;
OSCheck(SetTimer(Handle, 1, FAnimateInterval, nil) <> 0);
FAnimating := True;
end;
end;
procedure TJvCustomImageButton.StopAnimate;
begin
if FAnimating then
begin
KillTimer(Handle, 1);
FCurrentAnimateFrame := 0;
DoubleBuffered := False;
FAnimating := False;
end;
end;
{$IFDEF VCL}
procedure TJvCustomImageButton.WMDestroy(var Msg: TWMDestroy);
begin
StopAnimate;
inherited;
end;
procedure TJvCustomImageButton.WMLButtonDblClk(var Msg: TWMLButtonDblClk);
begin
{$IFDEF CLR}
Perform(WM_LBUTTONDOWN, Msg.OriginalMessage.WParam, Msg.OriginalMessage.LParam);
{$ELSE}
Perform(WM_LBUTTONDOWN, Msg.Keys, Longint(Msg.Pos));
{$ENDIF CLR}
end;
{$ENDIF VCL}
{$IFDEF VisualCLX}
procedure TJvCustomImageButton.DestroyWidget;
begin
StopAnimate;
inherited DestroyWidget;
end;
{$ENDIF VisualCLX}
procedure TJvCustomImageButton.WMTimer(var Msg: TWMTimer);
begin
if Msg.TimerID = 1 then
begin
ShowNextFrame;
Msg.Result := 1;
end
else
inherited;
end;
initialization
{$IFDEF UNITVERSIONING}
RegisterUnitVersion(HInstance, UnitVersioning);
{$ENDIF UNITVERSIONING}
finalization
FreeAndNil(DefaultImgBtnImagesList);
{$IFDEF UNITVERSIONING}
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.