{

  Copyright (c) 1997-2003 by CoolDev.Com. Part of CoolControls package.

}

{$I versions.inc}
unit CoolCtrlsEx;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Commctrl, ShellApi, {$IFDEF DELPHI4_OR_ABOVE} ImgList, {$ENDIF} ComCtrls, CoolCtrls,
  CoolUtils, {$IFNDEF VER90} ToolWin, {$ENDIF} CoolTools, CoolLists, FileCtrl;

type
  {$IFDEF DELPHI4_OR_ABOVE}

  // TCoolCustomListView is advanced list view control. Wallpapers, transparency, color edges
  // and more enhancements for list view.
  TCoolCustomListView = class(TCustomListView)
  private
    FAboutBox: TCCAboutBox;

    FWallpaper: TBitmap;
    FSelWallpaper: TBitmap;
    FCaptionWallpaper: TBitmap;

    FSelColor,
    FCaptionColor,
    FCaptionTextColor: TColor;

    FOptions: TCoolOptions;

    FCoolImagesChangeLink: TCoolChangeLink;
    FCoolImages: TCoolImages;
    FidWallpaper,
    FidSelWallpaper,
    FidCaptionWallpaper: Integer;

    FTransparencyLevel: Byte;

    FEdgeBorders: TEdgeBorders;
    FBorderPen: TPen;
    FBordersTrColor: TColor;

    FShadowColor: TColor;
    FShadowSize: Byte;
    FShadowPos: TShadowPosition;
    FSimpleView: Boolean;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;

    procedure SetOptions(Value: TCoolOptions);
    procedure SetTransparencyLevel(Value: Byte);

    procedure SetCaptionColor(Value: TColor);
    procedure SetCaptionTextColor(Value: TColor);

    procedure SetCoolImages(Value: TCoolImages);
    procedure SetidWallpaper(Value: Integer);
    procedure SetidSelWallpaper(Value: Integer);
    procedure SetidCaptionWallpaper(Value: Integer);

    procedure SetWallpaper(Value: TBitmap);
    function GetWallpaper: TBitmap;
    procedure SetSelWallpaper(Value: TBitmap);
    function GetSelWallpaper: TBitmap;
    procedure SetCaptionWallpaper(Value: TBitmap);
    function GetCaptionWallpaper: TBitmap;

    procedure WallpaperChange(Sender: TObject);

    procedure SetShadowColor(Value: TColor);
    procedure SetShadowSize(Value: Byte);
    procedure SetShadowPos(Value: TShadowPosition);
    procedure SetSimpleView(Value: Boolean);

    function CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
    function CTLDrawCaptionWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
    function CTLDrawSelWallpaper(DC: HDC; R, SubRect: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
    function IsWallpaperAssigned: Boolean;
    function IsSelWallpaperAssigned: Boolean;
    procedure CoolImagesChange(Sender: TObject);

    procedure BorderPenChange(Sender: TObject);
    procedure SetEdgeBorders(Value: TEdgeBorders);
    procedure SetBorderPen(Value: TPen);
    procedure SetBordersTrColor(Value: TColor);

    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure WMPaint (var Message: TMessage); message WM_PAINT;
    procedure WMNCPaint (var Message: TMessage); message WM_NCPAINT;
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
    procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  protected
    OldViewOrigin: TPoint;
    {$IFNDEF DELPHI5_OR_ABOVE}
    procedure MyCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    {$ELSE}
    procedure MyAdvancedCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage; var DefaultDraw: Boolean);
    {$ENDIF}
    procedure NCCtlChanged; virtual;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Change(Item: TListItem; Change: Integer); override;
    procedure CreateWnd; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  public
    // It's possible to draw the edges (borders) for control. Based on EdgeBorders values you can control what borders will be drawn and the BorderPen property points to the pen object used to draw the borders around control.
    // 
    // See Also:
    //   EdgeBorders
    property BorderPen: TPen read FBorderPen write SetBorderPen;
    // If EdgeBorders specified (any) and BordersTrColor is different from clNone there will be painted borders for NON DEFINED edges with the BordersTrColor color. That makes sense if BorderStyle is bsSingle and you would like to make all but one or few edges transparent. Alternatively you can set BorderStyle to bsNone.
    //
    // See Also:
    //   EdgeBorders
    //   BorderPen
    property BordersTrColor: TColor read FBordersTrColor write SetBordersTrColor default clNone;
    // Some controls in the Coolcontrols package 
    // may have captions just like forms (they even 
    // can be dragged within the parent container). 
    // Appearance of the caption controlled by ocNoCaption flag 
    // (Options property)  Caption can be wide or small (ocSmallCaption flag).
    // 
    // Use CaptionColor to set Color of the control's Caption (when 
    // it is visible). clInctiveCaption is the default value.
    property CaptionColor: TColor read FCaptionColor write SetCaptionColor default clInactiveCaption;
    // Some controls in the Coolcontrols package may
    // have captions just like forms (they even can be 
    // dragged within the parent container). Appearance 
    // of the caption controlled by ocNoCaption flag (Options 
    // property)  Caption can be wide or small (ocSmallCaption flag).
    // 
    // Use CaptionTextColor to set the \color of the control's Caption 
    // text (when caption is visible). clInctiveCaptionText is the 
    // default value. The caption text itself is being set by Caption 
    // property.
    property CaptionTextColor: TColor read FCaptionTextColor write SetCaptionTextColor default clInactiveCaptionText;
    // Some controls in the CoolControls package may have 
    // captions just like forms (they even can be dragged 
    // within the parent container). Appearance of the caption 
    // controlled by ocNoCaption flag (Options property)  
    // Caption can be wide or small (ocSmallCaption flag).
    // 
    // Use CaptionWallpaper to specify the bitmap image to be 
    // painted as wallpaper for the caption (when caption is visible).  
    // 
    // There's another possible solution, instead of assigning 
    // CaptionWallpaper property you can use CoolImages and idCaptionWallpaper 
    // properties. This way you save system resources by using the same image for 
    // many controls.
    // 
    // See Also:
    //   Options
    //   idCaptionWallpaper
    //   CoolImages
    property CaptionWallpaper: TBitmap read GetCaptionWallpaper write SetCaptionWallpaper;
    // Use CoolImages property to specify  TCoolImages component will be used 
    // to load bitmaps for wallpapers from. TcoolImages acts much like 
    // TImageList that is behaves as placeholder for images. It can contain 
    // bitmaps only but bitmaps of different sizes and color modes can be stored 
    // together in the same object.
    property CoolImages: TCoolImages read FCoolImages write SetCoolImages;
    // It's possible to draw the edges (borders) for control. 
    // Based on EdgeBorders values you can control what borders 
    // will be drawn and the BorderPen property points to the 
    // pen object used to draw the borders around control. And  
    // the EdgeBorders property used to add or remove borders.
    property EdgeBorders: TEdgeBorders read FEdgeBorders write SetEdgeBorders default [];
    // Some controls in the CoolControls 
    // package may have captions just like 
    // forms (they even can be dragged within 
    // the parent container). Appearance of the 
    // caption controlled by ocNoCaption flag
    // (Options property)  Caption can be wide 
    // or small (ocSmallCaption flag).
    // 
    // Use CaptionWallpaper to specify the bitmap image 
    // to be painted as wallpaper for the caption 
    // (when caption is visible).  
    // 
    // There's another possible solution, instead of 
    // assigning CaptionWallpaper property you can 
    // use CoolImages and idCaptionWallpaper properties. This 
    // way you save system resources by using the 
    // same image for many controls.
    // 
    // See Also:
    //   Options
    //   CoolImages
    //   CaptionWallpaper
    property idCaptionWallpaper: Integer read FidCaptionWallpaper write SetidCaptionWallpaper default -1;
    // There's an opportunity to paint background image for 
    // selected items only. Among with using SelWallpaper there's 
    // a way to use CoolImages and idSelWallpaper 
    // properties to specify the image. This technique allows to 
    // save resources by using the same image for many controls.
    // IdSelWallpaper indicates the index of the image in TcoolImages 
    // container. If the control has Options property it's necessary to 
    // include ocPaintSelWallpaper flag into he Options set to actually 
    // enable the painting of the selected wallpaper.
    // 
    // See Also:
    //   Options
    //   CoolImages
    //   SelWallpaper
    property idSelWallpaper: Integer read FidSelWallpaper write SetidSelWallpaper default -1;
    // There's an alternative for direct assigning of 
    // the Wallpaper property for cases when you want 
    // to paint the image background for the 
    // control - use CoolImages and idWallpaper properties 
    // for that. This technique allows to save system resources 
    // by sharing the same image between many controls. IdWallpaper 
    // indicates the index of the image from CoolImages to be used. 
    // For controls that have Options property it's necessary to 
    // include ocPaintWallpaper flag (Options property) to enable 
    // the wallpaper painting.
    // 
    // See Also:
    //   Options
    //   CoolImages
    //   Wallpaper
    property idWallpaper: Integer read FidWallpaper write SetidWallpaper default -1;
    // Options property controls variety of various controls parameters, the combination of included and excluded flags  determines appearance and behavior of the control. The following items that being used separately or in combination define control's look, note that some flags can not be used together and the others can or even must, note also that not all flags can be supported by the particular control or component.
    // These flags can be used with the following meaning:
    // <P>
    // * <I>ocPaintWallpaper.</I> Whether you want to paint the wallpaper for control. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocPaintSelWallpaper.</I> Whether you want to paint the wallpaper for selected items. SelWallpaper or combination of  CoolImages and idSelWallpaper properties must be assigned properly.
    // * <I>ocStretchWallpaper.</I> Whether you like to stretch the image to fit all the control surface. If false image will be repeatedly painted to fill the control (tiled).
    // * <I>ocPaintCaptionWallpaper.</I> Whether you want to paint the wallpaper for control's caption (if the latest is visible). CaptionWallpaper or combination of  CoolImages and idCaptionWallpaper properties must be assigned properly.
    // * <I>ocPaintGradiently.</I> Whether you  want to paint the gradient background. Respective color properties define the background range colors.
    // * <I>ocInvertWallpaperAsSelect.</I> Whether you want to use the same wallpaper you use for control to highlight selected items. When presents selected items will be drawn using inverted Wallpaper image, Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocBevelOnlyIfSel.</I> Whether you like to paint bevel around all the control items or only around those selected. 
    // * <I>ocNoHighlightImage.</I> If the items have attached images determines whether those for selected items should or should not be highlighted among with the item.
    // * <I>ocNoImageAttached.</I> Whether control presumes that its items some with attached images If not there will not be extra space between border and items
    // * <I>ocUseImageList.</I> Whether images should be taken from the linked Image List component or directly from the Glyph property. 
    // * <I>oc3dMDIForm.</I> Whether MDI parent form has more 3D look.
    // * <I>ocWallpaperForMDIChildren.</I> Whether attached wallpaper should be painted for all MDI child windows. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocNoCaption.</I> Whether control has caption area. Some controls will not have caption even if this property set to True.
    // * <I>ocSmallCaption.</I> What kind of caption should be used for window (if possible) standard or small caption (like for tool windows).
    // * <I>ocNoMDIChildrensCaptions.</I> Whether MDI child windows should  be drawn with the captions.
    // * <I>ocDragUsingClientArea.</I> Is it possible to drag the form using its client area.
    // * <I>ocNoDragUsingCaption.</I> Is it possible to drag the form using its caption area.
    // * <I>ocRoundedForm.</I> Whether the form should have oval shape.
    // * <I>ocFlatBorder.</I> Whether control should be painted with the modern flat look.
    // * <I>ocPaintTransparently.</I> Whether the control should have its own background or use that of the parent container.
    property Options: TCoolOptions read FOptions write SetOptions default [ocNoCaption];
    // SelColor indicates the \color to be used to highlight selected items.
    property SelColor: TColor read FSelColor write FSelColor default clHighlight;
    // There's an opportunity to paint background image 
    // for selected items only. Use SelWallpaper 
    // to specify the image to be painted as wallpaper 
    // for selected items. Among with using SelWallpaper 
    // there's a way to use CoolImages and idSelWallpaper 
    // properties to specify the image. This technique 
    // allows to save resources by using the same image 
    // for many controls. IdSelWallpaper indicates the 
    // index of the image in TcoolImages container. If the 
    // control has Options property it's necessary to include 
    // ocPaintSelWallpaper flag into he Options set to 
    // actually enable the painting of the selected wallpaper.
    // 
    // See Also:
    //   Options
    //   idSelWallpaper
    //   CoolImages
    property SelWallpaper: TBitmap read GetSelWallpaper write SetSelWallpaper;
    // Use TransparencyLevel to specify the 
    // parent control whose part will be used 
    // to draw the background of the component. 
    // For example if control placed on the panel 
    // that is placed on the form, setting TransparencyLevel 
    // to 0 will force part of the panel to be used for 
    // painting of the transparent background, setting 
    // TransparencyLevel to 1 will force the part of the 
    // form to be selected on the controls device context 
    // when paint transparently.
    property TransparencyLevel: Byte read FTransparencyLevel write SetTransparencyLevel default 0;
    // Use Wallpaper to specify the bitmap image 
    // that will be painted as background wallpaper 
    // for a control. In most cases CoolControls package 
    // requires ocPaintWallpaper flag included into 
    // Options property set in order to actually enable 
    // wallpaper painting. Mind you that there's an 
    // alternative way to attach the image to be painted 
    // on control's background - use CoolImages and idWallpaper 
    // properties for that. This technique allows to save system 
    // resources by sharing the same image between many controls.
    //
    // See Also:
    //   Options
    //   idWallpaper
    //   CoolImages
    property Wallpaper: TBitmap read GetWallpaper write SetWallpaper;

    // In the CoolControls package many controls that 
    // have captions or string items allow to paint 
    // these with the 3D effect. When you use this feature, 
    // use ShadowColor to set the color of the shadow dropped. 
    // The effect being achieved by painting the text 
    // twice - once with the main color and then with the 
    // ShadowColor (allowing ShadowSize offset).
    // 
    // See Also:
    //   ShadowSize
    //   ShadowPos
    //   SimpleView
    property ShadowColor: TColor read FShadowColor write SetShadowColor default clBtnHighlight;
    // In the CoolControls package many controls that have captions 
    // or string items allow to paint these with the 3D effect. 
    // When you use this feature, use ShadowSiize to indicate the 
    // offset  of the shadow dropped. The effect being achieved by
    // painting the text twice - once with the main color and then 
    // with the ShadowColor (allowing ShadowSize offset).
    // 
    // See Also:
    //   ShadowPos
    //   ShadowColor
    //   SimpleView
    property ShadowSize: Byte read FShadowSize write SetShadowSize default 1;
    // In the CoolControls package many controls that have captions or 
    // string items allow to paint these with the 3D effect. When 
    // you use this feature, use ShadowPos to indicate the position 
    // (relatively to the main text) of the shadow dropped. The effect 
    // being achieved by painting the text twice - once with the main 
    // color and then with the ShadowColor (allowing ShadowSize offset).
    // 
    // <TABLE>
    // Value              Meaning
    // -------            -------------------------
    // spLeftTop          Shadow is in the Left Top direction.
    // spLeftBottom       Shadow is in the Left Bottom direction.
    // spRightBottom      Shadow is in the Right Bottom direction.
    // spRightTop         Shadow is in the Right Top direction.
    // </TABLE>
    // 
    // See Also:
    //   ShadowSize
    //   ShadowColor
    //   SimpleView
    property ShadowPos: TShadowPosition read FShadowPos write SetShadowPos default spLeftTop;
    // In the CoolControls package many controls that have 
    // captions or string items allow to paint these with 
    // the 3D effect. When you use this feature, use ShadowPos 
    // to indicate the position (relatively to the main text) 
    // of the shadow dropped. The effect being achieved by 
    // painting the text twice - once with the main color and 
    // then with the ShadowColor (allowing ShadowSize offset).
    // Use SimpleView to indicate whether you want to use the 
    // described feature  or you do not.
    // 
    // See Also:
    //   ShadowSize
    //   ShadowPos
    //   ShadowColor
    property SimpleView: Boolean read FSimpleView write SetSimpleView default False;

    // OnMouseEnter event occurs immediately after mouse cursor enters the control.
    property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    // OnMouseLeave event occurs immediately after mouse cursor leaves the control.
    property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
  end;

  // TCoolListView publishes properties  defined in the TCoolCustomListView
  TCoolListView = class(TCoolCustomListView)
  published
    property BorderPen;
    property BordersTrColor;
    property CaptionColor;
    property CaptionTextColor;
    property CaptionWallpaper;
    property CoolImages;
    property EdgeBorders;
    property idCaptionWallpaper;
    property idSelWallpaper;
    property idWallpaper;
    property Options;
    property SelColor;
    property SelWallpaper;
    property TransparencyLevel;
    property ShadowColor;
    property ShadowSize;
    property ShadowPos;
    property SimpleView;
    property Wallpaper;

    property Align;
    property AllocBy;
    property Anchors;
    property BiDiMode;
    property BorderStyle;
    property BorderWidth;
    property Checkboxes;
    property Caption;
    property Color;
    property ColumnClick;
    property Columns;
    property Constraints;
    property Cursor;
    property Font;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property FlatScrollBars;
    property FullDrag;
    property GridLines;
    property HideSelection;
    property Hint;
    property HotTrack;
    property HotTrackStyles;
    {$IFDEF DELPHI5_OR_ABOVE}
    property HoverTime;
    {$ENDIF}
    property IconOptions;
    property Items;
    property LargeImages;
    property MultiSelect;
    property OwnerData;
    property ParentBiDiMode;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly;
    property SmallImages;
    property ShowColumnHeaders;
    property ShowHint;
    {$IFDEF DELPHI5_OR_ABOVE}
    property ShowWorkAreas;
    {$ENDIF}
    property SortType;
    property TabOrder;
    property ViewStyle;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnAdvancedCustomDraw;
    property OnAdvancedCustomDrawItem;
    property OnAdvancedCustomDrawSubItem;
    {$ENDIF}
    property OnChange;
    property OnChanging;
    property OnClick;
    property OnColumnClick;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnColumnDragged;
    property OnColumnRightClick;
    {$ENDIF}
    property OnCompare;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnContextPopup;
    {$ENDIF}
    property OnCustomDraw;
    property OnCustomDrawItem;
    property OnCustomDrawSubItem;
    property OnData;
    property OnDataFind;
    property OnDataHint;
    property OnDataStateChange;
    property OnDblClick;
    property OnDeletion;
    property OnDrawItem;
    property OnEdited;
    property OnEditing;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnGetImageIndex;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnGetSubItemImage;
    {$ENDIF}
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnInfoTip;
    {$ENDIF}
    property OnInsert;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnSelectItem;
    property OnStartDock;
    property OnStartDrag;

    property OnMouseEnter;
    property OnMouseLeave;
  end;

  // Event defines action that occurs in a responce to double click on an item.
  TIconDblClickEvent = procedure(Sender: TObject; ItemCaption: string) of Object;

  // TCoolExplorerListView is an advanced class that provides functionality similar
  // to the explorer, that is allows to display contents of the folder, supports drag-and-drop
  // and provides with the ability to customize the appearance of the data.
  TCoolExplorerListView = class(TCoolCustomListView)
  private
    FDirectory: TFileName;
    FFileMask: string;
    FFileType: TFileType;

    FMemStream: TMemoryStream;
    FOnIconDblClick: TIconDblClickEvent;

    procedure SetDirectory(Value: TFileName);
    procedure SetFileMask(Value: string);
    procedure SetFileType(Value: TFileType);

    procedure WMDropFiles(var Message: TWMDropFiles); message WM_DROPFILES;
    procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWnd; override;
    procedure DestroyWnd; override;
    procedure Delete(Item: TListItem); override;
    procedure Edit(const Item: TLVItem); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure DragDrop(Source: TObject; X, Y: Integer); override;
    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;

    // Use SaveToStream to save list view's contents into the stream.
    //
    // Parameters:
    //   AStream  - stream the list view's contents will be saved to.
    procedure SaveToStream(Stream: TStream);
    // Use LoadFromStream to load list view's contents from the stream.
    //
    // Parameters:
    //   AStream  - stream the list view's contents will be loaded from.
    procedure LoadFromStream(Stream: TStream);
     // Use SaveToFile to save list view's contents into the file.
    //
    // Parameters:
    //   FileName  - name of the file the list view's contents will be saved to.
   procedure SaveToFile(FileName: TFileName);
    // Use LoadFromFile to load list view's contents from the file.
    //
    // Parameters:
    //   FileName  - file the list view's contents will be loaded from.
    procedure LoadFromfile(FileName: TFileName);
  published
    // Use Directory to specify the folder which contents will be displayed 
    // by the control.  
    property Directory: TFileName read FDirectory write SetDirectory;
    // You may want to limit the files count to these matching the mask given. 
    // Any valid DOS mask acceptable.
    property FileMask: string read FFileMask write SetFileMask;
    // Use FileType to specify file types to be displayed by the control.
    // 
    //<TABLE>
    // Value                    Meaning
    // -----                    -------
    // ftReadOnly		Displays files with the read-only attribute.
    // ftHidden			Displays files with the hidden attribute.
    // ftSystem			Displays system files.
    // ftVolumeID		Displays the volume name.
    // ftDirectory		Displays directories.
    // ftArchive		Displays files with archive attribute.
    // ftNormal			Displays files with no special attributes.
    //</TABLE>
    property FileType: TFileType read FFileType write SetFileType default [ftDirectory, ftArchive];    
    // Event occurs when user double-click's the particular item (icon).
    property OnIconDblClick: TIconDblClickEvent read FOnIconDblClick write FOnIconDblClick;

    property BorderPen;
    property BordersTrColor;
    property CaptionColor;
    property CaptionTextColor;
    property CaptionWallpaper;
    property CoolImages;
    property EdgeBorders;
    property idCaptionWallpaper;
    property idSelWallpaper;
    property idWallpaper;
    property Options;
    property SelColor;
    property SelWallpaper;
    property TransparencyLevel;
    property ShadowColor;
    property ShadowSize;
    property ShadowPos;
    property SimpleView;
    property Wallpaper;

    property Align;
    property AllocBy;
    property Anchors;
    property BiDiMode;
    property BorderStyle;
    property BorderWidth;
    property Checkboxes;
    property Caption;
    property Color;
    property ColumnClick;
    property Columns;
    property Constraints;
    property Cursor;
    property Font;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property FlatScrollBars;
    property FullDrag;
    property GridLines;
    property HideSelection;
    property Hint;
    property HotTrack;
    property HotTrackStyles;
    {$IFDEF DELPHI5_OR_ABOVE}
    property HoverTime;
    {$ENDIF}
    property IconOptions;
    property MultiSelect;
    property OwnerData;
    property ParentBiDiMode;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly;
    property ShowColumnHeaders;
    property ShowHint;
    {$IFDEF DELPHI5_OR_ABOVE}
    property ShowWorkAreas;
    {$ENDIF}
    property SortType;
    property TabOrder;
    property ViewStyle;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnAdvancedCustomDraw;
    property OnAdvancedCustomDrawItem;
    property OnAdvancedCustomDrawSubItem;
    {$ENDIF}
    property OnChange;
    property OnChanging;
    property OnClick;
    property OnColumnClick;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnColumnDragged;
    property OnColumnRightClick;
    {$ENDIF}
    property OnCompare;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnContextPopup;
    {$ENDIF}
    property OnCustomDraw;
    property OnCustomDrawItem;
    property OnCustomDrawSubItem;
    property OnData;
    property OnDataFind;
    property OnDataHint;
    property OnDataStateChange;
    property OnDblClick;
    property OnDeletion;
    property OnDrawItem;
    property OnEdited;
    property OnEditing;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnGetImageIndex;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnGetSubItemImage;
    {$ENDIF}
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnInfoTip;
    {$ENDIF}
    property OnInsert;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnSelectItem;
    property OnStartDock;
    property OnStartDrag;

    property OnMouseEnter;
    property OnMouseLeave;
  end;

  {$ENDIF}

  // TCoolScrollBox is advanced s croll box control. Wallpapers, transparency and more features supported.
  TCoolScrollBox = class(TScrollBox)
  private
    FAboutBox: TCCAboutBox;
    FOptions: TCoolOptions;
    FTransparencyLevel: Byte;
    FWallpaper: TBitmap;

    FCoolImages: TCoolImages;
    FidWallpaper: Integer;
    FCoolImagesChangeLink: TCoolChangeLink;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;

    procedure SetOptions(Value: TCoolOptions);
    function GetWallpaper: TBitmap;
    procedure SetWallpaper(Value: TBitmap);
    procedure SetTransparencyLevel(Value: Byte);
    procedure WallpaperChanged(Sender: TObject);

    procedure SetCoolImages(Value: TCoolImages);
    procedure SetidWallpaper(Value: Integer);
    function IsWallpaperAssigned: Boolean;
    function CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
    procedure CoolImagesChange(Sender: TObject);

    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
    procedure WMEraseBkGnd(var Message: TWMEraseBkGnd); message WM_ERASEBKGND;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use CoolImages property to specify  TCoolImages component will be used 
    // to load bitmaps for wallpapers from. TcoolImages acts much like 
    // TImageList that is behaves as placeholder for images. It can contain 
    // bitmaps only but bitmaps of different sizes and color modes can be stored 
    // together in the same object.
    property CoolImages: TCoolImages read FCoolImages write SetCoolImages;
    // There's an alternative for direct assigning of 
    // the Wallpaper property for cases when you want 
    // to paint the image background for the 
    // control - use CoolImages and idWallpaper properties 
    // for that. This technique allows to save system resources 
    // by sharing the same image between many controls. IdWallpaper 
    // indicates the index of the image from CoolImages to be used. 
    // For controls that have Options property it's necessary to 
    // include ocPaintWallpaper flag (Options property) to enable 
    // the wallpaper painting.
    // 
    // See Also:
    //   Options
    //   CoolImages
    //   Wallpaper
    property idWallpaper: Integer read FidWallpaper write SetidWallpaper default -1;
    // Use Wallpaper to specify the bitmap image 
    // that will be painted as background wallpaper 
    // for a control. In most cases CoolControls package 
    // requires ocPaintWallpaper flag included into 
    // Options property set in order to actually enable 
    // wallpaper painting. Mind you that there's an 
    // alternative way to attach the image to be painted 
    // on control's background - use CoolImages and idWallpaper 
    // properties for that. This technique allows to save system 
    // resources by sharing the same image between many controls.
    // 
    // See Also:
    //   Options
    //   idWallpaper
    //   CoolImages
    property Wallpaper: TBitmap read GetWallpaper write SetWallpaper;
    // Options property controls variety of various controls parameters, the combination of included and excluded flags  determines appearance and behavior of the control. The following items that being used separately or in combination define control's look, note that some flags can not be used together and the others can or even must, note also that not all flags can be supported by the particular control or component.
    // These flags can be used with the following meaning:
    // <P>
    // * <I>ocPaintWallpaper.</I> Whether you want to paint the wallpaper for control. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocPaintSelWallpaper.</I> Whether you want to paint the wallpaper for selected items. SelWallpaper or combination of  CoolImages and idSelWallpaper properties must be assigned properly.
    // * <I>ocPaintCaptionWallpaper.</I> Whether you want to paint the wallpaper for control's caption (if the latest is visible). CaptionWallpaper or combination of  CoolImages and idCaptionWallpaper properties must be assigned properly.
    // * <I>ocPaintGradiently.</I> Whether you  want to paint the gradient background. Respective color properties define the background range colors.
    // * <I>ocInvertWallpaperAsSelect.</I> Whether you want to use the same wallpaper you use for control to highlight selected items. When presents selected items will be drawn using inverted Wallpaper image, Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocBevelOnlyIfSel.</I> Whether you like to paint bevel around all the control items or only around those selected. 
    // * <I>ocNoHighlightImage.</I> If the items have attached images determines whether those for selected items should or should not be highlighted among with the item.
    // * <I>ocNoImageAttached.</I> Whether control presumes that its items some with attached images If not there will not be extra space between border and items
    // * <I>ocUseImageList.</I> Whether images should be taken from the linked Image List component or directly from the Glyph property. 
    // * <I>oc3dMDIForm.</I> Whether MDI parent form has more 3D look.
    // * <I>ocWallpaperForMDIChildren.</I> Whether attached wallpaper should be painted for all MDI child windows. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocNoCaption.</I> Whether control has caption area. Some controls will not have caption even if this property set to True.
    // * <I>ocSmallCaption.</I> What kind of caption should be used for window (if possible) standard or small caption (like for tool windows).
    // * <I>ocNoMDIChildrensCaptions.</I> Whether MDI child windows should  be drawn with the captions.
    // * <I>ocDragUsingClientArea.</I> Is it possible to drag the form using its client area.
    // * <I>ocNoDragUsingCaption.</I> Is it possible to drag the form using its caption area.
    // * <I>ocRoundedForm.</I> Whether the form should have oval shape.
    // * <I>ocFlatBorder.</I> Whether control should be painted with the modern flat look.
    // * <I>ocPaintTransparently.</I> Whether the control should have its own background or use that of the parent container.
    property Options: TCoolOptions read FOptions write SetOptions default [];
    // Use TransparencyLevel to specify the 
    // parent control whose part will be used 
    // to draw the background of the component. 
    // For example if control placed on the panel 
    // that is placed on the form, setting TransparencyLevel 
    // to 0 will force part of the panel to be used for 
    // painting of the transparent background, setting 
    // TransparencyLevel to 1 will force the part of the 
    // form to be selected on the controls device context 
    // when paint transparently.
    property TransparencyLevel: Byte read FTransparencyLevel write SetTransparencyLevel default 0;
    // OnMouseEnter event occurs immediately after mouse cursor enters the control.
    property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    // OnMouseLeave event occurs immediately after mouse cursor leaves the control.
    property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  end;

  TCoolPageControl = class;

  // TCoolTabSheet represents page of the TCoolPageControl control.
  TCoolTabSheet = class(TWinControl)
  private
    FImageIndex: {$IFDEF DELPHI5_OR_ABOVE}TImageIndex{$ELSE}Integer{$ENDIF};
    FPageControl: TCoolPageControl;
    FTabVisible: Boolean;
    FTabShowing: Boolean;
    FHighlighted: Boolean;
    FOnHide: TNotifyEvent;
    FOnShow: TNotifyEvent;

    FAboutBox: TCCAboutBox;
    FWallpaper: TBitmap;
    FidWallpaper: Integer;
    FTransparencyLevel: Byte;
    FCoolImagesChangeLink: TCoolChangeLink;
    FCoolImages: TCoolImages;
    FOptions: TCoolOptions;
    FParentWallpaper: Boolean;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;

    procedure SetOptions(Value: TCoolOptions);
    procedure SetWallpaper(Value: TBitmap);
    function GetWallpaper: TBitmap;
    procedure WallpaperChanged(Sender: TObject);
    procedure SetCoolImages(Value: TCoolImages);
    procedure SetidWallpaper(Value: Integer);
    procedure SetTransparencyLevel(Value: Byte);
    procedure CoolImagesChange(Sender: TObject);
    function CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
    function IsWallpaperAssigned: Boolean;
    procedure SetParentWallpaper(Value: Boolean);

    function GetPageIndex: Integer;
    function GetTabIndex: Integer;
    procedure SetHighlighted(Value: Boolean);
    procedure SetImageIndex(Value: {$IFDEF DELPHI5_OR_ABOVE}TImageIndex{$ELSE}Integer{$ENDIF});
    procedure SeTCoolPageControl(APageControl: TCoolPageControl);
    procedure SetPageIndex(Value: Integer);
    procedure SetTabShowing(Value: Boolean);
    procedure SetTabVisible(Value: Boolean);
    procedure UpdateTabShowing;
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;

    procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure DoHide; dynamic;
    procedure DoShow; dynamic;
    procedure ReadState(Reader: TReader); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // TCooolPageControl current class related to.
    property PageControl: TCoolPageControl read FPageControl write SeTCoolPageControl;
    // Index in the parent TCoolPageControl pages list.
    property TabIndex: Integer read GetTabIndex;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use CoolImages property to specify  TCoolImages component will be used 
    // to load bitmaps for wallpapers from. TcoolImages acts much like 
    // TImageList that is behaves as placeholder for images. It can contain 
    // bitmaps only but bitmaps of different sizes and color modes can be stored 
    // together in the same object.
    property CoolImages: TCoolImages read FCoolImages write SetCoolImages;
    // Options property controls variety of various controls parameters, the combination of included and excluded flags  determines appearance and behavior of the control. The following items that being used separately or in combination define control's look, note that some flags can not be used together and the others can or even must, note also that not all flags can be supported by the particular control or component.
    // These flags can be used with the following meaning:
    // <P>
    // * <I>ocPaintWallpaper.</I> Whether you want to paint the wallpaper for control. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocPaintSelWallpaper.</I> Whether you want to paint the wallpaper for selected items. SelWallpaper or combination of  CoolImages and idSelWallpaper properties must be assigned properly.
    // * <I>ocPaintCaptionWallpaper.</I> Whether you want to paint the wallpaper for control's caption (if the latest is visible). CaptionWallpaper or combination of  CoolImages and idCaptionWallpaper properties must be assigned properly.
    // * <I>ocPaintGradiently.</I> Whether you  want to paint the gradient background. Respective color properties define the background range colors.
    // * <I>ocInvertWallpaperAsSelect.</I> Whether you want to use the same wallpaper you use for control to highlight selected items. When presents selected items will be drawn using inverted Wallpaper image, Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocBevelOnlyIfSel.</I> Whether you like to paint bevel around all the control items or only around those selected. 
    // * <I>ocNoHighlightImage.</I> If the items have attached images determines whether those for selected items should or should not be highlighted among with the item.
    // * <I>ocNoImageAttached.</I> Whether control presumes that its items some with attached images If not there will not be extra space between border and items
    // * <I>ocUseImageList.</I> Whether images should be taken from the linked Image List component or directly from the Glyph property. 
    // * <I>oc3dMDIForm.</I> Whether MDI parent form has more 3D look.
    // * <I>ocWallpaperForMDIChildren.</I> Whether attached wallpaper should be painted for all MDI child windows. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocNoCaption.</I> Whether control has caption area. Some controls will not have caption even if this property set to True.
    // * <I>ocSmallCaption.</I> What kind of caption should be used for window (if possible) standard or small caption (like for tool windows).
    // * <I>ocNoMDIChildrensCaptions.</I> Whether MDI child windows should  be drawn with the captions.
    // * <I>ocDragUsingClientArea.</I> Is it possible to drag the form using its client area.
    // * <I>ocNoDragUsingCaption.</I> Is it possible to drag the form using its caption area.
    // * <I>ocRoundedForm.</I> Whether the form should have oval shape.
    // * <I>ocFlatBorder.</I> Whether control should be painted with the modern flat look.
    // * <I>ocPaintTransparently.</I> Whether the control should have its own background or use that of the parent container.
    property Options: TCoolOptions read FOptions write SetOptions default [];
    // There's an alternative for direct assigning of 
    // the Wallpaper property for cases when you want 
    // to paint the image background for the 
    // control - use CoolImages and idWallpaper properties 
    // for that. This technique allows to save system resources 
    // by sharing the same image between many controls. IdWallpaper 
    // indicates the index of the image from CoolImages to be used. 
    // For controls that have Options property it's necessary to 
    // include ocPaintWallpaper flag (Options property) to enable 
    // the wallpaper painting.
    // 
    // See Also:
    //   Options
    //   CoolImages
    //   Wallpaper
    property idWallpaper: Integer read FidWallpaper write SetidWallpaper default -1;
    // Determines whether the component should use (display) wallpapers attached to the parent TCoolPageControl.
    property ParentWallpaper: Boolean read FParentWallpaper write SetParentWallpaper default True;
    // Use TransparencyLevel to specify the 
    // parent control whose part will be used 
    // to draw the background of the component. 
    // For example if control placed on the panel 
    // that is placed on the form, setting TransparencyLevel 
    // to 0 will force part of the panel to be used for 
    // painting of the transparent background, setting 
    // TransparencyLevel to 1 will force the part of the 
    // form to be selected on the controls device context 
    // when paint transparently.
    property TransparencyLevel: Byte read FTransparencyLevel write SetTransparencyLevel default 0;
    // Use Wallpaper to specify the bitmap image 
    // that will be painted as background wallpaper 
    // for a control. In most cases CoolControls package 
    // requires ocPaintWallpaper flag included into 
    // Options property set in order to actually enable 
    // wallpaper painting. Mind you that there's an 
    // alternative way to attach the image to be painted 
    // on control's background - use CoolImages and idWallpaper 
    // properties for that. This technique allows to save system 
    // resources by sharing the same image between many controls.
    // 
    // See Also:
    //   Options
    //   idWallpaper
    //   CoolImages
    property Wallpaper: TBitmap read GetWallpaper write SetWallpaper;

    {$IFDEF DELPHI4_OR_ABOVE}
    property BorderWidth;
    {$ENDIF}
    property Caption;
    property Color;
    property DragMode;
    property Enabled;
    property Font;
    property Height stored False;
    property Highlighted: Boolean read FHighlighted write SetHighlighted default False;
    property ImageIndex: {$IFDEF DELPHI5_OR_ABOVE}TImageIndex{$ELSE}Integer{$ENDIF} read FImageIndex write SetImageIndex default 0;
    property Left stored False;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Constraints;
    {$ENDIF}
    property PageIndex: Integer read GetPageIndex write SetPageIndex stored False;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabVisible: Boolean read FTabVisible write SetTabVisible default True;
    property Top stored False;
    property Visible stored False;
    property Width stored False;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnContextPopup;
    {$ENDIF}
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    // Event fired when the page becomes invisible.
    property OnHide: TNotifyEvent read FOnHide write FOnHide;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnResize;
    {$ENDIF}
    // Event fired when the page becomes visible.
    property OnShow: TNotifyEvent read FOnShow write FOnShow;
    property OnStartDrag;
  end;

  // TCoolPageControl is advanced page control component that comes with the  
  // features such as wallpapers, transparency and more.
  TCoolPageControl = class(TCustomTabControl)
  private
    FPages: TList;
    FActivePage: TCoolTabSheet;
    {$IFDEF DELPHI4_OR_ABOVE}
    FNewDockSheet: TCoolTabSheet;
    {$ENDIF}
    FUndockingPage: TCoolTabSheet;

    FAboutBox: TCCAboutBox;
    FWallpaper: TBitmap;
    FidWallpaper: Integer;
    FTransparencyLevel: Byte;
    FCoolImagesChangeLink: TCoolChangeLink;
    FCoolImages: TCoolImages;
    FOptions: TCoolOptions;
    FWallpaperWholeControl: Boolean;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;

    procedure SetOptions(Value: TCoolOptions);
    procedure SetWallpaper(Value: TBitmap);
    function GetWallpaper: TBitmap;
    procedure WallpaperChanged(Sender: TObject);
    procedure SetCoolImages(Value: TCoolImages);
    procedure SetidWallpaper(Value: Integer);
    procedure SetTransparencyLevel(Value: Byte);
    procedure CoolImagesChange(Sender: TObject);
    function CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
    function IsWallpaperAssigned: Boolean;
    procedure SetWallpaperWholeControl(Value: Boolean);

    procedure CMDesignHitTest(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
    procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
    {$IFDEF DELPHI4_OR_ABOVE}
    procedure CMDockClient(var Message: TCMDockClient); message CM_DOCKCLIENT;
    procedure CMDockNotification(var Message: TCMDockNotification); message CM_DOCKNOTIFICATION;
    procedure CMUnDockClient(var Message: TCMUnDockClient); message CM_UNDOCKCLIENT;
    {$ENDIF}
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;

    procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  protected
    {$IFDEF DELPHI4_OR_ABOVE}
    function CanShowTab(TabIndex: Integer): Boolean; override;
    {$ENDIF}
    procedure Change; override;
    {$IFDEF DELPHI4_OR_ABOVE}
    procedure DoAddDockClient(Client: TControl; const ARect: TRect); override;
    procedure DockOver(Source: TDragDockObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean); override;
    procedure DoRemoveDockClient(Client: TControl); override;
    {$ENDIF}
    {$IFNDEF VER90}
    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
    {$ENDIF}
    {$IFDEF DELPHI4_OR_ABOVE}
    function GetImageIndex(TabIndex: Integer): Integer; override;
    function GetPageFromDockClient(Client: TControl): TCoolTabSheet;
    procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect;
      MousePos: TPoint; var CanDock: Boolean); override;
    {$ENDIF}
    procedure Loaded; override;
    procedure SetChildOrder(Child: TComponent; Order: Integer); override;
    procedure ShowControl(AControl: TControl); override;
    procedure UpdateActivePage; virtual;
    {$IFDEF DELPHI4_OR_ABOVE}
    procedure DrawTab(TabIndex: Integer; const Rect: TRect; Active: Boolean); override;
    {$ENDIF}
  public
    procedure ChangeActivePage(Page: TCoolTabSheet);
    procedure DeleteTab(Page: TCoolTabSheet; Index: Integer);
    function GetActivePageIndex: Integer;
    {$IFDEF DELPHI4_OR_ABOVE}
    function GetDockClientFromMousePos(MousePos: TPoint): TControl;
    {$ENDIF}
    function NewPage: TCoolTabSheet;
    function GetPage(Index: Integer): TCoolTabSheet;
    function GetPageCount: Integer;
    procedure InsertPage(Page: TCoolTabSheet);
    procedure InsertTab(Page: TCoolTabSheet);
    procedure MoveTab(CurIndex, NewIndex: Integer);
    procedure RemovePage(Page: TCoolTabSheet);
    procedure SetActivePage(Page: TCoolTabSheet);
    procedure SetActivePageIndex(const Value: Integer);
    procedure UpdateTab(Page: TCoolTabSheet);
    procedure UpdateTabHighlights;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function FindNextPage(CurPage: TCoolTabSheet;
      GoForward, CheckTabVisible: Boolean): TCoolTabSheet;
    procedure SelectNextPage(GoForward: Boolean);
    property ActivePageIndex: Integer read GetActivePageIndex
      write SetActivePageIndex;
    property PageCount: Integer read GetPageCount;
    property Pages[Index: Integer]: TCoolTabSheet read GetPage;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use CoolImages property to specify  TCoolImages component will be used 
    // to load bitmaps for wallpapers from. TcoolImages acts much like 
    // TImageList that is behaves as placeholder for images. It can contain 
    // bitmaps only but bitmaps of different sizes and color modes can be stored 
    // together in the same object.
    property CoolImages: TCoolImages read FCoolImages write SetCoolImages;
    // Options property controls variety of various controls parameters, the combination of included and excluded flags  determines appearance and behavior of the control. The following items that being used separately or in combination define control's look, note that some flags can not be used together and the others can or even must, note also that not all flags can be supported by the particular control or component.
    // These flags can be used with the following meaning:
    // <P>
    // * <I>ocPaintWallpaper.</I> Whether you want to paint the wallpaper for control. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocPaintSelWallpaper.</I> Whether you want to paint the wallpaper for selected items. SelWallpaper or combination of  CoolImages and idSelWallpaper properties must be assigned properly.
    // * <I>ocPaintCaptionWallpaper.</I> Whether you want to paint the wallpaper for control's caption (if the latest is visible). CaptionWallpaper or combination of  CoolImages and idCaptionWallpaper properties must be assigned properly.
    // * <I>ocPaintGradiently.</I> Whether you  want to paint the gradient background. Respective color properties define the background range colors.
    // * <I>ocInvertWallpaperAsSelect.</I> Whether you want to use the same wallpaper you use for control to highlight selected items. When presents selected items will be drawn using inverted Wallpaper image, Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocBevelOnlyIfSel.</I> Whether you like to paint bevel around all the control items or only around those selected. 
    // * <I>ocNoHighlightImage.</I> If the items have attached images determines whether those for selected items should or should not be highlighted among with the item.
    // * <I>ocNoImageAttached.</I> Whether control presumes that its items some with attached images If not there will not be extra space between border and items
    // * <I>ocUseImageList.</I> Whether images should be taken from the linked Image List component or directly from the Glyph property. 
    // * <I>oc3dMDIForm.</I> Whether MDI parent form has more 3D look.
    // * <I>ocWallpaperForMDIChildren.</I> Whether attached wallpaper should be painted for all MDI child windows. Wallpaper or combination of  CoolImages and idWallpaper properties must be assigned properly.
    // * <I>ocNoCaption.</I> Whether control has caption area. Some controls will not have caption even if this property set to True.
    // * <I>ocSmallCaption.</I> What kind of caption should be used for window (if possible) standard or small caption (like for tool windows).
    // * <I>ocNoMDIChildrensCaptions.</I> Whether MDI child windows should  be drawn with the captions.
    // * <I>ocDragUsingClientArea.</I> Is it possible to drag the form using its client area.
    // * <I>ocNoDragUsingCaption.</I> Is it possible to drag the form using its caption area.
    // * <I>ocRoundedForm.</I> Whether the form should have oval shape.
    // * <I>ocFlatBorder.</I> Whether control should be painted with the modern flat look.
    // * <I>ocPaintTransparently.</I> Whether the control should have its own background or use that of the parent container.
    property Options: TCoolOptions read FOptions write SetOptions default [];
    // There's an alternative for direct assigning of 
    // the Wallpaper property for cases when you want 
    // to paint the image background for the 
    // control - use CoolImages and idWallpaper properties 
    // for that. This technique allows to save system resources 
    // by sharing the same image between many controls. IdWallpaper 
    // indicates the index of the image from CoolImages to be used. 
    // For controls that have Options property it's necessary to 
    // include ocPaintWallpaper flag (Options property) to enable 
    // the wallpaper painting.
    // 
    // See Also:
    //   Options
    //   CoolImages
    //   Wallpaper
    property idWallpaper: Integer read FidWallpaper write SetidWallpaper default -1;
    // Use TransparencyLevel to specify the 
    // parent control whose part will be used 
    // to draw the background of the component. 
    // For example if control placed on the panel 
    // that is placed on the form, setting TransparencyLevel 
    // to 0 will force part of the panel to be used for 
    // painting of the transparent background, setting 
    // TransparencyLevel to 1 will force the part of the 
    // form to be selected on the controls device context 
    // when paint transparently.
    property TransparencyLevel: Byte read FTransparencyLevel write SetTransparencyLevel default 0;
    // Use Wallpaper to specify the bitmap image 
    // that will be painted as background wallpaper 
    // for a control. In most cases CoolControls package 
    // requires ocPaintWallpaper flag included into 
    // Options property set in order to actually enable 
    // wallpaper painting. Mind you that there's an 
    // alternative way to attach the image to be painted 
    // on control's background - use CoolImages and idWallpaper 
    // properties for that. This technique allows to save system 
    // resources by sharing the same image between many controls.
    // 
    // See Also:
    //   Options
    //   idWallpaper
    //   CoolImages
    property Wallpaper: TBitmap read GetWallpaper write SetWallpaper;
    // If true wallpapers will cover non client control's area as well.
    //
    // See Also:
    //   Wallpaper
    //   Options
    //   idWallpaper
    property WallpaperWholeControl: Boolean read FWallpaperWholeControl write SetWallpaperWholeControl default True;

    property ActivePage: TCoolTabSheet read FActivePage write SetActivePage;
    property Align;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Anchors;
    property BiDiMode;
    {$ENDIF}
    property Color;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Constraints;
    property DockSite;
    {$ENDIF}
    property DragCursor;
    {$IFDEF DELPHI4_OR_ABOVE}
    property DragKind;
    {$ENDIF}
    property DragMode;
    property Enabled;
    property Font;
    {$IFNDEF VER90}
    property HotTrack;
    {$ENDIF}
    {$IFDEF DELPHI4_OR_ABOVE}
    property Images;
    {$ENDIF}
    property MultiLine;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OwnerDraw;
    property ParentBiDiMode;
    {$ENDIF}
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    {$IFDEF DELPHI4_OR_ABOVE}
    property RaggedRight;
    {$ENDIF}
    {$IFNDEF VER90}
    property ScrollOpposite;
    {$ENDIF}
    property ShowHint;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Style;
    {$ENDIF}
    property TabHeight;
    property TabOrder;
    {$IFNDEF VER90}
    property TabPosition;
    {$ENDIF}
    property TabStop;
    property TabWidth;
    property Visible;
    property OnChange;
    property OnChanging;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnContextPopup;
    {$ENDIF}
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnDockDrop;
    property OnDockOver;
    {$ENDIF}
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnDrawTab;
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnGetImageIndex;
    property OnGetSiteInfo;
    {$ENDIF}
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnResize;
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnUnDock;
    {$ENDIF}
  end;

  // TCoolThermomitor control can graphically display progress of the operation.
  // TCoolThermomitor looks much like thermomitor you use in real life.
  TCoolThermomitor = class(TGraphicControl)
  private
    FAboutBox: TCCAboutBox;

    FImageWidth,
    FImageHeight: Integer;
    FMin,
    FMax,
    FPositionPercent,
    FPosition: Integer;

    FLabelTitle,
    FLabelCurrent,
    FLabelGoal: TCaption;

    FColorTitle,
    FColorCurrent,
    FColorGoal: TColor;

    FFontTitle,
    FFontCurrent,
    FFontGoal: TFont;

    FTransparent: Boolean;

    procedure SetMax(Value: Integer);
    procedure SetMin(Value: Integer);
    procedure SetPosition(Value: Integer);
    procedure SetTransparent(Value: Boolean);

    procedure SetLabelTitle(Value: TCaption);
    procedure SetLabelGoal(Value: TCaption);
    procedure SetLabelCurrent(Value: TCaption);

    procedure SetColorTitle(Value: TColor);
    procedure SetColorGoal(Value: TColor);
    procedure SetColorCurrent(Value: TColor);

    procedure SetFontTitle(Value: TFont);
    procedure SetFontGoal(Value: TFont);
    procedure SetFontCurrent(Value: TFont);

    procedure FontChanged(Sender: TObject);
  protected
    ltHeight, ltWidth: Integer;
    lcHeight, lcWidth: Integer;
    lgHeight, lgWidth: Integer;
    function CalculatePositionPercent: Integer; virtual;
    procedure PaintCoolThermomitor(ACanvas: TCanvas; R: TRect);
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    {$IFDEF DELPHI4_OR_ABOVE}
    // Use PaintTo method to paint the control on the specified \Canvas.
    procedure PaintTo(ACanvas: TCanvas; X, Y: Integer); overload;
    // Use PaintTo method to paint the control on the specified device context.
    procedure PaintTo(DC: HDC; X, Y: Integer); overload;
    {$ELSE}
    // Use PaintTo method to paint the control on the specified Canvas.
    procedure PaintTo(ACanvas: TCanvas; X, Y: Integer);
    // Use PaintTo method to paint the control on the specified device context.
    procedure PaintToDC(DC: HDC; X, Y: Integer);
    {$ENDIF}
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use ColorTitle to set the background \color of the title label.
    //
    // See Also:
    //   FontTitle
    //   LabelTitle
    property ColorTitle: TColor read FColorTitle write SetColorTitle default clWhite;
    // Use ColorCurrent to set the background \color of the current label.
    //
    // See Also:
    //   LabelCurrent
    //   FontCurrent
    property ColorCurrent: TColor read FColorCurrent write SetColorCurrent default clWhite;
    // Use ColorGoal to set the background \color of the goal label.
    //
    // See Also:
    //   LabelGoal
    //   FontGoal
    property ColorGoal: TColor read FColorGoal write SetColorGoal default clWhite;
    // Use FontTitle to set the \font for the title label.
    //
    // See Also:
    //   ColorTitle
    //   LabelTitle
    property FontTitle: TFont read FFontTitle write SetFontTitle;
    // Use FontCurrent to set the \font for the current label.
    //
    // See Also:
    //   ColorCurrent
    //   LabelCurrent
    property FontCurrent: TFont read FFontCurrent write SetFontCurrent;
    // Use FontGoal to set the \font for the goal label.
    //
    // See Also:
    //   LabelGoal
    //   ColorGoal
    property FontGoal: TFont read FFontGoal write SetFontGoal;
    // Use LabelTitle to set the text to be written as a control's title.
    //
    // See Also:
    //   ColorTitle
    //   FontTitle
    property LabelTitle: TCaption read FLabelTitle write SetLabelTitle;
    // Use LabelCurrent to specify the text to be written toward the current position of the thermomitor.
    //
    // See Also:
    //   ColorCurrent
    //   FontCurrent
    property LabelCurrent: TCaption read FLabelCurrent write SetLabelCurrent;
    // Use LabelGoal to specify the text to be written toward the top (max) position of the thermomitor.
    //
    // See Also:
    //   ColorGoal
    //   FontGoal
    property LabelGoal: TCaption read FLabelGoal write SetLabelGoal;    
    // Use Max to set a higher limit to the value that can be represented 
    // using the control. 
    property Max: Integer read FMax write SetMax default 100;
    // Use Min to set a lower limit to the value that can be represented 
    // using the control. 
    property Min: Integer read FMin write SetMin default 0;
    // Set or read Position to determine the current value represented by the track bar. Position is 
    // a value in the range between Min and Max (inclusive).
    property Position: Integer read FPosition write SetPosition default 0;
    // Use Transparent property to specify that the
    // control will be drawn transparently. Similar to the
    // meaning of the ocPaintTransparently flag in the Options
    // property of the most controls.
    property Transparent: Boolean read FTransparent write SetTransparent default True;
    property Align;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Anchors;
    {$ENDIF}
    property Color;
    property Font;
  end;


  TMouseStates = (msMouseInside, msMouseDown);
  TMouseState = set of TMouseStates;

  // TCustomBitmapButton is button control that takes shape of the attached
  // bitmap. Any bitmap image can be used, Transparent areas of the bitmap 
  // will be invisible in the control.
  TCustomBitmapButton = class(TCustomControl)
  private
    FAboutBox: TCCAboutBox;
    FColors: TColorList;

    FMouseState: TMouseState;
    FShadowEffect: Boolean;
    FPositionEffect: Boolean;

    FShadowColor: TColor;
    FShadowSize: Byte;
    FShadowPos: TShadowPosition;
    FSimpleView: Boolean;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;

    procedure SetColors(Value: TColorList);
    function GetColorsRegion(ABitmap: TBitmap): HRGN;
    procedure SetColorsRegion(ABitmap: TBitmap);
    procedure DeleteRegion;

    procedure SetShadowColor(Value: TColor);
    procedure SetShadowSize(Value: Byte);
    procedure SetShadowPos(Value: TShadowPosition);
    procedure SetSimpleView(Value: Boolean);

    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure WMSetText(var Message: TMessage); message WM_SETTEXT;
  protected
    Rgn: HRGN;
    procedure ColorListChanged(Sender: TObject); virtual; abstract;
    {$IFNDEF VER90}
    procedure FadeOut(ABitmap: TBitmap); virtual;
    procedure FadeIn(ABitmap: TBitmap); virtual;
    {$ENDIF}
    procedure PositionIn; virtual;
    procedure PositionOut; virtual;

    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  public
    // Use Colors to assign the list of the colors that will be used to create 
    // the temlate either being included or excluded from the region.
    // TColorList supports the same methods and properties TList does and deals with the TColor type items.
    property Colors: TColorList read FColors write SetColors;
    // If True then there will be effect of moving button when mouse pressed and depressed.
    property PositionEffect: Boolean read FPositionEffect write FPositionEffect default True;
    // If true then there will be shadow effect when m mouse pressed and depressed.
    property ShadowEffect: Boolean read FShadowEffect write FShadowEffect default True;

    // In the CoolControls package many controls that 
    // have captions or string items allow to paint 
    // these with the 3D effect. When you use this feature, 
    // use ShadowColor to set the color of the shadow dropped. 
    // The effect being achieved by painting the text 
    // twice - once with the main color and then with the 
    // ShadowColor (allowing ShadowSize offset).
    // 
    // See Also:
    //   ShadowSize
    //   ShadowPos
    //   SimpleView
    property ShadowColor: TColor read FShadowColor write SetShadowColor default clBtnHighlight;
    // In the CoolControls package many controls that have captions
    // or string items allow to paint these with the 3D effect. 
    // When you use this feature, use ShadowSiize to indicate the 
    // offset  of the shadow dropped. The effect being achieved by 
    // painting the text twice - once with the main color and then 
    // with the ShadowColor (allowing ShadowSize offset).
    // 
    // See Also:
    //   ShadowPos
    //   ShadowColor
    //   SimpleView
    property ShadowSize: Byte read FShadowSize write SetShadowSize default 1;
    // In the CoolControls package many controls that have captions or 
    // string items allow to paint these with the 3D effect. When 
    // you use this feature, use ShadowPos to indicate the position 
    // (relatively to the main text) of the shadow dropped. The effect 
    // being achieved by painting the text twice - once with the main 
    // color and then with the ShadowColor (allowing ShadowSize offset).
    // 
    // <TABLE>
    // Value              Meaning
    // -------            -------------------------
    // spLeftTop          Shadow is in the Left Top direction.
    // spLeftBottom       Shadow is in the Left Bottom direction.
    // spRightBottom      Shadow is in the Right Bottom direction.
    // spRightTop         Shadow is in the Right Top direction.
    // </TABLE>
    // 
    // See Also:
    //   ShadowSize
    //   ShadowColor
    //   SimpleView
    property ShadowPos: TShadowPosition read FShadowPos write SetShadowPos default spLeftTop;
    // In the CoolControls package many controls that have 
    // captions or string items allow to paint these with 
    // the 3D effect. When you use this feature, use ShadowPos 
    // to indicate the position (relatively to the main text) 
    // of the shadow dropped. The effect being achieved by 
    // painting the text twice - once with the main color and
    // then with the ShadowColor (allowing ShadowSize offset).
    // Use SimpleView to indicate whether you want to use the 
    // described feature  or you do not.
    //
    // See Also:
    //   ShadowSize
    //   ShadowPos
    //   ShadowColor
    property SimpleView: Boolean read FSimpleView write SetSimpleView default False;

    // OnMouseEnter event occurs immediately after mouse cursor enters the control.
    property OnMoseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    // OnMouseLeave event occurs immediately after mouse cursor leaves the control.
    property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
  end;

  // TCoolBitmapButton is button control that takes shape of the attached bitmap. 
  // Any bitmap image can be used, Transparent areas of the bitmap will be invisible in the control.
  // TCoolBitmapButton publishes properties of the TCustomBitmapButton.
  TCoolBitmapButton = class(TCustomBitmapButton)
  private
    FBitmap: TBitmap;
    procedure SetBitmap(Value: TBitmap);
    procedure BitmapChange(Sender: TObject);
  protected
    procedure Paint; override;
    procedure Loaded; override;
    {$IFDEF DELPHI4_OR_ABOVE}
    function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
    {$ENDIF}
    procedure ColorListChanged(Sender: TObject); override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Bitmap: TBitmap read FBitmap write SetBitmap;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Action;
    property Anchors;
    property BiDiMode;
    property AutoSize;
    property Caption;
    property Constraints;
    {$ENDIF}
    property Colors;
    property Cursor;
    property DragCursor;
    {$IFDEF DELPHI4_OR_ABOVE}
    property DragKind;
    {$ENDIF}
    property DragMode;
    property Enabled;
    property Font;
    property HelpContext;
    property Hint;
    property ParentShowHint;
    property PositionEffect;
    property ShadowEffect;

    property ShadowColor;
    property ShadowSize;
    property ShadowPos;
    property SimpleView;

    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;
    property OnClick;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnContextPopup;
    {$ENDIF}
    property OnDragOver;
    property OnDragDrop;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
    property OnMoseEnter;
    property OnMouseLeave;
  end;

  // TCoolManyBitmapsButton component comes with the similar functionality as TBitmapButton except for that it allows to specify separate image for each state of the control. Images should be added to TImageList attached to the control. The following states/images are appropriate (indexes in respectiveImageList):
  //
  // <PRE>
  //   0 - Normal Image
  //   1 - Disabled Image
  //   2 - Mouse pressed image
  //   3 - Mouse inside control image
  // </PRE>  
  TCoolManyBitmapsButton = class(TCustomBitmapButton)
  private
    FImages: TCustomImageList;
    FImagesChangeLink: TChangeLink;
    procedure SetImages(Value: TCustomImageList);
    procedure ImagesChange(Sender: TObject);
    procedure CurrentImageChanged;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Paint; override;
    procedure Loaded; override;
    procedure ColorListChanged(Sender: TObject); override;
    {$IFDEF DELPHI4_OR_ABOVE}
    function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
    {$ENDIF}

    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    // Points to the TImageList component that holds images to be used with the control.
    property Images: TCustomImageList read FImages write SetImages;
    {$IFDEF DELPHI4_OR_ABOVE}
    property Action;
    property Anchors;
    property BiDiMode;
    property AutoSize;
    property Caption;
    property Constraints;
    {$ENDIF}
    property Colors;
    property Cursor;
    property DragCursor;
    {$IFDEF DELPHI4_OR_ABOVE}
    property DragKind;
    {$ENDIF}
    property DragMode;
    property Enabled;
    property Font;
    property HelpContext;
    property Hint;
    property ParentShowHint;
    property PositionEffect;
    property ShowHint;

    property ShadowColor;
    property ShadowSize;
    property ShadowPos;
    property SimpleView;

    property TabOrder;
    property TabStop;
    property Visible;
    property OnClick;
    {$IFDEF DELPHI5_OR_ABOVE}
    property OnContextPopup;
    {$ENDIF}
    property OnDragOver;
    property OnDragDrop;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
    property OnMoseEnter;
    property OnMouseLeave;
  end;

implementation
{$R CoolCtrlsEx.res}

const
  MaxPixelCount = 32768;

type
  pRGBArray = ^TRGBArray;
  TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;

{$IFDEF DELPHI4_OR_ABOVE}

type
  TImageListEx = class(TImageList);

{TCoolCustomListView}
constructor TCoolCustomListView.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FOptions := [ocNoCaption];
  FWallpaper := nil;
  FSelWallpaper := nil;
  FCaptionWallpaper := nil;

  FCoolImagesChangeLink := TCoolChangeLink.Create;
  FCoolImagesChangeLink.OnChange := CoolImagesChange;
  FSelColor := clHighlight;
  FCaptionColor := clInactiveCaption;
  FCaptionTextColor := clInactiveCaptionText;
  FidWallpaper := -1;
  FidCaptionWallpaper := -1;
  FidSelWallpaper := -1;
  FTransparencyLevel := 0;

  FBorderPen := TPen.Create;
  FBorderPen.OnChange := BorderPenChange;
  FEdgeBorders := [];
  FBordersTrColor := clNone;

  FShadowColor := clBtnHighlight;
  FShadowSize := 1;
  FShadowPos := spLeftTop;
  FSimpleView := False;

  RowSelect := True;
  OldViewOrigin := Point(0, 0) ;

  if not DesignTime(Self) then
  begin
    {$IFNDEF DELPHI5_OR_ABOVE}
    OnCustomDrawItem := MyCustomDrawItem;
    {$ELSE}
    OnAdvancedCustomDrawItem := MyAdvancedCustomDrawItem;
    {$ENDIF}
  end;
end;

destructor TCoolCustomListView.Destroy;
begin
  if Assigned(FWallpaper) then FWallPaper.Free;
  if Assigned(FSelWallpaper) then FSelWallPaper.Free;
  if Assigned(FCaptionWallpaper) then FCaptionWallPaper.Free;
  FCoolImagesChangeLink.Free;
  FBorderPen.Free;
  inherited Destroy;
end;

procedure TCoolCustomListView.SetOptions(Value: TCoolOptions);
begin
  if FOptions <> Value then
  begin
    if (ocPaintTransparently in Value) and (ocPaintWallpaper in FOptions) then
      Exclude(Value, ocPaintWallpaper) else
        if (ocPaintWallpaper in Value) and (ocPaintTransparently in FOptions) then
          Exclude(Value, ocPaintTransparently);

    FOptions := Value;
    RecreateWnd;
    Perform(CM_COLORCHANGED, 0, 0);
  end;
end;

procedure TCoolCustomListView.SetWallpaper(Value: TBitmap);
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  FWallPaper.Assign(Value);
  Invalidate;
end;

function TCoolCustomListView.GetWallpaper: TBitmap;
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  Result := FWallpaper;
  Result.OnChange := WallpaperChange;
end;

procedure TCoolCustomListView.SetSelWallpaper(Value: TBitmap);
begin
  if FSelWallpaper = nil then FSelWallpaper := TBitmap.Create;
  FSelWallPaper.Assign(Value);
  Invalidate;
end;

function TCoolCustomListView.GetSelWallpaper: TBitmap;
begin
  if FSelWallpaper = nil then FSelWallpaper := TBitmap.Create;
  Result := FSelWallpaper;
  Result.OnChange := WallpaperChange;
end;

procedure TCoolCustomListView.SetCaptionWallpaper(Value: TBitmap);
begin
  if FCaptionWallpaper = nil then FCaptionWallpaper := TBitmap.Create;
  FCaptionWallPaper.Assign(Value);
  Invalidate;
end;

function TCoolCustomListView.GetCaptionWallpaper: TBitmap;
begin
  if FCaptionWallpaper = nil then FCaptionWallpaper := TBitmap.Create;
  Result := FCaptionWallpaper;
  Result.OnChange := WallpaperChange;
end;

procedure TCoolCustomListView.BorderPenChange(Sender: TObject);
begin
  Invalidate;
end;

procedure TCoolCustomListView.SetEdgeBorders(Value: TEdgeBorders);
begin
  if FEdgeBorders <> Value then
  begin
    FEdgeBorders := Value;
    Invalidate;
  end;
end;

procedure TCoolCustomListView.SetBorderPen(Value: TPen);
begin
  FBorderPen.Assign(Value);
end;

procedure TCoolCustomListView.SetBordersTrColor(Value: TColor);
begin
  if FBordersTrColor <> Value then
  begin
    FBordersTrColor := Value;
    Invalidate;
  end;
end;

procedure TCoolCustomListView.WallpaperChange(Sender: TObject);
begin
  Invalidate;
end;

{$IFNDEF DELPHI5_OR_ABOVE}
procedure TCoolCustomListView.MyCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
const
  DrawingStyle: array[Boolean] of Cardinal = (ILD_NORMAL, ILD_SELECTED);
  DrawingTextStyle: array[Boolean] of UINT = (DT_MODIFYSTRING or DT_END_ELLIPSIS or DT_WORDBREAK, DT_SINGLELINE);
var
  IconRect: TRect;
  TextRect: TRect;
  X, Y: Integer;
  iPos: Integer;
  iCount: Integer;
  pCaption: PChar;
begin
  if Assigned(Item) then
  begin
    //
    // Text
    //
    TextRect := Item.DisplayRect(drLabel);

    if (cdsSelected in State) then
    begin
      Sender.Canvas.Font.Color := clHighlightText;
      if IsSelWallpaperAssigned then
        CTLDrawSelWallpaper(Sender.Canvas.Handle, ClientRect, TextRect, True, SRCCOPY) else
          begin
            Sender.Canvas.Brush.Color := FSelColor;
            Sender.Canvas.FillRect(TextRect);
          end;
    end;

    if (cdsFocused in State) and (ViewStyle <> vsReport) then
      Sender.Canvas.DrawFocusRect(TextRect);

    SetBkMode(Sender.Canvas.Handle, TRANSPARENT);
    InflateRect(TextRect, -2, -2);

    pCaption := StrNew(PChar(Item.Caption));

    if not Enabled then
      Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} spRightBottom {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DrawingTextStyle[cdsSelected in State], clBtnShadow, clBtnHighlight, 1)
    else
      if FSimpleView then
        DrawText(Sender.Canvas.Handle, pCaption,  -1, TextRect, DrawingTextStyle[cdsSelected in State])
      else
        Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} FShadowPos {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DrawingTextStyle[cdsSelected in State], Font.Color,
            FShadowColor, FShadowSize);

    StrDispose(pCaption);

    if ViewStyle = vsReport then
    begin
      //
      // SubItems Text
      //
      TextRect := Rect(0, 0, 0, 0);
      Perform(LVM_GETSUBITEMRECT, Item.Index, LongInt(@TextRect));

      iPos := 0;
      for iCount := 0 to Item.SubItems.Count-1 do
      begin
        Inc(iPos, ListView_GetColumnWidth(Sender.Handle, iCount));

        TextRect.Left := iPos;
        TextRect.Right := iPos + ListView_GetColumnWidth(Sender.Handle, iCount);

        if (cdsSelected in State) then
          if RowSelect then
            if IsSelWallpaperAssigned then
              CTLDrawSelWallpaper(Sender.Canvas.Handle, ClientRect, TextRect, True, SRCCOPY) else
                begin
                  Sender.Canvas.Brush.Color := FSelColor;
                  Sender.Canvas.FillRect(TextRect);
                  Sender.Canvas.Font.Color := clHighlightText;
                end;

        SetBkMode(Sender.Canvas.Handle, TRANSPARENT);

        pCaption := StrNew(PChar(Item.SubItems[iCount]));
        if not Enabled then
          Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} spRightBottom {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DT_PATH_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX, clBtnShadow, clBtnHighlight, 1) else
            if FSimpleView then
              DrawText(Sender.Canvas.Handle, pCaption,  -1, TextRect, DT_PATH_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX) else
                Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} FShadowPos {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DT_PATH_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX, Font.Color, FShadowColor, FShadowSize);
        StrDispose(pCaption);
      end;

      TextRect.Left := 0;
      if (cdsFocused in State) then
        Sender.Canvas.DrawFocusRect(TextRect);
    end else
    begin
      //
      // Icon
      //
      IconRect := Item.DisplayRect(drIcon);
      case ViewStyle of
        vsIcon:
          begin
            with IconRect do
            begin
              X := Left + (Right - Left) div 2 - TImageListEx(LargeImages).Width div 2;
              Y := Top + (Bottom - Top) div 2 - TImageListEx(LargeImages).Height div 2;
            end;
            TImageListEx(LargeImages).BlendColor := clNavy;
            TImageListEx(LargeImages).DoDraw(Item.ImageIndex, Sender.Canvas, X, Y, DrawingStyle[cdsSelected in State], True);
          end;
        vsReport,
        vsList,
        vsSmallIcon:
          begin
            with IconRect do
            begin
              X := Left + (Right - Left) div 2 - TImageListEx(SmallImages).Width div 2;
              Y := Top + (Bottom - Top) div 2 - TImageListEx(SmallImages).Height div 2;
            end;
            TImageListEx(SmallImages).BlendColor := clNavy;
            TImageListEx(SmallImages).DoDraw(Item.ImageIndex, Sender.Canvas, X, Y, DrawingStyle[cdsSelected in State], True);
          end;
      end;
    end;
    DefaultDraw := False;
  end;
end;
{$ELSE}
procedure TCoolCustomListView.MyAdvancedCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage; var DefaultDraw: Boolean);
const
  DrawingStyle: array[Boolean] of Cardinal = (ILD_NORMAL, ILD_SELECTED);
  DrawingTextStyle: array[Boolean] of UINT = (DT_MODIFYSTRING or DT_END_ELLIPSIS or DT_WORDBREAK, DT_SINGLELINE);
var
  IconRect: TRect;
  TextRect: TRect;
  X, Y: Integer;
  iPos: Integer;
  iCount: Integer;
  pCaption: PChar;
begin
  if Assigned(Item) then
  begin
    //
    // Text
    //
    TextRect := Item.DisplayRect(drLabel);

    if (cdsSelected in State) then
    begin
      Sender.Canvas.Font.Color := clHighlightText;
      if IsSelWallpaperAssigned then
        CTLDrawSelWallpaper(Sender.Canvas.Handle, ClientRect, TextRect, True, SRCCOPY) else
          begin
            Sender.Canvas.Brush.Color := FSelColor;
            Sender.Canvas.FillRect(TextRect);
          end;
    end;

    if (cdsFocused in State) and (ViewStyle <> vsReport) then
      Sender.Canvas.DrawFocusRect(TextRect);

    SetBkMode(Sender.Canvas.Handle, TRANSPARENT);
    InflateRect(TextRect, -2, -2);

    pCaption := StrNew(PChar(Item.Caption));

    if not Enabled then
      Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} spRightBottom {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DrawingTextStyle[cdsSelected in State], clBtnShadow, clBtnHighlight, 1)
    else
      if FSimpleView then
        DrawText(Sender.Canvas.Handle, pCaption,  -1, TextRect, DrawingTextStyle[cdsSelected in State])
      else
        Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} FShadowPos {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DrawingTextStyle[cdsSelected in State], Font.Color,
          FShadowColor, FShadowSize);

    StrDispose(pCaption);

    if ViewStyle = vsReport then
    begin
      //
      // SubItems Text
      //
      TextRect := Rect(0, 0, 0, 0);
      Perform(LVM_GETSUBITEMRECT, Item.Index, LongInt(@TextRect));

      iPos := 0;
      for iCount := 0 to Item.SubItems.Count-1 do
      begin
        Inc(iPos, ListView_GetColumnWidth(Sender.Handle, iCount));

        TextRect.Left := iPos;
        TextRect.Right := iPos + ListView_GetColumnWidth(Sender.Handle, iCount);

        if (cdsSelected in State) then
          if RowSelect then
            if IsSelWallpaperAssigned then
              CTLDrawSelWallpaper(Sender.Canvas.Handle, ClientRect, TextRect, True, SRCCOPY) else
                begin
                  Sender.Canvas.Brush.Color := FSelColor;
                  Sender.Canvas.FillRect(TextRect);
                  Sender.Canvas.Font.Color := clHighlightText;
                end;

        SetBkMode(Sender.Canvas.Handle, TRANSPARENT);

        pCaption := StrNew(PChar(Item.SubItems[iCount]));
        if not Enabled then
          Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} spRightBottom {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DT_PATH_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX, clBtnShadow, clBtnHighlight, 1) else
            if FSimpleView then
              DrawText(Sender.Canvas.Handle, pCaption,  -1, TextRect, DT_PATH_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX) else
                Draw3DText(Sender.Canvas.Handle, TextRect, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} FShadowPos {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, pCaption, DT_PATH_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX, Font.Color, FShadowColor, FShadowSize);
        StrDispose(pCaption);
      end;

      TextRect.Left := 0;
      if (cdsFocused in State) then
          Sender.Canvas.DrawFocusRect(TextRect);
    end else
    begin
      //
      // Icon
      //
      IconRect := Item.DisplayRect(drIcon);
      case ViewStyle of
        vsIcon:
          begin
            with IconRect do
            begin
              X := Left + (Right - Left) div 2 - TImageListEx(LargeImages).Width div 2;
              Y := Top + (Bottom - Top) div 2 - TImageListEx(LargeImages).Height div 2;
            end;
            TImageListEx(LargeImages).BlendColor := clNavy;
            TImageListEx(LargeImages).DoDraw(Item.ImageIndex, Sender.Canvas, X, Y, DrawingStyle[cdsSelected in State], True);
          end;
        vsReport,
        vsList,
        vsSmallIcon:
          begin
            with IconRect do
            begin
              X := Left + (Right - Left) div 2 - TImageListEx(SmallImages).Width div 2;
              Y := Top + (Bottom - Top) div 2 - TImageListEx(SmallImages).Height div 2;
            end;
            TImageListEx(SmallImages).BlendColor := clNavy;
            TImageListEx(SmallImages).DoDraw(Item.ImageIndex, Sender.Canvas, X, Y, DrawingStyle[cdsSelected in State], True);
          end;
      end;
    end;
    DefaultDraw := False;
  end;
end;
{$ENDIF}
function TCoolCustomListView.CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
begin
  Result := False;
  if Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty then
  begin
    DrawWallpaper(DC, FCoolImages.Images.Items[FidWallpaper].Bitmap, R, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FWallpaper) and not FWallpaper.Empty then
  begin
    DrawWallpaper(DC, FWallpaper, R, IsStretch, Mode);
    Result := True;
  end;
end;

function TCoolCustomListView.IsWallpaperAssigned: Boolean;
begin
  Result := (Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty) or
            (Assigned(FWallpaper) and not FWallpaper.Empty);
end;

function TCoolCustomListView.IsSelWallpaperAssigned: Boolean;
begin
  Result := (Assigned(FCoolImages) and (FidSelWallpaper >= 0) and (FidSelWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidSelWallpaper].Bitmap) and not FCoolImages.Images.Items[FidSelWallpaper].Bitmap.Empty) or
            (Assigned(FSelWallpaper) and not FSelWallpaper.Empty);
end;

function TCoolCustomListView.CTLDrawCaptionWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
begin
  Result := False;
  if Assigned(FCoolImages) and (FidCaptionWallpaper >= 0) and (FidCaptionWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidCaptionWallpaper].Bitmap) and not FCoolImages.Images.Items[FidCaptionWallpaper].Bitmap.Empty then
  begin
    DrawWallpaper(DC, FCoolImages.Images.Items[FidCaptionWallpaper].Bitmap, R, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FCaptionWallpaper) and not FCaptionWallpaper.Empty then
  begin
    DrawWallpaper(DC, FCaptionWallpaper, R, IsStretch, Mode);
    Result := True;
  end;
end;

function TCoolCustomListView.CTLDrawSelWallpaper(DC: HDC; R, SubRect: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
begin
  Result := False;
  if Assigned(FCoolImages) and (FidSelWallpaper >= 0) and (FidSelWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidSelWallpaper].Bitmap) and not FCoolImages.Images.Items[FidSelWallpaper].Bitmap.Empty then
  begin
    DrawWallpaperEx(DC, FCoolImages.Images.Items[FidSelWallpaper].Bitmap, R, SubRect, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FSelWallpaper) and not FSelWallpaper.Empty then
  begin
    DrawWallpaperEx(DC, FSelWallpaper, R, SubRect, IsStretch, Mode);
    Result := True;
  end;
end;

procedure TCoolCustomListView.SetCoolImages(Value: TCoolImages);
begin
  if Assigned(CoolImages) then
    CoolImages.UnRegisterChanges(FCoolImagesChangeLink);

  FCoolImages := Value;

  if Assigned(CoolImages) then
    CoolImages.RegisterChanges(FCoolImagesChangeLink);

  NCCtlChanged;
end;

procedure TCoolCustomListView.SetidWallpaper(Value: Integer);
begin
  if FidWallpaper <> Value then
  begin
    FidWallpaper := Value;
    Invalidate;
  end;
end;

procedure TCoolCustomListView.SetidCaptionWallpaper(Value: Integer);
begin
  if FidCaptionWallpaper <> Value then
  begin
    FidCaptionWallpaper := Value;
    NCCtlChanged;
  end;
end;

procedure TCoolCustomListView.SetidSelWallpaper(Value: Integer);
begin
  if FidSelWallpaper <> Value then
  begin
    FidSelWallpaper := Value;
    Invalidate;
  end;
end;

procedure TCoolCustomListView.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);

  with Params do
  begin
    if not (ocNoCaption in FOptions) then
      Style := Style or WS_CAPTION else
        Style := Style and not WS_CAPTION;

    if ocSmallCaption in FOptions then
      ExStyle := ExStyle or WS_EX_TOOLWINDOW else
        ExStyle := ExStyle and not WS_EX_TOOLWINDOW;
  end;
end;

procedure TCoolCustomListView.CreateWnd;
begin
  inherited CreateWnd;
end;

procedure TCoolCustomListView.NCCtlChanged;
begin
  if HandleAllocated then
    SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_DRAWFRAME or SWP_NOACTIVATE or SWP_NOMOVE or
                                        SWP_NOSIZE or SWP_NOZORDER);
end;

procedure TCoolCustomListView.Change(Item: TListItem; Change: Integer);
begin
  inherited Change(Item, Change);
  if not PointsFakeEqual(ViewOrigin, OldViewOrigin, 1) and (((ocPaintWallpaper in Foptions) and IsWallpaperAssigned) or (ocPaintTransparently in FOptions)) then
  begin
    Invalidate;
    OldViewOrigin := ViewOrigin;
  end;
end;

procedure TCoolCustomListView.CoolImagesChange(Sender: TObject);
begin
  NCCtlChanged;
  Invalidate;
end;

procedure TCoolCustomListView.SetCaptionColor(Value: TColor);
begin
  if FCaptionColor <> Value then
  begin
    FCaptionColor := Value;
    NCCtlChanged;
  end;
end;

procedure TCoolCustomListView.SetCaptionTextColor(Value: TColor);
begin
  if FCaptionTextColor <> Value then
  begin
    FCaptionTextColor := Value;
    NCCtlChanged;
  end;
end;

procedure TCoolCustomListView.SetTransparencyLevel(Value: Byte);
begin
  if FTransparencyLevel <> Value then
  begin
    FTransparencyLevel := Value;
    Invalidate;
  end;
end;

procedure TCoolCustomListView.SetShadowColor(Value: TColor);
begin
  if FShadowColor <> Value then
  begin
    FShadowColor := Value;
    FSimpleView := False;
    Repaint;
  end;
end;

procedure TCoolCustomListView.SetShadowSize(Value: Byte);
begin
  if FShadowSize <> Value then
  begin
    FShadowSize := Value;
    FSimpleView := False;
    Repaint;
  end;
end;

procedure TCoolCustomListView.SetShadowPos(Value: TShadowPosition);
begin
  if FShadowPos <> Value then
  begin
    FShadowPos := Value;
    FSimpleView := False;
    Repaint;
  end;
end;

procedure TCoolCustomListView.SetSimpleView(Value: Boolean);
begin
  if FSimpleView <> Value then
  begin
    FSimpleView := Value;
    Repaint;
  end;
end;

procedure TCoolCustomListView.CMMouseEnter(var Message: TMessage);
begin
  inherited;
  if (ocFlatBorder in FOptions) and not IsCoolControl(Screen.ActiveControl) then
    DrawFlatBorder(0, Self, True);

  if Assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TCoolCustomListView.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  if (ocFlatBorder in FOptions) and not IsCoolControl(Screen.ActiveControl) then
    DrawFlatBorder(0, Self, False);

  if Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;

procedure TCoolCustomListView.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
  if DesignTime(Self) then
    inherited
  else
    if (ocPaintTransparently in FOptions) then
      PaintBackground(TrControl(Self, FTransparencyLevel), Message.DC, True) else
        if (ocPaintWallpaper in FOptions) and IsWallpaperAssigned then
          CTLDrawWallpaper(Message.DC, ClientRect, (ocStretchWallpaper in FOptions), SRCCOPY) else
            inherited;
end;

procedure TCoolCustomListView.WMPaint (var Message: TMessage);
begin
  inherited;

  if (ocFlatBorder in FOptions) then
    DrawFlatBorder(0, Self, Focused);

  DrawBorders(Message.wParam, Self, FEdgeBorders, FBorderPen, FBordersTrColor);
end;

procedure TCoolCustomListView.WMVScroll(var Message: TWMVScroll);
begin
  inherited;

  if ((ocPaintWallpaper in FOptions) and IsWallpaperAssigned) or (ocPaintTransparently in FOptions) then
    Invalidate;
end;

procedure TCoolCustomListView.WMHScroll(var Message: TWMHScroll);
begin
  inherited;
  if ((ocPaintWallpaper in FOptions) and IsWallpaperAssigned) or (ocPaintTransparently in FOptions) then
    Invalidate;
end;

procedure TCoolCustomListView.WMNCPaint(var Message: TMessage);
var
  WR, R: TRect;
  MyDC: HDC;
  MyRgn: HRGN;
  OldFont, MyFont: HFONT;
  MyBrush: HBRUSH;
  DeleteRgn: Boolean;
  NCM: TNonClientMetrics;
begin
  inherited;
  if not (ocNoCaption in FOptions) and ( (FCaptionColor <> clInactiveCaption) or (FCaptionTextColor <> clInactiveCaptionText) or (ocPaintCaptionWallpaper in FOptions) ) then
  begin
    DeleteRgn := FALSE;
    MyRgn := Message.wParam;

    MyDC := GetWindowDC(Handle);
    try
      GetWindowRect(Handle, WR);

      if SelectClipRgn(MyDC, MyRgn) = ERROR then
        with WR do
        begin
          MyRgn := CreateRectRgn(Left, Top, Right, Bottom);
          SelectClipRgn(MyDC, MyRgn);
          DeleteRgn := TRUE;
        end;

      OffsetClipRgn(MyDC, -WR.Left, -WR.Top);
      GetWindowRect(Handle, R);
      OffsetRect(R, -R.Left, -R.Top);
      InflateRect(R, -GetSystemMetrics(SM_CXFIXEDFRAME),  -GetSystemMetrics(SM_CYFIXEDFRAME));
      if (ocSmallCaption in FOptions) then
        R.Bottom := R.Top + GetSystemMetrics(SM_CYSMCAPTION)-1 else
          R.Bottom := R.Top + GetSystemMetrics(SM_CYCAPTION)-1;

      MyBrush := CreateSolidBrush(ColorToRGB(FCaptionColor));
      try
        if not (ocPaintCaptionWallpaper in FOptions) then
          FillRect(MyDC, R, MyBrush) else
            CTLDrawCaptionWallpaper(MyDC, R, True, SRCCOPY);

        NCM.cbSize := SizeOf(NCM);
        SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NCM, 0);
        if (ocSmallCaption in FOptions) then
          MyFont := CreateFontIndirect(NCM.lfSmCaptionFont) else
            MyFont := CreateFontIndirect(NCM.lfCaptionFont);
        try
          OldFont := SelectObject(MyDC, MyFont);
          try
            OffsetRect(R, 2, 0);
            try
              SetTextColor(MyDC, ColorToRGB(FCaptionTextColor));
              SetBkMode(MyDC, Transparent);
              DrawText(MyDC, PChar(Caption), -1, R, DT_LEFT or DT_VCENTER or DT_SINGLELINE);
            finally
              OffsetRect(R, -2, 0);
            end;
          finally
            SelectObject(MyDC, OldFont);
          end;
        finally
          DeleteObject(MyFont);
        end;
      finally
        DeleteObject(MyBrush);
      end;

      ExcludeClipRect(MyDC, R.Left, R.Top, R.Right, R.Bottom);
      OffsetClipRgn(MyDC, WR.Left, WR.Top);
      GetClipRgn(MyDC, MyRgn);
      Message.Result := DefWindowProc(Handle, Message.Msg, MyRgn, Message.lParam);

    finally
      if DeleteRgn then DeleteObject(MyRgn);
      ReleaseDC(Handle, MyDC);
    end;
  end;
end;

procedure TCoolCustomListView.WMSetFocus(var Message: TWMSetFocus);
begin
  inherited;
  Invalidate;
  if (ocFlatBorder in FOptions) then
    DrawFlatBorder(0, Self, True);
end;

procedure TCoolCustomListView.WMKillFocus(var Message: TWMKillFocus);
begin
  inherited;
  Invalidate;
  if (ocFlatBorder in FOptions) then
    DrawFlatBorder(0, Self, True);
end;

{TCoolExplorerListView}
constructor TCoolExplorerListView.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  LargeImages := TImageList.Create(Self);
  LargeImages.BlendColor := clHighlight;
  LargeImages.Width := 32;
  LargeImages.Height := 32;

  SmallImages := TImageList.Create(Self);
  SmallImages.BlendColor := clHighlight;
  SmallImages.Width := 16;
  SmallImages.Height := 16;

  FMemStream := TMemoryStream.Create;
  FFileMask := '*.*' ;
  FFileType := [ftDirectory, ftArchive];
end;

destructor TCoolExplorerListView.Destroy;
begin
  FMemStream.Free;
  LargeImages.Free;
  SmallImages.Free;
  inherited Destroy;
end;

procedure TCoolExplorerListView.CreateWnd;
begin
  inherited CreateWnd;
  DragAcceptFiles(Handle, True);

  if FMemStream.Size > 0 then
  begin
    FMemStream.Position := 0;
    LoadFromStream(FMemStream);
    Arrange(arDefault);
  end;
end;

procedure TCoolExplorerListView.DestroyWnd;
begin
  FMemStream.Clear;
  SaveToStream(FMemStream);
  DragAcceptFiles(Handle, False);
  inherited DestroyWnd;
end;

procedure TCoolExplorerListView.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_ACCEPTFILES;
end;

procedure TCoolExplorerListView.DragDrop(Source: TObject; X, Y: Integer);
var
  Item: TListItem;
  XOld, YOld: Integer;
  P: TPoint;
  R: TRect;
begin
  inherited DragDrop(Source, X, Y);
  Item := Selected;
  if Item <> nil then
  begin
    R := Item.DisplayRect(drIcon);
    XOld := R.Left;
    YOld := R.Top;
    repeat
      P := Item.GetPosition;
      R := Item.DisplayRect(drIcon);

      P.X := P.X + (X - R.Left + (R.Left - XOld));
      P.Y := P.Y + (Y - R.Top + (R.Top - YOld));

      Item.SetPosition(P);
      Item := GetNextItem(Item, sdAll, [isSelected]);
    until Item = nil;
  end;
end;

procedure TCoolExplorerListView.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
  inherited DragOver(Source, X, Y, State, Accept);
  Accept := True;
end;

procedure TCoolExplorerListView.SaveToStream(Stream: TStream);
var
  I: Integer;
begin
  with TWriter.Create(Stream, 4096) do
  try
    Stream.WriteComponent(LargeImages);
    Stream.WriteComponent(SmallImages);

    WriteInteger(Items.Count);
    for I := 0 to Pred(Items.Count) do
    begin
      WriteString(Items[I].Caption);
      WriteString(String(Items[I].Data^));
      WriteInteger(Items[I].ImageIndex);
      WriteInteger(Items[I].Left);
      WriteInteger(Items[I].Top);
    end;
  finally
    Free;
  end;
end;

procedure TCoolExplorerListView.LoadFromStream(Stream: TStream);
var
  I, Count: Integer;
  Item: TListItem;
  P: PString;
begin
  with TReader.Create(Stream, 4096) do
  try
    LargeImages.Clear;
    Stream.ReadComponent(LargeImages);

    SmallImages.Clear;
    Stream.ReadComponent(SmallImages);

    Items.Clear;
    Count := ReadInteger;
    for I := 0 to Pred(Count) do
    begin
      Item := Items.Add;
      Item.Caption := ReadString;
      P := New(PString);
      P^ := ReadString;
      Item.Data := P;
      Item.ImageIndex := ReadInteger;
      Item.Left := ReadInteger;
      Item.Top := ReadInteger;
    end;
  finally
    Free;
  end;
end;

procedure TCoolExplorerListView.SaveToFile(FileName: TFileName);
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(Stream);
  finally
    Stream.Free;
  end;
end;

procedure TCoolExplorerListView.LoadFromfile(FileName: TFileName);
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

procedure TCoolExplorerListView.Delete(Item: TListItem);
begin
  if Assigned(Item) then
  begin
    if Assigned(Item.Data) then
    begin
      Dispose(Item.Data);
      Item.Data := nil;
    end;

    if Item.ImageIndex <= Pred(LargeImages.Count) then
      LargeImages.Delete(Item.ImageIndex);

    if Item.ImageIndex <= Pred(SmallImages.Count) then
      SmallImages.Delete(Item.ImageIndex);
  end;

  inherited Delete(Item);
end;

procedure TCoolExplorerListView.Edit(const Item: TLVItem);
var
  P: PString;
begin
  inherited Edit(Item);
  P := Selected.Data;
  P^ := ExtractFilePath(P^) + Selected.Caption;
  Selected.Data := P;
end;

procedure TCoolExplorerListView.SetFileType(Value: TFileType);
var
  CurDir: TFileName;
begin
  if FFileType <> Value then
  begin
    FFileType := Value;

    CurDir := Directory;
    Directory := CurDir;
  end;
end;

procedure TCoolExplorerListView.SetFileMask(Value: string);
var
  CurDir: TFileName;
begin
  if FFileMask <> Value then
  begin
    FFileMask := Value;

    CurDir := Directory;
    Directory := CurDir;
  end;
end;

procedure TCoolExplorerListView.SetDirectory(Value: TFileName);
const
   Attributes: array[TFileAttr] of Word = (SysUtils.faReadOnly, SysUtils.faHidden, SysUtils.faSysFile,
                                           SysUtils.faVolumeID, SysUtils.faDirectory, SysUtils.faArchive, SysUtils.faAnyFile);
var
  Num: Integer;
  FileList: TStringList;
  FileName: array [0..255] of Char;
  Icon: TIcon;
  IconIndex: Word;
  Item: TListItem;
  P: PString;
  Attr: Integer;
  AttrIndex: TFileAttr;
begin
  if DirectoryExists(Value) then
  begin
    FDirectory := Value;

    Items.BeginUpdate;
    try
      Items.Clear;

      //
      // Attrs
      //
      Attr := 0;
      for AttrIndex := ftReadOnly to ftNormal do
        if AttrIndex in FileType then
            Attr := Attr or Attributes[AttrIndex];

      //
      // Dirs and files.
      //
      if Attr and faDirectory <> 0 then
      begin
        FileList := GetFileDirList(FDirectory, FileMask, Attr);
        try
          for Num := 0 to Pred(FileList.Count) do
          begin
            StrPCopy(FileName, FDirectory + FileList[Num]);

            Icon := TIcon.Create;
            try
              Icon.Handle := ExtractAssociatedIcon(Application.Handle, FileName, IconIndex);

              if Assigned(LargeImages) then
                LargeImages.AddIcon(Icon);

              if Assigned(SmallImages) then
                SmallImages.AddIcon(Icon);

              Item := Items.Add;
              Item.Caption := ExtractFileName(FileName);

              P := New(PString);
              P^ := FileName;
              Item.Data := P;

              case ViewStyle of
                vsIcon:
                  if Assigned(LargeImages) then
                    Item.ImageIndex := Pred(LargeImages.Count);
                vsList,
                vsSmallIcon:
                  if Assigned(SmallImages) then
                    Item.ImageIndex := Pred(SmallImages.Count);
              end;

            finally
              Icon.Free;
            end;
          end;
        finally
          FileList.Free;
        end;
      end;
    finally
      Items.EndUpdate;
    end;
  end;
end;

procedure TCoolExplorerListView.WMDropFiles(var Message: TWMDropFiles);
var
  FileName: array [0..255] of Char;
  Num, Count: Integer;
  Icon: TIcon;
  IconIndex: Word;
  Item: TListItem;
  P: PString;
begin
  inherited;
  Count := DragQueryFile(Message.Drop, $FFFFFFFF, nil, 0);

  for Num := 0 to Pred(Count) do
  begin
    DragQueryFile(Message.Drop, Num, FileName, SizeOf(FileName));
    Icon := TIcon.Create;
    try
      Icon.Handle := ExtractAssociatedIcon(Application.Handle, FileName, IconIndex);

      LargeImages.AddIcon(Icon);
      SmallImages.AddIcon(Icon);

      Item := Items.Add;
      Item.Caption := ExtractFileName(FileName);

      P := New(PString);
      P^ := FileName;
      Item.Data := P;

      case ViewStyle of
        vsIcon:
          Item.ImageIndex := Pred(LargeImages.Count);
        vsList,
        vsSmallIcon:
          Item.ImageIndex := Pred(SmallImages.Count);
      end;
    finally
      Icon.Free;
    end;
  end;
  DragFinish(Message.Drop);
  Invalidate;
end;

procedure TCoolExplorerListView.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
  inherited;
  if Assigned(Selected) and Assigned(FOnIconDblClick) then
    FOnIconDblClick(Self, String(Selected.Data^));
end;

{$ENDIF}

{TCoolScrollBox}
constructor TCoolScrollBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FOptions := [];
  FCoolImagesChangeLink := TCoolChangeLink.Create;
  FCoolImagesChangeLink.OnChange := CoolImagesChange;
  FidWallpaper := -1;
end;

destructor TCoolScrollBox.Destroy;
begin
  FCoolImagesChangeLink.Free;
  if Assigned(FWallpaper) then FWallpaper.Free;
  inherited Destroy;
end;

procedure TCoolScrollBox.SetOptions(Value: TCoolOptions);
begin
  if FOptions <> Value then
  begin
    if (ocPaintTransparently in Value) and (ocPaintWallpaper in FOptions) then
      Exclude(Value, ocPaintWallpaper) else
        if (ocPaintWallpaper in Value) and (ocPaintTransparently in FOptions) then
          Exclude(Value, ocPaintTransparently);

    FOptions := Value;
    Perform(CM_COLORCHANGED, 0, 0);
  end;
end;

procedure TCoolScrollBox.SetTransparencyLevel(Value: Byte);
begin
  if FTransparencyLevel <> Value then
  begin
    FTransparencyLevel := Value;
    Invalidate;
  end;
end;

procedure TCoolScrollBox.SetWallpaper(Value: TBitmap);
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  FWallpaper.Assign(Value);
  Invalidate;
end;

function TCoolScrollBox.GetWallpaper: TBitmap;
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  Result := FWallpaper;
  Result.OnChange := WallpaperChanged;
end;

procedure TCoolScrollBox.WallpaperChanged(Sender: TObject);
begin
  Invalidate;
  Perform(CM_COLORCHANGED, 0, 0);
end;

procedure TCoolScrollBox.SetidWallpaper(Value: Integer);
begin
  if FidWallpaper <> Value then
  begin
    FidWallpaper := Value;
    Invalidate;
  end;
end;

procedure TCoolScrollBox.SetCoolImages(Value: TCoolImages);
begin
  if Assigned(CoolImages) then
    CoolImages.UnRegisterChanges(FCoolImagesChangeLink);

  FCoolImages := Value;

  if Assigned(CoolImages) then
    CoolImages.RegisterChanges(FCoolImagesChangeLink);

  Invalidate;
end;

function TCoolScrollBox.CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
begin
  Result := False;
  if Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty then
  begin
    DrawWallpaper(DC, FCoolImages.Images.Items[FidWallpaper].Bitmap, R, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FWallpaper) and not FWallpaper.Empty then
  begin
    DrawWallpaper(DC, FWallpaper, R, IsStretch, Mode);
    Result := True;
  end;
end;

function TCoolScrollBox.IsWallpaperAssigned: Boolean;
begin
  Result := (Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty) or
            (Assigned(FWallpaper) and not FWallpaper.Empty);
end;

procedure TCoolScrollBox.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and Assigned(FCoolImages) and (AComponent = FCoolImages) then
    CoolImages := nil;
end;

procedure TCoolScrollBox.CoolImagesChange(Sender: TObject);
begin
  Invalidate;
end;

procedure TCoolScrollBox.CMMouseEnter (var Message: TMessage);
begin
  inherited;
  if Assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TCoolScrollBox.CMMouseLeave (var Message: TMessage);
begin
  inherited;
  if Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;

procedure TCoolScrollBox.WMEraseBkGnd(var Message: TWMEraseBkGnd);
begin
  if (ocPaintTransparently in FOptions) then
    PaintBackground(TrControl(Self, FTransparencyLevel), Message.DC, True) else
      if (ocPaintWallpaper in FOptions) and IsWallpaperAssigned then
        CTLDrawWallpaper(Message.DC, ClientRect, (ocStretchWallpaper in FOptions), SRCCOPY) else
          inherited;
end;

procedure TCoolScrollBox.WMPaint(var Message: TWMPaint);
begin
  inherited;
end;

procedure TCoolScrollBox.WMSize(var Message: TWMSize);
begin
  inherited;
  if (ocPaintTransparently in FOptions) or ((ocPaintWallpaper in FOptions) and IsWallpaperAssigned) then
    Invalidate;
end;

procedure TCoolScrollBox.WMHScroll(var Message: TWMHScroll);
begin
  inherited;
  if (ocPaintTransparently in FOptions) or ((ocPaintWallpaper in FOptions) and IsWallpaperAssigned) then
    Invalidate;
end;

procedure TCoolScrollBox.WMVScroll(var Message: TWMVScroll);
begin
  inherited;
  if (ocPaintTransparently in FOptions) or ((ocPaintWallpaper in FOptions) and IsWallpaperAssigned) then
    Invalidate;
end;

{TCoolTabSheet}
constructor TCoolTabSheet.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Align := alClient;
  ControlStyle := ControlStyle + [csAcceptsControls, csNoDesignVisible];
  Visible := False;
  FTabVisible := True;
  FHighlighted := False;

///////////////////////////// CC //////////////////////////////////////
  FOptions := [];
  FCoolImagesChangeLink := TCoolChangeLink.Create;
  FCoolImagesChangeLink.OnChange := CoolImagesChange;
  FidWallpaper := -1;
  FTransparencyLevel := 0;
  FParentWallpaper := True;
///////////////////////////// CC //////////////////////////////////////
end;

destructor TCoolTabSheet.Destroy;
begin
  if FPageControl <> nil then
  begin
    if FPageControl.FUndockingPage = Self then FPageControl.FUndockingPage := nil;
    FPageControl.RemovePage(Self);
  end;
  FCoolImagesChangeLink.Free;
  FCoolImagesChangeLink := nil;
  inherited Destroy;
end;

procedure TCoolTabSheet.DoHide;
begin
  if Assigned(FOnHide) then FOnHide(Self);
end;

procedure TCoolTabSheet.DoShow;
begin
  if Assigned(FOnShow) then FOnShow(Self);
end;

function TCoolTabSheet.GetPageIndex: Integer;
begin
  if FPageControl <> nil then
    Result := FPageControl.FPages.IndexOf(Self) else
    Result := -1;
end;

function TCoolTabSheet.GetTabIndex: Integer;
var
  I: Integer;
begin
  Result := 0;
  if not FTabShowing then Dec(Result) else
    for I := 0 to PageIndex - 1 do
      if TCoolTabSheet(FPageControl.FPages[I]).FTabShowing then
        Inc(Result);
end;

procedure TCoolTabSheet.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params.WindowClass do
    style := style and not (CS_HREDRAW or CS_VREDRAW);
end;

procedure TCoolTabSheet.ReadState(Reader: TReader);
begin
  inherited ReadState(Reader);
  if Reader.Parent is TCoolPageControl then
    PageControl := TCoolPageControl(Reader.Parent);
end;

procedure TCoolTabSheet.SetImageIndex(Value: {$IFDEF DELPHI5_OR_ABOVE}TImageIndex{$ELSE}Integer{$ENDIF});
begin
  if FImageIndex <> Value then
  begin
    FImageIndex := Value;
    if FTabShowing then FPageControl.UpdateTab(Self);
  end;
end;

procedure TCoolTabSheet.SeTCoolPageControl(APageControl: TCoolPageControl);
begin
  if FPageControl <> APageControl then
  begin
    if FPageControl <> nil then FPageControl.RemovePage(Self);
    Parent := APageControl;
    if APageControl <> nil then APageControl.InsertPage(Self);
  end;
end;

procedure TCoolTabSheet.SetPageIndex(Value: Integer);
var
  I, MaxPageIndex: Integer;
begin
  if FPageControl <> nil then
  begin
    MaxPageIndex := FPageControl.FPages.Count - 1;
    if Value > MaxPageIndex then
      raise EListError.Create('Invalid Page Index: ' + IntToStr(Value));
    I := TabIndex;
    FPageControl.FPages.Move(PageIndex, Value);
    if I >= 0 then FPageControl.MoveTab(I, TabIndex);
  end;
end;

procedure TCoolTabSheet.SetTabShowing(Value: Boolean);
var
  Index: Integer;
begin
  if FTabShowing <> Value then
    if Value then
    begin
      FTabShowing := True;
      FPageControl.InsertTab(Self);
    end else
    begin
      Index := TabIndex;
      FTabShowing := False;
      FPageControl.DeleteTab(Self, Index);
    end;
end;

procedure TCoolTabSheet.SetTabVisible(Value: Boolean);
begin
  if FTabVisible <> Value then
  begin
    FTabVisible := Value;
    UpdateTabShowing;
  end;
end;

procedure TCoolTabSheet.UpdateTabShowing;
begin
  SetTabShowing((FPageControl <> nil) and FTabVisible);
end;

procedure TCoolTabSheet.CMTextChanged(var Message: TMessage);
begin
  if FTabShowing then FPageControl.UpdateTab(Self);
end;

procedure TCoolTabSheet.CMShowingChanged(var Message: TMessage);
begin
  inherited;
  if Showing then
  begin
    try
      DoShow
    except
      Application.HandleException(Self);
    end;
  end else if not Showing then
  begin
    try
      DoHide;
    except
      Application.HandleException(Self);
    end;
  end;
end;

procedure TCoolTabSheet.SetHighlighted(Value: Boolean);
begin
  {$IFDEF DELPHI4_OR_ABOVE}
  if not (csReading in ComponentState) then
    SendMessage(PageControl.Handle, TCM_HIGHLIGHTITEM, TabIndex,
      MakeLong(Word(Value), 0));
  {$ENDIF}
  FHighlighted := Value;
end;

///////////////////////////// CC //////////////////////////////////////
procedure TCoolTabSheet.SetOptions(Value: TCoolOptions);
begin
  if FOptions <> Value then
  begin
    if (ocPaintTransparently in Value) and (ocPaintWallpaper in FOptions) then
      Exclude(Value, ocPaintWallpaper) else
        if (ocPaintWallpaper in Value) and (ocPaintTransparently in FOptions) then
          Exclude(Value, ocPaintTransparently);

    FOptions := Value;
    Invalidate;
  end;
end;

procedure TCoolTabSheet.SetWallpaper(Value: TBitmap);
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  FWallPaper.Assign(Value);
  Invalidate;
end;

function TCoolTabSheet.GetWallpaper: TBitmap;
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  Result := FWallpaper;
  Result.OnChange := WallpaperChanged;
end;

procedure TCoolTabSheet.WallpaperChanged(Sender: TObject);
begin
  Invalidate;
  Perform(CM_COLORCHANGED, 0, 0);

  if Assigned(FWallpaper) and not FWallpaper.Empty then
    FParentWallpaper := False;
end;

procedure TCoolTabSheet.SetTransparencyLevel(Value: Byte);
begin
  if FTransparencyLevel <> Value then
  begin
    FTransparencyLevel := Value;
    Invalidate;
  end;
end;

procedure TCoolTabSheet.SetCoolImages(Value: TCoolImages);
begin
  if Assigned(CoolImages) then
    CoolImages.UnRegisterChanges(FCoolImagesChangeLink);

  FCoolImages := Value;

  if Assigned(CoolImages) then
    CoolImages.RegisterChanges(FCoolImagesChangeLink);

  Invalidate;
end;

procedure TCoolTabSheet.SetidWallpaper(Value: Integer);
begin
  if FidWallpaper <> Value then
  begin
    FidWallpaper := Value;
    Invalidate;
  end;
end;

procedure TCoolTabSheet.CoolImagesChange(Sender: TObject);
begin
  Invalidate;
end;

function TCoolTabSheet.CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
begin
  Result := False;
  if FParentWallpaper and Assigned(FPageControl.FWallpaper) and not FPageControl.FWallpaper.Empty then
  begin
    DrawWallpaper(DC, FPageControl.FWallpaper, R, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty then
  begin
    DrawWallpaper(DC, FCoolImages.Images.Items[FidWallpaper].Bitmap, R, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FWallpaper) and not FWallpaper.Empty then
  begin
    DrawWallpaper(DC, FWallpaper, R, IsStretch, Mode);
    Result := True;
  end;
end;

function TCoolTabSheet.IsWallpaperAssigned: Boolean;
begin
  Result := (Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty) or
            (FParentWallpaper and Assigned(FPageControl.FWallpaper) and not FPageControl.FWallpaper.Empty) or
            (Assigned(FWallpaper) and not FWallpaper.Empty);
end;

procedure TCoolTabSheet.SetParentWallpaper(Value: Boolean);
begin
  if FParentWallpaper <> Value then
  begin
    FParentWallpaper := Value;
    if FParentWallpaper and Assigned(FWallpaper) and not FWallpaper.Empty then
      FWallpaper := nil;
  end;
end;

procedure TCoolTabSheet.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
  if (ocPaintTransparently in FOptions) then
    PaintBackground(TrControl(Self, FTransparencyLevel), Message.DC, True) else
      if (ocPaintWallpaper in FOptions) and IsWallpaperAssigned then
        CTLDrawWallpaper(Message.DC, ClientRect, (ocStretchWallpaper in FOptions), SRCCOPY) else
          inherited;
end;

procedure TCoolTabSheet.CMMouseEnter (var Message: TMessage);
begin
  inherited;
  if Assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TCoolTabSheet.CMMouseLeave (var Message: TMessage);
begin
  inherited;
  if Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;

///////////////////////////// CC //////////////////////////////////////

{TCoolPageControl}
constructor TCoolPageControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := [csDoubleClicks, csOpaque];
  FPages := TList.Create;

///////////////////////////// CC //////////////////////////////////////
  FOptions := [];
  FCoolImagesChangeLink := TCoolChangeLink.Create;
  FCoolImagesChangeLink.OnChange := CoolImagesChange;
  FidWallpaper := -1;
  FTransparencyLevel := 0;
  FWallpaperWholeControl := True;
///////////////////////////// CC //////////////////////////////////////
end;

destructor TCoolPageControl.Destroy;
var
  I: Integer;
begin
  for I := 0 to FPages.Count - 1 do TCoolTabSheet(FPages[I]).FPageControl := nil;
  FPages.Free;

  FCoolImagesChangeLink.Free;
  FCoolImagesChangeLink := nil;
  inherited Destroy;
end;

procedure TCoolPageControl.UpdateTabHighlights;
var
  I: Integer;
begin
  for I := 0 to PageCount - 1 do
    Pages[I].SetHighlighted(Pages[I].FHighlighted);
end;

procedure TCoolPageControl.Loaded;
begin
  inherited Loaded;
  UpdateTabHighlights;
end;

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolPageControl.CanShowTab(TabIndex: Integer): Boolean;
begin
  Result := TCoolTabSheet(FPages[TabIndex]).Enabled;
end;
{$ENDIF}

procedure TCoolPageControl.Change;
var
{$IFNDEF VER90}
  Form: TCustomForm;
{$ELSE}
  Form: TForm;
{$ENDIF}
begin
  UpdateActivePage;
  if csDesigning in ComponentState then
  begin
    Form := GetParentForm(Self);
    if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified;
  end;
  inherited Change;
end;

procedure TCoolPageControl.ChangeActivePage(Page: TCoolTabSheet);
var
{$IFNDEF VER90}
  ParentForm: TCustomForm;
{$ELSE}
  ParentForm: TForm;
{$ENDIF}
begin
  if FActivePage <> Page then
  begin
    ParentForm := GetParentForm(Self);
    if (ParentForm <> nil) and (FActivePage <> nil) and
      FActivePage.ContainsControl(ParentForm.ActiveControl) then
    begin
      ParentForm.ActiveControl := FActivePage;
      if ParentForm.ActiveControl <> FActivePage then
      begin
        TabIndex := FActivePage.TabIndex;
        Exit;
      end;
    end;
    if Page <> nil then
    begin
      Page.BringToFront;
      Page.Visible := True;
      if (ParentForm <> nil) and (FActivePage <> nil) and
        (ParentForm.ActiveControl = FActivePage) then
        if Page.CanFocus then
          ParentForm.ActiveControl := Page else
          ParentForm.ActiveControl := Self;
    end;
    if FActivePage <> nil then FActivePage.Visible := False;
    FActivePage := Page;
    if (ParentForm <> nil) and (FActivePage <> nil) and
      (ParentForm.ActiveControl = FActivePage) then
      FActivePage.SelectFirst;
  end;
end;

procedure TCoolPageControl.DeleteTab(Page: TCoolTabSheet; Index: Integer);
var
  UpdateIndex: Boolean;
begin
  UpdateIndex := Page = ActivePage;
  Tabs.Delete(Index);
  if UpdateIndex then
  begin
    if Index >= Tabs.Count then
      Index := Tabs.Count - 1;
    TabIndex := Index;
  end;
  UpdateActivePage;
end;

{$IFDEF DELPHI4_OR_ABOVE}
procedure TCoolPageControl.DoAddDockClient(Client: TControl; const ARect: TRect);
begin
  if FNewDockSheet <> nil then Client.Parent := FNewDockSheet;
end;

procedure TCoolPageControl.DockOver(Source: TDragDockObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
var
  R: TRect;
begin
  GetWindowRect(Handle, R);
  Source.DockRect := R;
  DoDockOver(Source, X, Y, State, Accept);
end;

procedure TCoolPageControl.DoRemoveDockClient(Client: TControl);
begin
  if (FUndockingPage <> nil) and not (csDestroying in ComponentState) then
  begin
    SelectNextPage(True);
    FUndockingPage.Free;
    FUndockingPage := nil;
  end;
end;
{$ENDIF}

function TCoolPageControl.FindNextPage(CurPage: TCoolTabSheet;
  GoForward, CheckTabVisible: Boolean): TCoolTabSheet;
var
  I, StartIndex: Integer;
begin
  if FPages.Count <> 0 then
  begin
    StartIndex := FPages.IndexOf(CurPage);
    if StartIndex = -1 then
      if GoForward then StartIndex := FPages.Count - 1 else StartIndex := 0;
    I := StartIndex;
    repeat
      if GoForward then
      begin
        Inc(I);
        if I = FPages.Count then I := 0;
      end else
      begin
        if I = 0 then I := FPages.Count;
        Dec(I);
      end;
      Result := FPages[I];
      if not CheckTabVisible or Result.TabVisible then Exit;
    until I = StartIndex;
  end;
  Result := nil;
end;

{$IFNDEF VER90}
procedure TCoolPageControl.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
  I: Integer;
begin
  for I := 0 to FPages.Count - 1 do Proc(TComponent(FPages[I]));
end;
{$ENDIF}

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolPageControl.GetImageIndex(TabIndex: Integer): Integer;
var
  I,
  Visible,
  NotVisible: Integer;
begin
  if Assigned(OnGetImageIndex) then
    Result := inherited GetImageIndex(TabIndex) else
    begin
     { For a PageControl, TabIndex refers to visible tabs only. The control
     doesn't store }
      Visible := 0;
      NotVisible := 0;
      for I := 0 to FPages.Count - 1 do
      begin
        if not GetPage(I).TabVisible then Inc(NotVisible)
        else Inc(Visible);
        if Visible = TabIndex + 1 then Break;
      end;
      Result := GetPage(TabIndex + NotVisible).ImageIndex;
    end;
end;

function TCoolPageControl.GetPageFromDockClient(Client: TControl): TCoolTabSheet;
var
  I: Integer;
begin
  Result := nil;
  for I := 0 to PageCount - 1 do
  begin
    if (Client.Parent = Pages[I]) and (Client.HostDockSite = Self) then
    begin
      Result := Pages[I];
      Exit;
    end;
  end;
end;
{$ENDIF}

function TCoolPageControl.NewPage: TCoolTabSheet;
begin
  Result := TCoolTabSheet.Create(Owner);
  try
    Result.Parent := Self;
    InsertPage(Result);
  except
    Result.Free;
  end;
end;

function TCoolPageControl.GetPage(Index: Integer): TCoolTabSheet;
begin
  Result := FPages[Index];
end;

function TCoolPageControl.GetPageCount: Integer;
begin
  Result := FPages.Count;
end;

{$IFDEF DELPHI4_OR_ABOVE}
procedure TCoolPageControl.GetSiteInfo(Client: TControl; var InfluenceRect: TRect;
  MousePos: TPoint; var CanDock: Boolean);
begin
  CanDock := GetPageFromDockClient(Client) = nil;
  inherited GetSiteInfo(Client, InfluenceRect, MousePos, CanDock);
end;
{$ENDIF}

procedure TCoolPageControl.InsertPage(Page: TCoolTabSheet);
begin
  FPages.Add(Page);
  Page.FPageControl := Self;
  Page.UpdateTabShowing;
end;

procedure TCoolPageControl.InsertTab(Page: TCoolTabSheet);
begin
  Tabs.InsertObject(Page.TabIndex, Page.Caption, Page);
  UpdateActivePage;
end;

procedure TCoolPageControl.MoveTab(CurIndex, NewIndex: Integer);
begin
  Tabs.Move(CurIndex, NewIndex);
end;

procedure TCoolPageControl.RemovePage(Page: TCoolTabSheet);
var
  NextSheet: TCoolTabSheet;
begin
  NextSheet := FindNextPage(Page, True, not (csDesigning in ComponentState));
  if NextSheet = Page then NextSheet := nil;
  Page.SetTabShowing(False);
  Page.FPageControl := nil;
  FPages.Remove(Page);
  SetActivePage(NextSheet);
end;

procedure TCoolPageControl.SelectNextPage(GoForward: Boolean);
var
  Page: TCoolTabSheet;
begin
  Page := FindNextPage(ActivePage, GoForward, True);
  if (Page <> nil) and (Page <> ActivePage) and CanChange then
  begin
    TabIndex := Page.TabIndex;
    Change;
  end;
end;

procedure TCoolPageControl.SetActivePage(Page: TCoolTabSheet);
begin
  if (Page <> nil) and (Page.PageControl <> Self) then Exit;
  ChangeActivePage(Page);
  if Page = nil then
    TabIndex := -1
  else if Page = FActivePage then
    TabIndex := Page.TabIndex;
end;

procedure TCoolPageControl.SetChildOrder(Child: TComponent; Order: Integer);
begin
  TCoolTabSheet(Child).PageIndex := Order;
end;

procedure TCoolPageControl.ShowControl(AControl: TControl);
begin
  if (AControl is TCoolTabSheet) and (TCoolTabSheet(AControl).PageControl = Self) then
    SetActivePage(TCoolTabSheet(AControl));
  inherited ShowControl(AControl);
end;

procedure TCoolPageControl.UpdateTab(Page: TCoolTabSheet);
begin
  Tabs[Page.TabIndex] := Page.Caption;
end;

procedure TCoolPageControl.UpdateActivePage;
begin
  if TabIndex >= 0 then
    SetActivePage(TCoolTabSheet(Tabs.Objects[TabIndex]))
  else
    SetActivePage(nil);
end;

procedure TCoolPageControl.CMDesignHitTest(var Message: TCMDesignHitTest);
var
  HitIndex: Integer;
  HitTestInfo: TTCHitTestInfo;
begin
  HitTestInfo.pt := SmallPointToPoint(Message.Pos);
  HitIndex := SendMessage(Handle, TCM_HITTEST, 0, Longint(@HitTestInfo));
  if (HitIndex >= 0) and (HitIndex <> TabIndex) then Message.Result := 1;
end;

procedure TCoolPageControl.CMDialogKey(var Message: TCMDialogKey);
begin
  if (Focused or Windows.IsChild(Handle, Windows.GetFocus)) and
    (Message.CharCode = VK_TAB) and (GetKeyState(VK_CONTROL) < 0) then
  begin
    SelectNextPage(GetKeyState(VK_SHIFT) >= 0);
    Message.Result := 1;
  end else
    inherited;
end;

{$IFDEF DELPHI4_OR_ABOVE}
procedure TCoolPageControl.CMDockClient(var Message: TCMDockClient);
var
  IsVisible: Boolean;
  DockCtl: TControl;
begin
  Message.Result := 0;
  FNewDockSheet := TCoolTabSheet.Create(Self);
  try
    try
      DockCtl := Message.DockSource.Control;
      if DockCtl is TCustomForm then
        FNewDockSheet.Caption := TCustomForm(DockCtl).Caption;
      FNewDockSheet.PageControl := Self;
      DockCtl.Dock(Self, Message.DockSource.DockRect);
    except
      FNewDockSheet.Free;
      raise;
    end;
    IsVisible := DockCtl.Visible;
    FNewDockSheet.TabVisible := IsVisible;
    if IsVisible then ActivePage := FNewDockSheet;
    DockCtl.Align := alClient;
  finally
    FNewDockSheet := nil;
  end;
end;

procedure TCoolPageControl.CMDockNotification(var Message: TCMDockNotification);
var
  I: Integer;
  S: string;
  Page: TCoolTabSheet;
begin
  Page := GetPageFromDockClient(Message.Client);
  if Page <> nil then
    case Message.NotifyRec.ClientMsg of
      WM_SETTEXT:
        begin
          S := PChar(Message.NotifyRec.MsgLParam);
          { Search for first CR/LF and end string there }
          for I := 1 to Length(S) do
            if S[I] in [#13, #10] then
            begin
              SetLength(S, I - 1);
              Break;
            end;
          Page.Caption := S;
        end;
      CM_VISIBLECHANGED:
        Page.TabVisible := Boolean(Message.NotifyRec.MsgWParam);
    end;
  inherited;
end;

procedure TCoolPageControl.CMUnDockClient(var Message: TCMUnDockClient);
var
  Page: TCoolTabSheet;
begin
  Message.Result := 0;
  Page := GetPageFromDockClient(Message.Client);
  if Page <> nil then
  begin
    FUndockingPage := Page;
    Message.Client.Align := alNone;
  end;
end;

function TCoolPageControl.GetDockClientFromMousePos(MousePos: TPoint): TControl;
var
  i, HitIndex: Integer;
  HitTestInfo: TTCHitTestInfo;
  Page: TCoolTabSheet;
begin
  Result := nil;
  if DockSite then
  begin
    HitTestInfo.pt := MousePos;
    HitIndex := SendMessage(Handle, TCM_HITTEST, 0, Longint(@HitTestInfo));
    if HitIndex >= 0 then
    begin
      Page := nil;
      for i := 0 to HitIndex do
        Page := FindNextPage(Page, True, True);
      if (Page <> nil) and (Page.ControlCount > 0) then
      begin
        Result := Page.Controls[0];
        if Result.HostDockSite <> Self then Result := nil;
      end;
    end;
  end;
end;
{$ENDIF}

procedure TCoolPageControl.WMLButtonDown(var Message: TWMLButtonDown);
{$IFDEF DELPHI4_OR_ABOVE}
var
  DockCtl: TControl;
{$ENDIF}
begin
  inherited;
  {$IFDEF DELPHI4_OR_ABOVE}
  DockCtl := GetDockClientFromMousePos(SmallPointToPoint(Message.Pos));
  if (DockCtl <> nil) and (Style = tsTabs) then DockCtl.BeginDrag(False);
  {$ENDIF}
end;

procedure TCoolPageControl.WMLButtonDblClk(var Message: TWMLButtonDblClk);
{$IFDEF DELPHI4_OR_ABOVE}
var
  DockCtl: TControl;
{$ENDIF}
begin
  inherited;
  {$IFDEF DELPHI4_OR_ABOVE}
  DockCtl := GetDockClientFromMousePos(SmallPointToPoint(Message.Pos));
  if DockCtl <> nil then DockCtl.ManualDock(nil, nil, alNone);
  {$ENDIF}
end;

function TCoolPageControl.GetActivePageIndex: Integer;
begin
  if ActivePage <> nil then
    Result := ActivePage.GetPageIndex
  else
    Result := -1;
end;

procedure TCoolPageControl.SetActivePageIndex(const Value: Integer);
begin
  if (Value > -1) and (Value < PageCount) then
    ActivePage := Pages[Value]
  else
    ActivePage := nil;
end;

///////////////////////////// CC //////////////////////////////////////
procedure TCoolPageControl.SetOptions(Value: TCoolOptions);
begin
  if FOptions <> Value then
  begin
    if (ocPaintTransparently in Value) and (ocPaintWallpaper in FOptions) then
      Exclude(Value, ocPaintWallpaper) else
        if (ocPaintWallpaper in Value) and (ocPaintTransparently in FOptions) then
          Exclude(Value, ocPaintTransparently);

    FOptions := Value;
    Invalidate;
  end;
end;

procedure TCoolPageControl.SetWallpaper(Value: TBitmap);
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  FWallPaper.Assign(Value);
  Invalidate;
end;

function TCoolPageControl.GetWallpaper: TBitmap;
begin
  if FWallpaper = nil then FWallpaper := TBitmap.Create;
  Result := FWallpaper;
  Result.OnChange := WallpaperChanged;
end;

procedure TCoolPageControl.WallpaperChanged(Sender: TObject);
begin
  Invalidate;
  Perform(CM_COLORCHANGED, 0, 0);
end;

procedure TCoolPageControl.SetTransparencyLevel(Value: Byte);
begin
  if FTransparencyLevel <> Value then
  begin
    FTransparencyLevel := Value;
    Invalidate;
  end;
end;

procedure TCoolPageControl.SetCoolImages(Value: TCoolImages);
begin
  if Assigned(CoolImages) then
    CoolImages.UnRegisterChanges(FCoolImagesChangeLink);

  FCoolImages := Value;

  if Assigned(CoolImages) then
    CoolImages.RegisterChanges(FCoolImagesChangeLink);

  Invalidate;
end;

procedure TCoolPageControl.SetidWallpaper(Value: Integer);
begin
  if FidWallpaper <> Value then
  begin
    FidWallpaper := Value;
    Invalidate;
  end;
end;

procedure TCoolPageControl.CoolImagesChange(Sender: TObject);
begin
  Invalidate;
end;

function TCoolPageControl.CTLDrawWallpaper(DC: HDC; R: TRect; IsStretch: Boolean; Mode: Integer): Boolean;
begin
  Result := False;
  if Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty then
  begin
    DrawWallpaper(DC, FCoolImages.Images.Items[FidWallpaper].Bitmap, R, IsStretch, Mode);
    Result := True;
  end else
  if Assigned(FWallpaper) and not FWallpaper.Empty then
  begin
    DrawWallpaper(DC, FWallpaper, R, IsStretch, Mode);
    Result := True;
  end;
end;

function TCoolPageControl.IsWallpaperAssigned: Boolean;
begin
  Result := (Assigned(FCoolImages) and (FidWallpaper >= 0) and (FidWallpaper <= Pred(FCoolImages.Images.Count)) and Assigned(FCoolImages.Images.Items[FidWallpaper].Bitmap) and not FCoolImages.Images.Items[FidWallpaper].Bitmap.Empty) or
            (Assigned(FWallpaper) and not FWallpaper.Empty);
end;

procedure TCoolPageControl.SetWallpaperWholeControl(Value: Boolean);
begin
  if FWallpaperWholeControl <> Value then
  begin
    FWallpaperWholeControl := Value;
    Invalidate;
  end;
end;

procedure TCoolPageControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
  if not FWallpaperWholeControl then
    inherited
  else
    if (ocPaintTransparently in FOptions) then
      PaintBackground(TrControl(Self, FTransparencyLevel), Message.DC, True) else
        if (ocPaintWallpaper in FOptions) and IsWallpaperAssigned then
          CTLDrawWallpaper(Message.DC, ClientRect, (ocStretchWallpaper in FOptions), SRCCOPY) else
            inherited;
end;

procedure TCoolPageControl.CMMouseEnter (var Message: TMessage);
begin
  inherited;
  if Assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TCoolPageControl.CMMouseLeave (var Message: TMessage);
begin
  inherited;
  if Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;
///////////////////////////// CC //////////////////////////////////////

{$IFDEF DELPHI4_OR_ABOVE}
procedure TCoolPageControl.DrawTab(TabIndex: Integer; const Rect: TRect; Active: Boolean);
begin
  if (ocPaintTransparently in FOptions) then
    PaintBackgroundEx(TrControl(Self, FTransparencyLevel), Canvas.Handle, Rect, True) else
      if (ocPaintWallpaper in FOptions) and IsWallpaperAssigned then
        CTLDrawWallpaper(Canvas.Handle, Rect, (ocStretchWallpaper in FOptions), SRCCOPY) else
          Canvas.FillRect(Rect);

  if Assigned(OnDrawTab) then
    OnDrawTab(Self, TabIndex, Rect, Active);
end;
{$ENDIF}

{TCoolThermomitor}
constructor TCoolThermomitor.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FImageWidth := 100;
  FImageHeight := 294;

  FMax := 100;
  FMin := 0;
  FPosition := 0;
  FPositionPercent := 0;

  FTransparent := True;

  FFontCurrent := TFont.Create;
  FFontCurrent.Assign(Font);
  FFontCurrent.OnChange := FontChanged;

  FFontGoal := TFont.Create;
  FFontGoal.Assign(Font);
  FFontGoal.OnChange := FontChanged;

  FFontTitle := TFont.Create;
  FFontTitle.Assign(Font);
  FFontTitle.OnChange := FontChanged;

  FColorTitle := clWhite;
  FColorCurrent := clWhite;
  FColorGoal := clWhite;

  SetBounds(Left, Top, 195, 295);
end;

destructor TCoolThermomitor.Destroy;
begin
  FFontCurrent.Free;
  FFontGoal.Free;
  FFontTitle.Free;
  inherited Destroy;
end;

procedure TCoolThermomitor.SetMax(Value: Integer);
begin
  if (FMax <> Value) and (Value > FMin) then
  begin
    FMax := Value;
    Invalidate;
  end;
  FPositionPercent := CalculatePositionPercent;
end;

procedure TCoolThermomitor.SetLabelTitle(Value: TCaption);
begin
  if FLabelTitle <> Value then
  begin
    FLabelTitle := Value;
    Invalidate;
  end;
end;

procedure TCoolThermomitor.SetLabelGoal(Value: TCaption);
begin
  if FLabelGoal <> Value then
  begin
    FLabelGoal := Value;
    Invalidate;
  end;
end;

procedure TCoolThermomitor.SetLabelCurrent(Value: TCaption);
begin
  if FLabelCurrent <> Value then
  begin
    FLabelCurrent := Value;
    Invalidate;
  end;
end;

procedure TCoolThermomitor.SetColorTitle(Value: TColor);
begin
  if FColorTitle <> Value then
  begin
    FColorTitle := Value;
    Invalidate;
  end;
end;

procedure TCoolThermomitor.SetColorGoal(Value: TColor);
begin
  if FColorGoal <> Value then
  begin
    FColorGoal := Value;
    Invalidate;
  end;
end;

procedure TCoolThermomitor.SetColorCurrent(Value: TColor);
begin
  if FColorCurrent <> Value then
  begin
    FColorCurrent := Value;
    Invalidate;
  end;
end;

procedure TCoolThermomitor.SetFontTitle(Value: TFont);
begin
  FFontTitle.Assign(Value);
end;

procedure TCoolThermomitor.SetFontGoal(Value: TFont);
begin
  FFontGoal.Assign(Value);
end;

procedure TCoolThermomitor.SetFontCurrent(Value: TFont);
begin
  FFontCurrent.Assign(Value);
end;

procedure TCoolThermomitor.FontChanged(Sender: TObject);
begin
  Invalidate;
end;

procedure TCoolThermomitor.SetMin(Value: Integer);
begin
  if (FMin <> Value) and (Value < FMax) then
  begin
    FMin := Value;
    Invalidate;
  end;
  FPositionPercent := CalculatePositionPercent;
end;

procedure TCoolThermomitor.SetPosition(Value: Integer);
begin
  if (FPosition <> Value) and ((Value >= FMin) and (Value <= FMax)) then
  begin
    FPosition := Value;
    Invalidate;
  end;
  FPositionPercent := CalculatePositionPercent;
end;

procedure TCoolThermomitor.SetTransparent(Value: Boolean);
begin
  if FTransparent <> Value then
  begin
    FTransparent := Value;
    Invalidate;
  end;
end;

function TCoolThermomitor.CalculatePositionPercent: Integer;
begin
  Result := Trunc(FPosition * 100 / (FMax - FMin));
end;

procedure TCoolThermomitor.PaintCoolThermomitor(ACanvas: TCanvas; R: TRect);
var
  ImageRect: TRect;
  DestRect: TRect;
  ResultBitmap: TBitmap;
  TempBitmap: TBitmap;
  FillHeight: Integer;
begin
  ImageRect := Rect(0, 0, FImageWidth, FImageHeight);

  ResultBitmap := TBitmap.Create;
  try
    ResultBitmap.Width := ImageRect.Right- ImageRect.Left;
    ResultBitmap.Height := ImageRect.Bottom - ImageRect.Top;

    FillHeight := ResultBitmap.Height - Trunc(ResultBitmap.Height * FPositionPercent / 100);

    TempBitmap := TBitmap.Create;
    try
      TempBitmap.Handle := LoadBitmap(HInstance, 'BITMAP_1');
      DestRect := Rect(ImageRect.Left, FillHeight, ImageRect.Right, ImageRect.Bottom);
      ResultBitmap.Canvas.CopyRect(DestRect, TempBitmap.Canvas, DestRect);

      TempBitmap.Handle := LoadBitmap(HInstance, 'BITMAP_2');
      DestRect := Rect(ImageRect.Left, ImageRect.Top, ImageRect.Right, FillHeight);
      ResultBitmap.Canvas.CopyRect(DestRect, TempBitmap.Canvas, DestRect);

      {$IFNDEF VER90}
      ResultBitmap.Transparent := True;
      ACanvas.StretchDraw(R, ResultBitmap);
      {$ELSE}
      TransparentStretchBltEx(ACanvas.Handle, ResultBitmap.Canvas.Handle, R, ImageRect, clOlive);
      {$ENDIF}
    finally
      TempBitmap.Free;
    end;

  finally
    ResultBitmap.Free;
  end;
end;

procedure TCoolThermomitor.PaintTo(ACanvas: TCanvas; X, Y: Integer);
var
  R: TRect;
  lcPosition: Integer;
  SaveIndex: Integer;
begin
  with ACanvas do
  begin
    SaveIndex := SaveDC(Handle);
    MoveWindowOrg(Handle, X, Y);

    if not FTransparent then
    begin
      Brush.Color := Color;
      FillRect(ClientRect);
    end;

    if FLabelTitle <> '' then
    begin
      Brush.Color := FColorTitle;
      Font.Assign(FFontTitle);

      ltHeight := TextHeight(FLabelTitle) + 4;
      ltWidth := TextWidth(FLabelTitle) + 4;

      R := Rect(ClientWidth div 2 - ltWidth div 2, ClientRect.Top, ClientWidth div 2 + ltWidth div 2, ClientRect.Top + ltHeight);
      TextRect(R, R.Left + 2, R.Top + 2, FLabelTitle);
      Brush.Color := clBlack;
      FrameRect(R);
    end;

    if FLabelGoal <> '' then
    begin
      Brush.Color := FColorGoal;
      Font.Assign(FFontGoal);

      lgHeight := TextHeight(FLabelGoal) + 4;
      lgWidth := TextWidth(FLabelGoal) + 4;

      R := Rect(ClientRect.Left + 4, ClientRect.Top + ltHeight + 4, ClientRect.Left + lgWidth + 4, ClientRect.Top + lgHeight + ltHeight + 4);
      TextRect(R, R.Left + 2, R.Top + 2, FLabelGoal);
      Brush.Color := clBlack;
      FrameRect(R);
    end;

    if FLabelCurrent <> '' then
    begin
      Brush.Color := FColorCurrent;
      Font.Assign(FFontCurrent);

      lcHeight := TextHeight(FLabelCurrent) + 4;
      lcWidth := TextWidth(FLabelCurrent) + 4;

      lcPosition := Height - Trunc(Height * FPositionPercent / 100);
      R := Rect(ClientRect.Left + 4, lcPosition - lcHeight div 2, ClientRect.Left + lcWidth + 4, lcPosition + lcHeight div 2);
      TextRect(R, R.Left + 2, R.Top + 2, FLabelCurrent);
      Brush.Color := clBlack;
      FrameRect(R);
    end;

    R := Rect(ClientWidth div 2, ClientRect.Top + ltHeight + 4, ClientRect.Right, ClientRect.Bottom - ltHeight - 4);
    PaintCoolThermomitor(ACanvas, R);

    RestoreDC(Handle, SaveIndex);
  end;    
end;

{$IFDEF DELPHI4_OR_ABOVE}
procedure TCoolThermomitor.PaintTo(DC: HDC; X, Y: Integer);
{$ELSE}
procedure TCoolThermomitor.PaintToDC(DC: HDC; X, Y: Integer);
{$ENDIF}
var
  ACanvas: TCanvas;
begin
  ACanvas := TCanvas.Create;
  try
    ACanvas.Handle := DC;
    PaintTo(ACanvas, X, Y);
  finally
    ACanvas.Free;
  end;
end;

procedure TCoolThermomitor.Paint;
begin
  if csDesigning in ComponentState then
    with Canvas do
    begin
      Pen.Style := psDash;
      Brush.Style := bsClear;
      Rectangle(ClientRect.Left, ClientRect.Top, ClientRect.Right, ClientRect.Bottom);
    end;

  PaintTo(Canvas, 0, 0);
end;

{TCustomBitmapButton}
constructor TCustomBitmapButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetBounds(Left, Top, 100, 100);
  TabStop := True;

  FColors := TColorList.Create;
  FColors.OnChange := ColorListChanged;

  FShadowEffect := True;
  FPositionEffect := True;
  FMouseState := [];

  FShadowColor := clBtnHighlight;
  FShadowSize := 1;
  FShadowPos := spLeftTop;
  FSimpleView := False;
end;

destructor TCustomBitmapButton.Destroy;
begin
  DeleteRegion;
  FColors.Free;
  inherited Destroy;
end;

procedure TCustomBitmapButton.SetColors(Value: TColorList);
begin
  FColors.Assign(Value);
end;

procedure TCustomBitmapButton.SetShadowColor(Value: TColor);
begin
  if FShadowColor <> Value then
  begin
    FShadowColor := Value;
    FSimpleView := False;
    Repaint;
  end;
end;

procedure TCustomBitmapButton.SetShadowSize(Value: Byte);
begin
  if FShadowSize <> Value then
  begin
    FShadowSize := Value;
    FSimpleView := False;
    Repaint;
  end;
end;

procedure TCustomBitmapButton.SetShadowPos(Value: TShadowPosition);
begin
  if FShadowPos <> Value then
  begin
    FShadowPos := Value;
    FSimpleView := False;
    Repaint;
  end;
end;

procedure TCustomBitmapButton.SetSimpleView(Value: Boolean);
begin
  if FSimpleView <> Value then
  begin
    FSimpleView := Value;
    Repaint;
  end;
end;

procedure TCustomBitmapButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  inherited MouseDown(Button, Shift, X, Y);
  SetFocus;
  Include(FMouseState, msMouseDown);
  Invalidate;
end;

procedure TCustomBitmapButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  inherited MouseUp(Button, Shift, X, Y);
  Exclude(FMouseState, msMouseDown);
  Invalidate;
end;

procedure TCustomBitmapButton.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited KeyDown(Key, Shift);
  if (msMouseDown in FMouseState = False) and (Key in [VK_SPACE, VK_RETURN]) then
  begin
    Include(FMouseState, msMouseDown);
    Invalidate;
  end;
end;

procedure TCustomBitmapButton.KeyUp(var Key: Word; Shift: TShiftState);
begin
  inherited KeyUp(Key, Shift);
  if (msMouseDown in FMouseState) and (Key in [VK_SPACE, VK_RETURN]) then
  begin
    Exclude(FMouseState, msMouseDown);
    Invalidate;
    Click;
  end;
end;

function TCustomBitmapButton.GetColorsRegion(ABitmap: TBitmap): HRGN;
var
  Rgn: HRGN;
  X0, X, Y: Integer;
  Rects: TRectList;
begin
  Result := CreateRectRgn(0, 0, 0, 0);

  Rects := TRectList.Create;
  try
    for Y := 0 to Pred(ABitmap.Height) do
    begin
      X := 0;
      while X < Pred(ABitmap.Width) do
      begin
        X0 := X;
        while X < Pred(ABitmap.Width) do
        begin
          if FColors.IndexOf(ABitmap.Canvas.Pixels[X, Y]) <> -1 then
            Break;

          Inc(X);
        end;
        if X > X0 then
        begin
          Rgn := CreateRectRgn(X0, Y, X, Succ(Y));
          CombineRgn(Result, Result, Rgn, RGN_OR);
          DeleteObject(Rgn);
        end;
        Inc(X);
      end;
    end;
  finally
    Rects.Free;
  end;
end;

procedure TCustomBitmapButton.SetColorsRegion(ABitmap: TBitmap);
begin
  if not (csDestroying in ComponentState) then
  begin
    SetWindowRgn(Handle, 0, True);
    if FColors.Count <> 0 then
    begin
      DeleteRegion;
      Rgn := GetColorsRegion(ABitmap);
      SetWindowRgn(Handle, Rgn, True);
    end;
  end;
end;

procedure TCustomBitmapButton.DeleteRegion;
begin
  if Rgn <> 0 then
  begin
    DeleteObject(Rgn);
    Rgn := 0;
  end;
end;

{$IFNDEF VER90}
procedure TCustomBitmapButton.FadeOut(ABitmap: TBitmap);
var
  Row:  pRGBArray;
  X, Y:  Integer;
begin
  ABitmap.PixelFormat := pf24bit;

  for Y := 0 to Pred(ABitmap.Height) do
  begin
    Row := ABitmap.Scanline[Y];

    for X := 0 to Pred(ABitmap.Width) do
    begin
      if FColors.IndexOf(ABitmap.Canvas.Pixels[X, Y]) = -1 then
      begin
        Row[X].rgbtRed   := Round(Row[X].rgbtRed * 0.88);
        Row[X].rgbtGreen := Round(Row[X].rgbtGreen * 0.88);
        Row[X].rgbtBlue  := Round(Row[X].rgbtBlue * 0.88);
      end;
    end;
  end;
end;

procedure TCustomBitmapButton.FadeIn(ABitmap: TBitmap);
var
  Row:  pRGBArray;
  X, Y:  Integer;
begin
  ABitmap.PixelFormat := pf24bit;

  for Y := 0 to Pred(ABitmap.Height) do
  begin
    Row := ABitmap.Scanline[Y];

    for X := 0 to Pred(ABitmap.Width) do
    begin
      if FColors.IndexOf(ABitmap.Canvas.Pixels[X, Y]) = -1 then
      begin
        Row[X].rgbtRed   := Round(Row[X].rgbtRed / 0.88);
        Row[X].rgbtGreen := Round(Row[X].rgbtGreen / 0.88);
        Row[X].rgbtBlue  := Round(Row[X].rgbtBlue / 0.88);
      end;
    end;
  end;
end;
{$ENDIF}

procedure TCustomBitmapButton.PositionIn;
begin
  Left := Pred(Left);
  Top := Pred(Top);
end;

procedure TCustomBitmapButton.PositionOut;
begin
  Left := Succ(Left);
  Top := Succ(Top);
end;

procedure TCustomBitmapButton.CMMouseEnter(var Message: TMessage);
begin
  inherited;
  Include(FMouseState, msMouseInside);
  if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
end;

procedure TCustomBitmapButton.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  Exclude(FMouseState, msMouseInside);
  if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
end;

procedure TCustomBitmapButton.WMSetText(var Message: TMessage); 
begin
  inherited;
  Invalidate;
end;

{TCoolBitmapButton}
constructor TCoolBitmapButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FBitmap := TBitmap.Create;
  FBitmap.OnChange := BitmapChange;
end;

destructor TCoolBitmapButton.Destroy;
begin
  FBitmap.Free;
  inherited Destroy;
end;

procedure TCoolBitmapButton.SetBitmap(Value: TBitmap);
begin
  FBitmap.Assign(Value);
end;

procedure TCoolBitmapButton.BitmapChange(Sender: TObject);
begin
  if Assigned(FBitmap) and not FBitmap.Empty then
    SetBounds(Left, Top, FBitmap.Width, FBitmap.Height);

  FColors.Clear;
  Invalidate;
end;

procedure TCoolBitmapButton.ColorListChanged(Sender: TObject);
begin
  SetColorsRegion(FBitmap);
  Invalidate;
end;

procedure TCoolBitmapButton.Paint;
var
  Recty: TRect;
  Flags: Longint;
begin
  inherited Paint;
  if Assigned(FBitmap) and not FBitmap.Empty then
    Canvas.Draw(0, 0, FBitmap) else
      if (csDesigning in ComponentState) then
        with Canvas do
        begin
          Brush.Style := bsSolid;
          Brush.Color := Color;
          Pen.Style := psDash;
          Rectangle(0, 0, Width, Height);
        end;

  Recty := ClientRect;
  Flags := DT_SINGLELINE or DT_CENTER or DT_VCENTER;
  Canvas.Font.Assign(Font);
  SetBkMode(Canvas.Handle, Windows.Transparent);

  if not Enabled then
    Draw3DText(Canvas.Handle, Recty, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} spRightBottom {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, PChar(Text), Flags, clBtnShadow, clBtnHighlight, 1) else
      if FSimpleView then
        DrawText(Canvas.Handle, PChar(Text),  Length(Caption), Recty, Flags) else
          Draw3DText(Canvas.Handle, Recty, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} FShadowPos {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, PChar(Text), Flags, Font.Color, FShadowColor, FShadowSize);
end;

procedure TCoolBitmapButton.Loaded;
begin
  inherited Loaded;
  SetColorsRegion(FBitmap);
end;

procedure TCoolBitmapButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if msMouseDown in FMouseState = False then
  begin
    FBitmap.OnChange := nil;
    {$IFNDEF VER90}
    if FShadowEffect then FadeOut(FBitmap);
    {$ENDIF}
    if FPositionEffect then PositionOut;
    FBitmap.OnChange := BitmapChange;
  end;
  inherited MouseDown(Button, Shift, X, Y);
end;

procedure TCoolBitmapButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if msMouseDown in FMouseState then
  begin
    FBitmap.OnChange := nil;
    {$IFNDEF VER90}
    if FShadowEffect then FadeIn(FBitmap);
    {$ENDIF}
    if FPositionEffect then PositionIn;
    FBitmap.OnChange := BitmapChange;
  end;
  inherited MouseUp(Button, Shift, X, Y);
end;

procedure TCoolBitmapButton.KeyDown(var Key: Word; Shift: TShiftState);
begin
  if (msMouseDown in FMouseState = False) and (Key in [VK_SPACE, VK_RETURN]) then
  begin
    FBitmap.OnChange := nil;
    {$IFNDEF VER90}
    if FShadowEffect then FadeOut(FBitmap);
    {$ENDIF}
    if FPositionEffect then PositionOut;
    FBitmap.OnChange := BitmapChange;
  end;
  inherited KeyDown(Key, Shift);
end;

procedure TCoolBitmapButton.KeyUp(var Key: Word; Shift: TShiftState);
begin
  if (msMouseDown in FMouseState) and (Key in [VK_SPACE, VK_RETURN]) then
  begin
    FBitmap.OnChange := nil;
    {$IFNDEF VER90}
    if FShadowEffect then FadeIn(FBitmap);
    {$ENDIF}
    if FPositionEffect then PositionIn;
    FBitmap.OnChange := BitmapChange;
  end;
  inherited KeyUp(Key, Shift);
end;

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolBitmapButton.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
begin
  Result := True;
  if not (csDesigning in ComponentState) or (FBitmap.Width > 0) and (FBitmap.Height > 0) then
  begin
    if Align in [alNone, alLeft, alRight] then
      NewWidth := FBitmap.Width;

    if Align in [alNone, alTop, alBottom] then
      NewHeight := FBitmap.Height;
  end;
end;
{$ENDIF}

{
  Images as following:
  -------------------
  0 - Normal Image
  1 - Disabled Image
  2 - Mouse pressed image
  3 - Mouse inside image
}

{TCoolManyBitmapsButton}
constructor TCoolManyBitmapsButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FImagesChangeLink := TChangeLink.Create;
  FImagesChangeLink.OnChange := ImagesChange;
end;

destructor TCoolManyBitmapsButton.Destroy;
begin
  FImagesChangeLink.Free;
  inherited Destroy;
end;

procedure TCoolManyBitmapsButton.SetImages(Value: TCustomImageList);
begin
  if Assigned(Images) then
    Images.UnRegisterChanges(FImagesChangeLink);

  FImages := Value;

  if Assigned(Images) then
    Images.RegisterChanges(FImagesChangeLink);

  if (FImages = nil) then
    FColors.Clear;

  Invalidate;
end;

procedure TCoolManyBitmapsButton.ImagesChange(Sender: TObject);
begin
  {$IFDEF DELPHI4_OR_ABOVE}
  if Assigned(FImages) then
    SetBounds(Left, Top, FImages.Width, FImages.Height);
  {$ENDIF}

  FColors.Clear;
  Invalidate;
end;

procedure TCoolManyBitmapsButton.Notification(AComponent: TComponent; Operation: TOperation);
begin
  if (Operation = opRemove) and Assigned(FImages) and (AComponent = FImages) then
  begin
    FImages := nil;
    FColors.Clear;
    Invalidate;
  end;
end;

procedure TCoolManyBitmapsButton.Paint;
var
  Recty: TRect;
  Flags: Longint;

  procedure PaintCaption;
  begin
    Recty := ClientRect;
    Flags := DT_SINGLELINE or DT_CENTER or DT_VCENTER;
    Canvas.Font.Assign(Font);
    SetBkMode(Canvas.Handle, Windows.Transparent);

    if not Enabled then
      Draw3DText(Canvas.Handle, Recty, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} spRightBottom {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, PChar(Text), Flags, clBtnShadow, clBtnHighlight, 1) else
        if FSimpleView then
          DrawText(Canvas.Handle, PChar(Text),  Length(Caption), Recty, Flags) else
            Draw3DText(Canvas.Handle, Recty, {$IFDEF BCB}{$IFDEF VER100}SPToInt({$ENDIF}{$ENDIF} FShadowPos {$IFDEF BCB}{$IFDEF VER100}){$ENDIF}{$ENDIF}, PChar(Text), Flags, Font.Color, FShadowColor, FShadowSize);
  end;

begin
  if Assigned(FImages) then
    if Enabled then
    begin
      if msMouseDown in FMouseState then
      begin
        if FImages.Count >= 2 then
          FImages.Draw(Canvas, 0, 0, 2);

        PaintCaption;
        Exit;
      end;
      if msMouseInside in FMouseState then
      begin
        if FImages.Count >= 3 then
          FImages.Draw(Canvas, 0, 0, 3);

        PaintCaption;
        Exit;
      end;

      if FImages.Count >= 0 then
        FImages.Draw(Canvas, 0, 0, 0);
    end else
    begin
      if FImages.Count >= 1 then
        FImages.Draw(Canvas, 0, 0, 1);
    end
  else
    if (csDesigning in ComponentState) then
      with Canvas do
      begin
        Brush.Style := bsSolid;
        Brush.Color := Color;
        Pen.Style := psDash;
        Rectangle(0, 0, Width, Height);
      end;

  PaintCaption;
end;

procedure TCoolManyBitmapsButton.ColorListChanged(Sender: TObject);
begin
  CurrentImageChanged;
  Invalidate;
end;

procedure TCoolManyBitmapsButton.Loaded;
begin
  inherited Loaded;
  CurrentImageChanged;
end;

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolManyBitmapsButton.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
begin
  Result := True;
  if Assigned(FImages) then
  begin
    if Align in [alNone, alLeft, alRight] then
      NewWidth := FImages.Width;

    if Align in [alNone, alTop, alBottom] then
      NewHeight := FImages.Height;
  end;
end;
{$ENDIF}

procedure TCoolManyBitmapsButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  CurrentImageChanged;
  if msMouseDown in FMouseState = False then
  begin
    if FPositionEffect then PositionOut;
  end;
  inherited MouseDown(Button, Shift, X, Y);
end;

procedure TCoolManyBitmapsButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  CurrentImageChanged;
  if msMouseDown in FMouseState then
  begin
    if FPositionEffect then PositionIn;
  end;
  inherited MouseUp(Button, Shift, X, Y);
end;

procedure TCoolManyBitmapsButton.KeyDown(var Key: Word; Shift: TShiftState);
begin
  CurrentImageChanged;
  if (msMouseDown in FMouseState = False) and (Key in [VK_SPACE, VK_RETURN]) then
  begin
    if FPositionEffect then PositionOut;
  end;
  inherited KeyDown(Key, Shift);
end;

procedure TCoolManyBitmapsButton.KeyUp(var Key: Word; Shift: TShiftState);
begin
  CurrentImageChanged;
  if (msMouseDown in FMouseState) and (Key in [VK_SPACE, VK_RETURN]) then
  begin
    if FPositionEffect then PositionIn;
  end;
  inherited KeyUp(Key, Shift);
end;

procedure TCoolManyBitmapsButton.CurrentImageChanged;
var
  B: TBitmap;
begin
  if Assigned(FImages) then
  begin
    B := TBitmap.Create;
    try
      if Enabled then
      begin
        if msMouseDown in FMouseState then
        begin
          if FImages.Count >= 2 then
            FImages.GetBitmap(2, B);

          Exit;
        end;
        if msMouseInside in FMouseState then
        begin
          if FImages.Count >= 3 then
            FImages.GetBitmap(3, B);

          Exit;
        end;

        if FImages.Count >= 0 then
          FImages.GetBitmap(0, B);
      end else
      begin
        if FImages.Count >= 1 then
          FImages.GetBitmap(1, B);
      end;
      SetColorsRegion(B);
    finally
      B.Free;
    end;
  end;
end;


procedure TCoolManyBitmapsButton.CMMouseEnter(var Message: TMessage);
begin
  inherited;
  CurrentImageChanged;
  Invalidate;
end;

procedure TCoolManyBitmapsButton.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  CurrentImageChanged;
  Invalidate;
end;

procedure TCoolManyBitmapsButton.CMEnabledChanged(var Message: TMessage);
begin
  inherited;
  CurrentImageChanged;
  Invalidate;
end;


end.
