{

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

}

{$I versions.inc}
unit CoolTools;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, CoolUtils, CoolCtrls,
  Clipbrd, ExtCtrls, IniFiles, Registry, {$IFNDEF VER90} ShlObj, ActiveX, ComObj, {$ENDIF}
  StdCtrls, Dialogs, CoolLists, CoolPolygons, FileCtrl, Menus,
  ShellAPI {$IFDEF DELPHI4_OR_ABOVE}, ImgList {$ENDIF};

const
  // Message used in the TCoolAnimateEffects control to indicate
  // that the iteration is over.
  //   
  CM_THREADOVER = CM_BASE + 500;

type
  // Represents the display resolution setting.
  // 
  // <TABLE>
  // Value                Meaning
  // -------------        ------------------
  // dr640x480            640 x 480 pixels
  // dr800x600            800 x 600 pixels
  // dr1024x768           1024 x 768 pixels
  // dr1152x864           1152 x 864 pixels
  // dr1280x960           11280 x 960 pixels
  // dr1280x1024          11280 x 1024 pixes
  // drError              Error resolution is not supported
  // </TABLE>
  //
  TDisplayResolution = (dr640x480,
                        dr800x600,
                        dr1024x768,
                        dr1152x864,
                        dr1280x960,
                        dr1280x1024,
                        drError);

  // Represents color mode setting.
  //
  //
  // <TABLE>
  // Value         Meaning
  // ---------     -----------------
  // cm4bit        16 colors mode
  // cm8bit        256 colors mode
  // cm16bit       High coilor mode
  // cm24bit       True color mode
  // cm32bit       True color mode
  // cmError       Color modeis not supported
  // </TABLE>
  //
  TColorMode = (cm4bit,
                cm8bit,
                cm16bit,
                cm24bit,
                cm32bit,
                cmError);

  // Defines the Windows restart action.
  //
  // <TABLE>
  // Value           Meaning
  // ----------      ----------------------------    
  // rwForced        Forced shutdown
  // rwLogOff        Log off and log in with other name
  // rwPowerOff      Stand by mode
  // rwReboot        Reboot computer
  // rwShutdown      Shutdown
  // </TABLE>
  //
  TRestartWindows = (rwForced,
                     rwLogOff,
                     rwPowerOff,
                     rwReboot,
                     rwShutdown);

  // Display frequency setting.
  // 
  // <TABLE>
  // Value            Meaning
  // ----------      ----------------------------    
  // df56Hertz        56 Hertz
  // df60Hertz        60 Hertz
  // df70Hertz        70 Hertz
  // df72Hertz        72 Hertz
  // df75Hertz        75 Hertz
  // df85Hertz        85 Hertz
  // df90Hertz        90 Hertz
  // df100Hertz       100 Hertz
  // df120Hertz       120 Hertz
  // dfError          Reserved. Do not use.
  // </TABLE>
  // 
  TDisplayFrequency = (df56Hertz,
                       df60Hertz,
                       df70Hertz,
                       df72Hertz,
                       df75Hertz,
                       df85Hertz,
                       df90Hertz,
                       df100Hertz,
                       df120Hertz,
                       dfError);

  // TCoolDesktop component gives access to Windows95/98/NT4/NT5 desktop. You can change wallpaper and pattern, 
  // add and remove shortcuts etc. Much more power in this component. You can create and delete shortcuts, manipulate
  // the files and more.
  TCoolDesktop = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FRestartType: TRestartWindows;
    FDisplayFrequency: TDisplayFrequency;
    FOnDisplaySettingsChange: TNotifyEvent;

    procedure SetDisplayResolution(Value: TDisplayResolution);
    function GetDisplayResolution: TDisplayResolution;
    procedure SetColorMode(Value: TColorMode);
    function GetColorMode: TColorMode;
    procedure SetDisplayFrequency(Value: TDisplayFrequency);
    function GetDisplayFrequency: TDisplayFrequency;

    function GetWindowsDirectoryValue: TFileName;
    function GetSystemDirectoryValue: TFileName;
    function GetCurrentDirectoryValue: TFileName;
    {$IFNDEF VER90}
    function GetDesktopDirectory: TFileName;
    {$ENDIF}
  public
    {$IFNDEF VER90}
    // The physical patch to the folder containing the Windows desktop.
    property DesktopDirectory: TFileName read GetDesktopDirectory;
    {$ENDIF}
    // The physical patch to the folder containing the Windows.
    property WindowsDirectory: TFileName read GetWindowsDirectoryValue;
    // The physical patch to the folder containing the Windows system folder.
    property SystemDirectory: TFileName read GetSystemDirectoryValue;
    // The physical patch to the folder containing the application running.    
    property CurrentDirectory: TFileName read GetCurrentDirectoryValue;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // Returns the TStrings list with the names of the files and folders found in the 
    // directory specified.
    //
    // Parameters:
    //   FDirectory - Directory with the contents to be returned by the function.
    //   Filter     - Filter to apply on the contents found in the directory. Any valid DOS mask acceptable.
    //   Attr       - Attributes to apply on the contents found and accepted.
    //
    // Result:
    //   Returns the list of the files and directories matching specified criteria.
    function GetFileDirList(FDirectory, Filter: TFileName; Attr: Integer): TStringList;
    // Returns the TStrings list with the names of the folders found in the 
    // directory specified.
    //
    // Parameters:
    //   FDirectory - Directory with the contents to be returned by the function.
    //   Filter     - Filter to apply on the contents found in the directory. Any valid DOS mask acceptable.
    //   Attr       - Attributes to apply on the contents found and accepted.
    //
    // Result:
    //   Returns the list of the directories matching specified criteria.
    function GetDirList(FDirectory, Filter: TFileName; Attr: Integer): TStringList;
    // Returns the TStrings list with the names of the files found in the 
    // directory specified.
    //
    // Parameters:
    //   FDirectory - Directory with the contents to be returned by the function.
    //   Filter     - Filter to apply on the contents found in the directory. Any valid DOS mask acceptable.
    //   Attr       - Attributes to apply on the contents found and accepted.
    //
    // Result:
    //   Returns the list of the files matching specified criteria.
    function GetFileList(FDirectory, Filter: TFileName; Attr: Integer): TStringList;
    // Returns the TStrings list with the names of the files and folders found in the 
    // directory specified.
    //
    // Parameters:
    //   FDirectory - Directory with the contents to be returned by the function.
    //   Filter     - Filter to apply on the contents found in the directory. Any valid DOS mask acceptable.
    //   Attr       - Attributes to apply on the contents found and accepted.
    //
    // Result:
    //   Returns the list of the files amd directories matching specified criteria.
    function GetFileNamesOnly(AList: TStringList): TStringList;
    // Converts the value of the TColorMode type into the Integer representation.
    //
    // Parameters:
    //   Value  -  TColorMode type value to be converted into the integer.
    //
    // Result:
    //   Integer value returned by the function.
    function ColorModeToInt(Value: TColorMode): Integer;
    // Converts the value of the Integer type into the TColorMode representation.
    //
    // Parameters:
    //   Value  -  Integer type value to be converted into the TColorMode.
    //
    // Result:
    //   TColorMode value returned by the function.
    function IntToColorMode(Value: Integer): TColorMode;
    // Converts the value of the Integer type into the TDisplayFrequency representation.
    //
    // Parameters:
    //   Value  -  Integer type value to be converted into the TDisplayFrequency.
    //
    // Result:
    //   TDisplayFrequency value returned by the function.
    function IntToDisplayFrequency(Value: Integer): TDisplayFrequency;
    // Converts the value of the TDisplayFrequency type into the Integer representation.
    //
    // Parameters:
    //   Value  -  TDisplayFrequency type value to be converted into the integer.
    //
    // Result:
    //   Integer value returned by the function.
    function DisplayFrequencyToInt(Value: TDisplayFrequency): Integer;
    // Returns width of the display based on the TDisplayResolution type value.
    //
    // Parameters:
    //   Value  -  TDisplayFrequency type value to be taken the Width from.
    //
    // Result:
    //   Integer value returned by the function representing display width.
    function DisplayResolutionToWidth(Value: TDisplayResolution): Integer;
    // Returns height of the display based on the TDisplayResolution type value.
    //
    // Parameters:
    //   Value  -  TDisplayFrequency type value to be taken the Height from.
    //
    // Result:
    //   Integer value returned by the function representing display height.
    function DisplayResolutionToHeight(Value: TDisplayResolution): Integer;
    // Returns string list TStringList object filled with full names of all 
    // bitmaps (*.bmp) placed in Windows directory.
    //
    // Parameters:
    //   NamesOnly - Boolean parameter indicating whether the function should return full qualified file name with path or file name only.
    //
    // Result:
    //   TStringList with the file names.
    function GetWindowsBitmaps(NamesOnly: Boolean): TStringList;
    // Changes currently selected Windows wallpaper.
    //
    // Parameters:
    //   AWallpaper - Name of the existing bitmap file.
    //   ATiled     - Boolean parameter indicating whether wallpapers should be tiled or centered.
    procedure SetWallpaper(AWallpaper: TFileName; ATiled: Boolean);
    // Returns the file contining currently selected Windows bitmap.
    // 
    // Result:
    //   name of the file with the bitmap used for Windows wallpapers.
    function GetWallpaper: TFileName;
    // Determines whether current bitmap image painted tiled or centered.
    //
    // Result:
    //   Boolean value indicating function result.
    function GetWallpaperIsTile: Boolean;
    // Returns string list containing names of all the patterns presented in system.
    function GetPatterns: TStringList;
    // Draws specified pattern
    // 
    // Parameters:
    //   APattern - valid pattern name
    procedure SetPattern(APattern: string);
    // Returns currently chosen pattern.
    //
    // Result:
    //   String indicating the name of the pattern selected in the system.
    function GetPattern: string;
    // Returns the TStringList object filled with the names of the virtual folders.
    //
    // Result:
    //   TStringList returned by the function.
    function GetShellFolders: TStringList;
   {$IFNDEF ver90}
    // Creates shortcut to the file.
    //
    // Parameters:
    //   AFileName - Name of the file to create the shortcut to.
    //   AFolder   - Name of the folder to create the shortcut in.
    //   AParam    - Parameters to run the file with.
    //   AName     - Name of the shortcut.
    procedure SetFile(AFileName, AFolder, AParam, AName: string);
    // Creates the shortcut to the specified file and places it on the system desktop.
    //
    // Parameters:
    //   AFileName - Name of the file to create the shortcut to.
    //   AFolder   - Name of the folder to create the shortcut in.
    //   AParam    - Parameters to run the file with.
    //   AName     - Name of the shortcut.
    procedure SetDesktopFile(AFileName, AParam, AName: string);
    // Creates the shortcut to the specified file and places it to the system favorites folder.
    //
    // Parameters:
    //   AFileName - Name of the file to create the shortcut to.
    //   AFolder   - Name of the folder to create the shortcut in.
    //   AParam    - Parameters to run the file with.
    //   AName     - Name of the shortcut.
    procedure SetFavoritesFile(AFileName, AParam, AName: string);
    // Returns list of the physical files representing Windows shortcuts found on the desktop.
    //
    // Result:
    //  Returns the TStringList object built by the function.
    function GetDesktopFiles: TStringList;
    // Deletes the file from the desktop.
    //
    // Parameters:
    //   AFileDesc - Name (label) of the file to be deleted.
    //
    // Result:
    //   Boolean value indicating function's result.
    function DeleteDesktopFile(AFileDesc: string): Boolean;
   {$ENDIF}
    // Opend the file by running the program associated with the specified file.
    // 
    // Parameters:
    //   AFileName - name of the file to be opened.
    //
    // Result:
    //   Boolean value indicating function's result.
    function OpenFile(AFileName: TFileName): Boolean;
    // Adds program to Windows startup programs.
    // 
    // Parameters:
    // ATitle   - programs title. 
    // ACmdLine - full command line of the program (can be obtained via Application.ExeName or ParamStr(0) ).
    // AOnce    - determines how many times program will be executed (once or each time Windows starts).
    //
    // Result:
    //   Boolean value indicating function's result.
    procedure SetStartupProgram(ATitle, ACmdLine: string; AOnce: Boolean);
    // Removes program from Windows startup programs group. 
    //
    // Parameters:
    //   ATitle  - programs title (the same title as you have specified in SetStartupProgram procedure). 
    //   AIsOnce - determines which group program has been added to and will be remove from (ones that run once or each time Windows starts).
    //
    // See Also:
    //   SetStartupProgram
    procedure DeleteStartupProgram(ATitle: string; AIsOnce: Boolean);
    // Registers new file type in Windows. 
    //
    // Parameters:
    //   AExtension - extension (file type) you want to register.
    //   ATitle     -  Title of new type.
    //   ACmdLine   -  Full path (include executablde) to application you want to associate extension with.
    procedure RegisterFileType(AExtension, ATitle, ACmdLine: string);
    // Unregisters file type in Windows. 
    // 
    // Parameters:
    //   - AExtension - extension (file type) you want to unregister.
    procedure UnRegisterFileType(AExtension: string);
    // Restarts Windows depending on the RestartType current value.
    //
    // Result:
    //   Boolean value indicating function result.
    //
    // See Also:
    //   RestartType
    function RestartWindows: Boolean;
    // Exewcutes program.
    //
    // Parameters:
    //   FAppName   - path to the application to be executed.
    //   FAppParams - list of the parameters application will e executed with.
    //
    // Result:
    //   Boolean value indicating function result.
    function ExecuteApp(FAppName: TFileName; FAppParams: string): Boolean;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use DisplayFrequency to specify frequency of your display:
    // 
    // <TABLE>
    // Value            Meaning
    // ----------      ----------------------------    
    // df56Hertz        56 Hertz
    // df60Hertz        60 Hertz
    // df70Hertz        70 Hertz
    // df72Hertz        72 Hertz
    // df75Hertz        75 Hertz
    // df85Hertz        85 Hertz
    // df90Hertz        90 Hertz
    // df100Hertz       100 Hertz
    // df120Hertz       120 Hertz
    // dfError          Reserved. Do not use.
    // </TABLE>
    //
    // When you specify new frequency value component will test whenever it is possible to set this value with currently selected 
    // color mode/resolution on your computer and if it is not possible will reduce frequency value.
    property DisplayFrequency: TDisplayFrequency read GetDisplayFrequency write SetDisplayFrequency default df75Hertz;
    // Use DisplayResolution to specify resolution of your display.
    //
    // <TABLE>
    // Value                Meaning
    // -------------        ------------------
    // dr640x480            640 x 480 pixels
    // dr800x600            800 x 600 pixels
    // dr1024x768           1024 x 768 pixels
    // dr1152x864           1152 x 864 pixels
    // dr1280x960           11280 x 960 pixels
    // dr1280x1024          11280 x 1024 pixes
    // drError              Error resolution is not supported
    // </TABLE>
    //
    // When you specify resolution component will test whenever it is possible to set this resolution with currently selected color 
    // mode on your computer and if it it not possible will reduce resolution value.
    property DisplayResolution: TDisplayResolution read GetDisplayResolution write SetDisplayResolution stored False;
    // Use ColorMode to specify color mode of your display:
    //
    // <TABLE>
    // Value         Meaning 
    // ---------     -----------------
    // cm4bit        16 colors mode
    // cm8bit        256 colors mode
    // cm16bit       High coilor mode
    // cm24bit       True color mode
    // cm32bit       True color mode
    // cmError       Color modeis not supported
    // </TABLE>
    //
    // When you specify new color mode component will test whenever it is possible to set this mode with 
    // currently selected display resolution on your computer and if it it not possible will reduce color mode value.
    property ColorMode: TColorMode read GetColorMode write SetColorMode stored False;
    // Use RestartType to specify what kind of action will be performed when you will restart Windows:
    //
    // <TABLE>
    // Value           Meaning
    // ----------      ----------------------------    
    // rwForced        Forced shutdown
    // rwLogOff        Log off and log in with other name
    // rwPowerOff      Stand by mode
    // rwReboot        Reboot computer
    // rwShutdown      Shutdown
    // </TABLE>
    property RestartType: TRestartWindows read FRestartType write FRestartType default rwShutdown;
    // Event being fired when display settings changed.
    property OnDisplaySettingsChange: TNotifyEvent read FOnDisplaySettingsChange write FOnDisplaySettingsChange;
  end;

  // Set of the various flags that set up TCoolLocker component.
  //
  // <TABLE>
  // Value                           Meaning
  // -----------                     -----------
  // loHideTaskBar                   Hides the system task bar.
  // loHideStartBtn                  Hides start button.
  // loHideProgman                   Hides Program Manager.
  // loPreventStartBtnExisting       Deletes the start button completely (until next restart).
  // loPreventAppClosing             Prevents application from being closed by the user.
  // loPreventAppMinimizing          Prevents application from being minimized by the user.
  // loPreventCursorLoosing          Does not let the cursor to move out of the program.
  // loPreventSystemKeysWork         Locks up the system keys.
  // loAlwaysOnTopPosition           Makes main application form to be the top-most system window.
  // loTaskBarAutoHide               Enables the toolbar auto hide feature. 
  // </TABLE>
  TLockerOption = (loHideTaskBar,
                   loHideStartBtn,
                   loHideProgman,
                   loPreventStartBtnExisting,
                   loPreventAppClosing,
                   loPreventAppMinimizing,
                   loPreventCursorLoosing,
                   loPreventSystemKeysWork,
                   loAlwaysOnTopPosition,
                   loTaskBarAutoHide);

  // Contains the set of the TLockerOption flags.
  TLockerOptions = set of TLockerOption;

  // TCoolLocker is system level component that allows you to "lock" your program (form) 
  // in various ways. You can prevent your user from switching to another task, closing or 
  // minimizing application and so on.
  TCoolLocker = class(TComponent)
  private
    FEnabled: Boolean;
    FTimer: TTimer;
    FOptions: TLockerOptions;
    FWindowHook: TWndHook;
    FAboutBox: TCCAboutBox;

    procedure SetEnabled(Value: Boolean);
    procedure SetOptions(Value: TLockerOptions);
    procedure TimeredAction(Sender: TObject);

    procedure BeforeMessage(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
    procedure AfterMessage(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
    procedure ChangeControl(Sender: TObject);
  protected
    Form: TCoolForm;
    procedure SetFlags(Value: TLockerOptions); virtual;
    procedure Loaded; 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;
    // Enables or disables the component's functionality.
    property Enabled: Boolean read FEnabled write SetEnabled;
    // Manipulate the Options property to achieve the desired component's functionality.
    //
    // <TABLE>
    // Value                           Meaning
    // -----------                     -----------
    // loHideTaskBar                   Hides the system task bar.
    // loHideStartBtn                  Hides start button.
    // loHideProgman                   Hides Program Manager.
    // loPreventStartBtnExisting       Deletes the start button completely (until next restart).
    // loPreventAppClosing             Prevents application from being closed by the user.
    // loPreventAppMinimizing          Prevents application from being minimized by the user.
    // loPreventCursorLoosing          Does not let the cursor to move out of the program.
    // loPreventSystemKeysWork         Locks up the system keys.
    // loAlwaysOnTopPosition           Makes main application form to be the top-most system window.
    // loTaskBarAutoHide               Enables the toolbar auto hide feature. 
    // </TABLE>
    property Options: TLockerOptions read FOptions write SetOptions;
  end;

  // Defines the destination object for the TCoolCapture object.
  //
  TCaptureObject = (coFile, coClipboard, coDevice);
  // Determines whether the object should be captured with the default or user defined
  // dimensions.
  //
  TCaptureSize = (csDefault, csCustom);

  // TCoolCapture is non visible system component that can be used to capture any window 
  // or any part of window from your screen. Image can be captured with any ratio, any visual 
  // effect, can be saved to clipboard or disk file or can be assigned to any device (printer for 
  // example) through its handle (HBITMAP).
  TCoolCapture = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FCaptureObject: TCaptureObject;
    FCaptureSize: TCaptureSize;
    FWindowHandle: THandle;
    FCaptureRect: TRect;
    FDeviceRect: TRect;
    FDeviceContext: THandle;
    FBuffer: TBitmap;
    FFileName: TFileName;
    FZoomRatio: Cardinal;
    FCopyMode: TCopyMode;
    procedure SetZoomRatio(Value: Cardinal);
  public
    // When CaptureSize is csCustom use CaptureRect to specify portion of the window you 
    // wish to capture.
    //
    // See Also:
    //   CaptureSize
    property CaptureRect: TRect read FCaptureRect write FCaptureRect;
    // 
    //
    property DeviceRect: TRect read FDeviceRect write FDeviceRect;
    // Use DeviceContext to speify device you want to paint captured image on.
    property DeviceContext: THandle read FDeviceContext write FDeviceContext;
    {$IFDEF VER90}
    // Set CopyMode to affect the way graphical images are drawn onto the canvas. The CopyMode is used when 
    // copying an image from another canvas using the CopyRect method. CopyMode is also used by TBitmap objects when they 
    // draw themselves to a canvas.
    //
    // Use CopyMode to achieve a variety of affects when rendering an image. Achieve special effects like merged images 
    // and making parts of a bitmap transparent by combining multiple images with different CopyModes.
    // 
    // The following table shows the possible values of CopyMode. (These are constants defined in the Windows unit.)
    //
    // <TABLE>
    // Value               Meaning
    // ---------           -----------
    // cmBlackness         Fills the destination rectangle on the canvas with black.
    // cmDstInvert         Inverts the image on the canvas and ignores the source.
    // cmMergeCopy         Combines the image on the canvas and the source bitmap by using the Boolean AND operator.
    // cmMergePaint        Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator.
    // cmNotSrcCopy        Copies the inverted source bitmap to the canvas.
    // cmNotSrcErase       Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result.
    // cmPatCopy           Copies the source pattern to the canvas.
    // cmPatInvert         Combines the source pattern with the image on the canvas using the Boolean XOR operator
    // cmPatPaint          Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator.
    // cmSrcAnd            Combines the image on the canvas and source bitmap by using the Boolean AND operator.
    // cmSrcCopy           Copies the source bitmap to the canvas.
    // cmSrcErase          Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator.
    // cmSrcInvert         Combines the image on the canvas and the source bitmap by using the Boolean XOR operator.
    // cmSrcPaint          Combines the image on the canvas and the source bitmap by using the Boolean OR operator.
    // cmWhiteness         Fills the destination rectangle on the canvas with white.
    // </TABLE>
    property CopyMode: TCopyMode read FCopyMode write FCopyMode default cmSrcCopy;
    {$ENDIF}
    // Run-time and read-only. Use Buffer property to obtain the copy of screen shoot. If there is any Buffer will return it otherwise 
    // Buffer will be nil.
    property Buffer: TBitmap read FBuffer;
    // Run-time only. Use WindowHandle to specify handle of the window whose screen shoot you want to have. It can be any windowed control from any currently running application.
    property WindowHandle: THandle read FWindowHandle write FWindowHandle default 0;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // When all the properties are set up use Capture method to actually capture screen shoot. 
    // Please keep in mind that window to be captured should be foreground one (i.e. it should 
    // be placed above other windows). See API functions SetForegroundWindow() / GetForegroundWindow().
    procedure Capture;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use CaptureObject property to specify the destination for taken screen shoot.
    // 
    // <TABLE>
    // Value               Meaning
    // --------------      --------------
    // coFile              Screen shoot will be saved to disk file. See FileName property
    // coClipboard         Screen shoot will be copied to clipboard.
    // coDevice            Screen shoot will be drawn onto specified device.
    // </TABLE>
    property CaptureObject: TCaptureObject read FCaptureObject write FCaptureObject default coClipboard;
    // Use CaptureSize to set size of the windows part being captured.
    // 
    // <TABLE>
    // Value                Meaning
    //  ---------------     ------------------
    // csDefault            The whole window will be captured.
    // csCustom             Only part of window will be captured. 
    // </TABLE>
    //
    // See Also:
    //   CaptureRect 
    property CaptureSize: TCaptureSize read FCaptureSize write FCaptureSize default csDefault;
    {$IFNDEF VER90}
    // Set CopyMode to affect the way graphical images are drawn onto the canvas. The CopyMode is used when 
    // copying an image from another canvas using the CopyRect method. CopyMode is also used by TBitmap objects when they 
    // draw themselves to a canvas.
    //
    // Use CopyMode to achieve a variety of affects when rendering an image. Achieve special effects like merged images 
    // and making parts of a bitmap transparent by combining multiple images with different CopyModes.
    // 
    // The following table shows the possible values of CopyMode. (These are constants defined in the Windows unit.)
    //
    // <TABLE>
    // Value               Meaning
    // ---------           -----------
    // cmBlackness         Fills the destination rectangle on the canvas with black.
    // cmDstInvert         Inverts the image on the canvas and ignores the source.
    // cmMergeCopy         Combines the image on the canvas and the source bitmap by using the Boolean AND operator.
    // cmMergePaint        Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator.
    // cmNotSrcCopy        Copies the inverted source bitmap to the canvas.
    // cmNotSrcErase       Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result.
    // cmPatCopy           Copies the source pattern to the canvas.
    // cmPatInvert         Combines the source pattern with the image on the canvas using the Boolean XOR operator
    // cmPatPaint          Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator.
    // cmSrcAnd            Combines the image on the canvas and source bitmap by using the Boolean AND operator.
    // cmSrcCopy           Copies the source bitmap to the canvas.
    // cmSrcErase          Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator.
    // cmSrcInvert         Combines the image on the canvas and the source bitmap by using the Boolean XOR operator.
    // cmSrcPaint          Combines the image on the canvas and the source bitmap by using the Boolean OR operator.
    // cmWhiteness         Fills the destination rectangle on the canvas with white.
    // </TABLE>
    property CopyMode: TCopyMode read FCopyMode write FCopyMode default cmSrcCopy;
    {$ENDIF}
    // When CaptureObject if coFile use FileName to specify name of the file image will be saved to. 
    // Screen shoot will be saved as bitmap.
    //
    // See Also: 
    //   CaptureObject
    property FileName: TFileName read FFileName write FFileName;
    // Use ZoomRatio to point out the radio which will apply to captured image. Default value is 100 (100%).
    property ZoomRatio: Cardinal read FZoomRatio write SetZoomRatio default 100;
  end;

  // Defines possible types of the TCoolLoupe control.
  //
  // <TABLE>
  // Value           Meaning
  // ----------      ----------------
  // ltDynamic       Control will display portion of the screen under the cursor position.
  // ltStatic        Control will display portion of the screen under the specified coordinates.
  // </TABLE>
  TLoupeType = (ltDynamic, ltStatic);

  // TCoolLoupe is a visual control that can display part of the screen underneath the cursor. 
  // Can display the screen part with the any rate and copy mode.
  TCoolLoupe = class(TGraphicControl)
  private
    FAboutBox: TCCAboutBox;
    FActive: Boolean;
    FCoolCapture: TCoolCapture;
    FInterval: Cardinal;
    FTimer: TTimer;
    FZoomRatio: Cardinal;
    FCopyMode: TCopyMode;
    FLoupeType: TLoupeType;
    FLoupePosition: TPoint;

    FBevelInner,
    FBevelOuter: TPanelBevel;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;
    FOnTotalMouseMove: TMouseMoveEvent;

    procedure SetActive(Value: Boolean);
    procedure SetInterval(Value: Cardinal);
    procedure SetZoomRatio(Value: Cardinal);
    procedure SetBevelInner(Value: TPanelBevel);
    procedure SetBevelOuter(Value: TPanelBevel);

    procedure TimerEvent(Sender: TObject);
    procedure UpdateTimer;

    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Paint; override;
  public
    {$IFDEF VER90}
    // Set CopyMode to affect the way graphical images are drawn onto the canvas. The CopyMode is used when 
    // copying an image from another canvas using the CopyRect method. CopyMode is also used by TBitmap objects when they 
    // draw themselves to a canvas.
    //
    // Use CopyMode to achieve a variety of affects when rendering an image. Achieve special effects like merged images 
    // and making parts of a bitmap transparent by combining multiple images with different CopyModes.
    // 
    // The following table shows the possible values of CopyMode. (These are constants defined in the Windows unit.)
    //
    // <TABLE>
    // Value               Meaning
    // ---------           -----------
    // cmBlackness         Fills the destination rectangle on the canvas with black.
    // cmDstInvert         Inverts the image on the canvas and ignores the source.
    // cmMergeCopy         Combines the image on the canvas and the source bitmap by using the Boolean AND operator.
    // cmMergePaint        Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator.
    // cmNotSrcCopy        Copies the inverted source bitmap to the canvas.
    // cmNotSrcErase       Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result.
    // cmPatCopy           Copies the source pattern to the canvas.
    // cmPatInvert         Combines the source pattern with the image on the canvas using the Boolean XOR operator
    // cmPatPaint          Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator.
    // cmSrcAnd            Combines the image on the canvas and source bitmap by using the Boolean AND operator.
    // cmSrcCopy           Copies the source bitmap to the canvas.
    // cmSrcErase          Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator.
    // cmSrcInvert         Combines the image on the canvas and the source bitmap by using the Boolean XOR operator.
    // cmSrcPaint          Combines the image on the canvas and the source bitmap by using the Boolean OR operator.
    // cmWhiteness         Fills the destination rectangle on the canvas with white.
    // </TABLE>
    property CopyMode: TCopyMode read FCopyMode write FCopyMode default cmSrcCopy;
    {$ENDIF}
    // Use LoupePosition to set the position for the screen portion displayed by the control. 
    // 
    // See Also:
    //   LoupeType
    property LoupePosition: TPoint read FLoupePosition write FLoupePosition;
    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 Active property to set or get state of the component. When Active is True control monitors cursor movements otherwise it does not.
    property Active: Boolean read FActive write SetActive default False;
    // Use BevelInner to specify whether the inner bevel has a raised, lowered, or flat look. 
    // 
    // The inner bevel appears immediately inside the outer bevel. If there is no outer bevel (BevelOuter is bvNone), the inner bevel appears immediately inside the border.
    property BevelInner: TPanelBevel read FBevelInner write SetBevelInner default bvNone;
    // Use BevelOuter to specify whether the outer bevel has a raised, lowered, or flat look. The outer bevel appears immediately inside the border and outside the inner bevel.
    property BevelOuter: TPanelBevel read FBevelOuter write SetBevelOuter default bvNone;
    {$IFNDEF VER90}
    // Set CopyMode to affect the way graphical images are drawn onto the canvas. The CopyMode is used when 
    // copying an image from another canvas using the CopyRect method. CopyMode is also used by TBitmap objects when they 
    // draw themselves to a canvas.
    //
    // Use CopyMode to achieve a variety of affects when rendering an image. Achieve special effects like merged images 
    // and making parts of a bitmap transparent by combining multiple images with different CopyModes.
    // 
    // The following table shows the possible values of CopyMode. (These are constants defined in the Windows unit.)
    //
    // <TABLE>
    // Value               Meaning
    // ---------           -----------
    // cmBlackness         Fills the destination rectangle on the canvas with black.
    // cmDstInvert         Inverts the image on the canvas and ignores the source.
    // cmMergeCopy         Combines the image on the canvas and the source bitmap by using the Boolean AND operator.
    // cmMergePaint        Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator.
    // cmNotSrcCopy        Copies the inverted source bitmap to the canvas.
    // cmNotSrcErase       Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result.
    // cmPatCopy           Copies the source pattern to the canvas.
    // cmPatInvert         Combines the source pattern with the image on the canvas using the Boolean XOR operator
    // cmPatPaint          Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator.
    // cmSrcAnd            Combines the image on the canvas and source bitmap by using the Boolean AND operator.
    // cmSrcCopy           Copies the source bitmap to the canvas.
    // cmSrcErase          Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator.
    // cmSrcInvert         Combines the image on the canvas and the source bitmap by using the Boolean XOR operator.
    // cmSrcPaint          Combines the image on the canvas and the source bitmap by using the Boolean OR operator.
    // cmWhiteness         Fills the destination rectangle on the canvas with white.
    // </TABLE>
    property CopyMode: TCopyMode read FCopyMode write FCopyMode default cmSrcCopy;
    {$ENDIF}
    // Use Interval property to specify how often the image displayed by the control will be updated.
    property Interval: Cardinal read FInterval write SetInterval default 100; 
    // Determines the type of the control. Possible values:
    //
    // <TABLE>
    // Value            Meaning
    // ---------        --------------
    // ltDynamic        Control will display portion of the screen under the cursor position.
    // ltStatic         Control will display portion of the screen under the specified coordinates.
    // </TABLE>
    //
    // See Also:
    //   LoupePosition
    property LoupeType: TLoupeType read FLoupeType write FLoupeType default ltDynamic;
    // Use ZoomRatio to point out the radio which will apply to captured image. Default value is 100 (100%).
    property ZoomRatio: Cardinal read FZoomRatio write SetZoomRatio default 100;
    // Event fired when mouse movement occurs. This event is system wide one. That is monitor mouse movements in the whole system.
    property OnTotalMouseMove: TMouseMoveEvent read FOnTotalMouseMove write FOnTotalMouseMove;
    property Align;
    {$IFDEF DELPHI4_OR_ABOVE}
    property AutoSize;
    property Anchors;
    property BiDiMode;
    property Constraints;
    {$ENDIF}
    property DragCursor;
    {$IFDEF DELPHI4_OR_ABOVE}
    property DragKind;
    {$ENDIF}
    property DragMode;
    {$IFDEF DELPHI4_OR_ABOVE}
    property ParentBiDiMode;
    {$ENDIF}
    property ParentColor;
    property ParentShowHint;
    property ShowHint;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
    // 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;

  // TCoolLoupePolygones brings similar functionality as TCoolLoupe component but allows to define non 
  // rectangular "magnificent glass". Allow to define polygones (one or more) to display the position 
  // of screen you are interested in.
  TCoolLoupePolygones = class(TCustomControl)
  private
    FActive: Boolean;
    FCoolLoupe: TCoolLoupe;
    FPolygones: TPolygones;

    FOnMouseEnter,
    FOnMouseLeave: TNotifyEvent;
    FOnTotalMouseMove: TMouseMoveEvent;

    procedure SetActive(Value: Boolean);
    procedure SetCopyMode(Value: TCopyMode);
    function GetCopyMode: TCopyMode;
    procedure SetInterval(Value: Cardinal);
    function GetInterval: Cardinal;
    procedure SetZoomRatio(Value: Cardinal);
    function GetZoomRatio: Cardinal;
    function GetLoupeType: TLoupeType;
    procedure SetLoupeType(Value: TLoupeType);
    function GetLoupePosition: TPoint;
    procedure SetLoupePosition(Value: TPoint);

    procedure SetPolygones(Value: TPolygones);
    procedure SetPolyRegiones;

    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  protected
    procedure Loaded; override;
    procedure ApplyPolygones; virtual;
    procedure Paint; override;
  public
    {$IFDEF VER90}
    // Set CopyMode to affect the way graphical images are drawn onto the canvas. The CopyMode is used when 
    // copying an image from another canvas using the CopyRect method. CopyMode is also used by TBitmap objects when they 
    // draw themselves to a canvas.
    //
    // Use CopyMode to achieve a variety of affects when rendering an image. Achieve special effects like merged images 
    // and making parts of a bitmap transparent by combining multiple images with different CopyModes.
    // 
    // The following table shows the possible values of CopyMode. (These are constants defined in the Windows unit.)
    //
    // <TABLE>
    // Value               Meaning
    // ---------           -----------
    // cmBlackness         Fills the destination rectangle on the canvas with black.
    // cmDstInvert         Inverts the image on the canvas and ignores the source.
    // cmMergeCopy         Combines the image on the canvas and the source bitmap by using the Boolean AND operator.
    // cmMergePaint        Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator.
    // cmNotSrcCopy        Copies the inverted source bitmap to the canvas.
    // cmNotSrcErase       Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result.
    // cmPatCopy           Copies the source pattern to the canvas.
    // cmPatInvert         Combines the source pattern with the image on the canvas using the Boolean XOR operator
    // cmPatPaint          Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator.
    // cmSrcAnd            Combines the image on the canvas and source bitmap by using the Boolean AND operator.
    // cmSrcCopy           Copies the source bitmap to the canvas.
    // cmSrcErase          Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator.
    // cmSrcInvert         Combines the image on the canvas and the source bitmap by using the Boolean XOR operator.
    // cmSrcPaint          Combines the image on the canvas and the source bitmap by using the Boolean OR operator.
    // cmWhiteness         Fills the destination rectangle on the canvas with white.
    // </TABLE>
    property CopyMode: TCopyMode read GetCopyMode write SetCopyMode default cmSrcCopy;
    {$ENDIF}
    // Use LoupePosition to set the position for the screen portion displayed by the control. 
    // 
    // See Also:
    //   LoupeType
    property LoupePosition: TPoint read GetLoupePosition write SetLoupePosition;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    // Use Active property to set or get state of the component. When Active is True control monitors cursor movements otherwise it does not.
    property Active: Boolean read FActive write SetActive default False;
    {$IFNDEF VER90}
    // Set CopyMode to affect the way graphical images are drawn onto the canvas. The CopyMode is used when 
    // copying an image from another canvas using the CopyRect method. CopyMode is also used by TBitmap objects when they 
    // draw themselves to a canvas.
    //
    // Use CopyMode to achieve a variety of affects when rendering an image. Achieve special effects like merged images 
    // and making parts of a bitmap transparent by combining multiple images with different CopyModes.
    // 
    // The following table shows the possible values of CopyMode. (These are constants defined in the Windows unit.)
    //
    // <TABLE>
    // Value               Meaning
    // ---------           -----------
    // cmBlackness         Fills the destination rectangle on the canvas with black.
    // cmDstInvert         Inverts the image on the canvas and ignores the source.
    // cmMergeCopy         Combines the image on the canvas and the source bitmap by using the Boolean AND operator.
    // cmMergePaint        Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator.
    // cmNotSrcCopy        Copies the inverted source bitmap to the canvas.
    // cmNotSrcErase       Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result.
    // cmPatCopy           Copies the source pattern to the canvas.
    // cmPatInvert         Combines the source pattern with the image on the canvas using the Boolean XOR operator
    // cmPatPaint          Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator.
    // cmSrcAnd            Combines the image on the canvas and source bitmap by using the Boolean AND operator.
    // cmSrcCopy           Copies the source bitmap to the canvas.
    // cmSrcErase          Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator.
    // cmSrcInvert         Combines the image on the canvas and the source bitmap by using the Boolean XOR operator.
    // cmSrcPaint          Combines the image on the canvas and the source bitmap by using the Boolean OR operator.
    // cmWhiteness         Fills the destination rectangle on the canvas with white.
    // </TABLE>
    property CopyMode: TCopyMode read GetCopyMode write SetCopyMode default cmSrcCopy;
    {$ENDIF}
    // Use Interval property to specify how often the image displayed by the control will be updated.
    property Interval: Cardinal read GetInterval write SetInterval default 100;
    // Determines the type of the control. Possible values:
    //
    // <TABLE>
    // Value            Meaning
    // ---------        --------------
    // ltDynamic        Control will display portion of the screen under the cursor position.
    // ltStatic         Control will display portion of the screen under the specified coordinates.
    // </TABLE>
    //
    // See Also:
    //   LoupePosition
    property LoupeType: TLoupeType read GetLoupeType write SetLoupeType default ltDynamic;
    // Use Polygones to access the collection of the TSinglePolygon object previously created and
    // contained by the control.
    property Polygones: TPolygones read FPolygones write SetPolygones;
    // Use ZoomRatio to point out the radio which will apply to captured image. Default value is 100 (100%).
    property ZoomRatio: Cardinal read GetZoomRatio write SetZoomRatio default 100;
    // 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;
    // Event fired when mouse movement occurs. This event is system wide one. That is monitor mouse movements in the whole system.
    property OnTotalMouseMove: TMouseMoveEvent read FOnTotalMouseMove write FOnTotalMouseMove;
  end;

  // Structure defines the fields required to describe  particular window
  // in the system.
  PWindowInfo = ^TWindowInfo;
  TWindowInfo = packed record
    // window's caption
    wTitle      : array[0..255] of Char;
    // name of window's class
    wClassName  : array[0..255] of Char;
    // Handle of a window.
    wHandle     : THandle;
    // Style flags of a window.
    wStyle      : LongInt;
    // Extended style flags of a window.
    wExStyle    : LongInt;
    // Window rect. That is rectangle defining window's coordinates.
    wWindowRect : TRect;
    // Window rect. That is rectangle defining window's client rect coordinates.
    wClientRect : TRect;
    // Enabled state of a window.
    wEnabled    : Boolean;
    // Visible state of a window.
    wVisible    : Boolean;
    // Maximized state of a window.
    wMaximized  : Boolean;
    // Minimized state of a window.
    wMinimized  : Boolean;
  end;

  // TCoolWindowsInformant is non visible system component that provides complete information  
  // about all system windows, or windows  which are children of specified one.
  TCoolWindowsInformant = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FWinList: TList;
    FHandle,
    FParentHandle: THandle;
    FInterval: Cardinal;
    FTimered: Boolean;
    FOnWindowsUpdating: TNotifyEvent;
    FOnWindowsUpdated: TNotifyEvent;
    function GetCount: Integer;
    function GetWindow(Index: Integer): PWindowInfo;
    procedure SetTimered(Value: Boolean);
    procedure SetInterval(Value: Cardinal);

    procedure ClearList;
    procedure UpdateTimer;
  protected
    procedure WndProc(var Msg: TMessage); virtual;
    procedure Loaded; override;
  public
    // Use Count property to obtain the count of the windows currently added into the component's list.
    property Count: Integer read GetCount;
    // Run-time. Use ParentHandle to determine handle of the window whose children's information  
    // will be adde to list. By default ParentHandle is 0 what means al system windows will be observed.
    property ParentHandle: THandle read FParentHandle write FParentHandle default 0;
    // Use Window property to obtain information about window with the index Index. This property points   
    // to TWindowInfo structure which holds window parameters. Since Window is pointer when in use it should 
    // be coded as any other pointer (for example Window[1]^.wTitle will return title of the window which is in list with index 1).
    property Window[Index: Integer]: PWindowInfo read GetWindow; default;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // Use UpdateWindows method to update list of the windows whose information currently holded by 
    // component.  You should call this method each time you change value of ParentHandle property. 
    //
    // See Also:
    //   ParentHandle
    //   Timered
    procedure UpdateWindows;
    // You can obtain information about certain window using this method. 
    //
    // Parameters:
    //   AHandle - handle of a window you're collecting information about. It does not have to be one of the windows currently in list. Can be any valid system window. 
    //   AInfo   - The structure will be filled with the data collected.
    procedure CertainWindowInfo(AHandle: THandle; var AInfo: PWindowInfo);
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // When windows list being updated automatically every specified period of time use Interval property to actually set up this period. Specified value is in miliseconds.
    //
    // See Also:
    //   Timered
    property Interval: Cardinal read FInterval write SetInterval default 1000;
    // Component can update list atomatically every specified time. Se Timeredto True when you want this feature.
    //
    // See Also:
    //   Interval
    property Timered: Boolean read FTimered write SetTimered default False;
    // Event occurs before windows list updated.
    property OnWindowsUpdating: TNotifyEvent read FOnWindowsUpdating write FOnWindowsUpdating;
    // Event occurs after windows list updated.
    property OnWindowsUpdated: TNotifyEvent read FOnWindowsUpdated write FOnWindowsUpdated;
  end;

  // Tray icon component. Displays icon in the tray area. Icon can be static or 
  // animated (in the latter case works together with TimageList). Icon can be previewed in 
  // design time (use component's editor available from component's menu).
  TCoolTrayIcon = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FActive: Boolean;
    FAnimated: Boolean;
    FHandle: THandle;
    FIcon: TIcon;
    FToolTip: string;
    FImageChangeLink: TChangeLink;
    FIcons: TImageList;
    FInterval: Cardinal;
    FIconIndex: Integer;
    FPopupMenu: TPopupMenu;
    FOwnerDrawMenu: Boolean;
    FPreview: Boolean;

    FOnMouseUp,
    FOnMouseDown,
    FOnDoubleClick: TMouseEvent;

    procedure SetActive(Value: Boolean);
    procedure SetAnimated(Value: Boolean);
    procedure SetIcon(Value: TIcon);
    procedure SetToolTip(Value: string);
    procedure SetIcons(Value: TImageList);
    procedure SetInterval(Value: Cardinal);
    procedure SetPopupMenu(Value: TPopupMenu);
    procedure SetPreview(Value: Boolean);
    function GetPreview: Boolean;

    procedure IconChange(Sender: TObject);
    procedure IconsChange(Sender: TObject);
    procedure UpdateTimer;
    procedure UpdateIcon;
    procedure ModifyIcon(AIcon: TIcon);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Loaded; override;
    procedure WndProc(var Message: TMessage); virtual;
    procedure MouseDown(Button: TMouseButton); dynamic;
    procedure MouseUp(Button: TMouseButton); dynamic;
    procedure DoubleClick(Button: TMouseButton); dynamic;
  public
    // Set to True when you would like to previiew the icon work in design time.
    property Preview: Boolean read GetPreview write SetPreview;
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Active property determines whenever tray icon is visible or not.  
    property Active: Boolean read FActive write SetActive default False;
    // If Animated then (if Icons assigned) animated icon will be displayed otherwise icon will be a static one (Icon property).
    //
    // See Also:
    //   Icons
    property Animated: Boolean read FAnimated write SetAnimated default False;
    // Icon to be shown (if static icon).
    //
    // See Also:
    //   Animated
    property Icon: TIcon read FIcon write SetIcon;
    // Icons animated set will be created from (if animated icon).
    //
    // See Also:
    //   Animated
    property Icons: TImageList read FIcons write SetIcons;
    // If component displays animated icons Interval determineshow often new icon will be taken from the list.
    //
    // See Also:
    //   Animated
    //   Icons
    property Interval: Cardinal read FInterval write SetInterval default 200;
    // If PopupMenu assigned OwnerDrawMenu controls the way menu will be activated. 
    // If True then API TrackPopupMenu() will be used, otherwise Popup() method of the TPopupMenu component.
    property OwnerDrawMenu: Boolean read FOwnerDrawMenu write FOwnerDrawMenu default False;
    // PopupMenu points to TPopupMenu component that will be activated when icon is clicked.
    property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
    // Tool tip to be shown when mouse moves over the icon.
    property ToolTip: string read FToolTip write SetToolTip;
    // Event occurs when mouse is in icon area and mouse button was hit down.
    property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
    // Event occurs when mouse is in icon area and mouse button was released.
    property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;
    // Event occurs when mouse is in icon area and mouse button was CLICKED twice.
    property OnDoubleClick: TMouseEvent read FOnDoubleClick write FOnDoubleClick;
  end;

  // Defines the TCoolInstancesChecker component's possible action.
  //
  // <TABLE>
  // Value                 Meaning
  // ----------            ----------
  // iaStartNew            New instance allowed.
  // iaSwitchToPrevious    New instance will be closed and previous will be brought to top.
  // iaCloseAll            All instances of an application will be closed.
  // </TABLE>
  TInstanceAction = (iaStartNew, iaSwitchToPrevious, iaCloseAll);

  // TCoolInstancesChecker component when put onto main form checks if the current instance of application is the unique one.
  TCoolInstancesChecker = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FInstanceID: Integer;
    FInstanceAction: TInstanceAction;
    procedure InstancesCheck;
  protected
    procedure Loaded; 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;
    // Determies what action should be performed when component founds instance of the program that was loaded before current.
    //
    // <TABLE>
    // Value                 Meaning
    // ----------            ----------
    // iaStartNew            New instance allowed.
    // iaSwitchToPrevious    New instance will be closed and previous will be brought to top.
    // iaCloseAll            All instances of an application will be closed.
    // </TABLE>
    property InstanceAction: TInstanceAction read FInstanceAction write FInstanceAction default iaSwitchToPrevious;
  end;

  // TCoolDisksInformant provides you with the information about the drives currently found in your system.
  TCoolDisksInformant = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FDrives: TStringList;
    FDrive: TFileName;
    procedure SetDrive(Value: TFileName);
    function GetDrives: TStringList;
    function GetDriveType: TDriveType;
    function GetDriveTypeStr: string;
    {$IFDEF DELPHI4_OR_ABOVE}
    function GetTotalBytes: int64;
    function GetFreeBytes: int64;
    {$ELSE}
    function GetTotalBytes: DWORD;
    function GetFreeBytes: DWORD;
    {$ENDIF}
    function GetVolumeName: string;
    procedure SetVolumeName(Value: string);
    function GetFileSystemName: string;
  public
    //Run-time and read only. Drives contains list of all the drives that are in your system at the time.
    property Drives: TStringList read GetDrives;                                                          
    // Use DriveType to onbtain information about the type of currently selected device.
    property DriveType: TDriveType read GetDriveType;
    // Use DriveType to onbtain information about the type of currently selected drive in string representation.
    property DriveTypeStr: string read GetDriveTypeStr; 
    {$IFDEF DELPHI4_OR_ABOVE}
    // Capability of the selected drive in bytes.
    property TotalBytes: int64 read GetTotalBytes;
    // Free space of the selected drive in bytes.
    property FreeBytes: int64 read GetFreeBytes;
    {$ELSE}
    // Capability of the selected drive in bytes.
    property TotalBytes: DWORD read GetTotalBytes;
    // Free space of the selected drive in bytes.
    property FreeBytes: DWORD read GetFreeBytes;
    {$ENDIF}
    // File system on the selected drive.    
    property FileSystemName: string read GetFileSystemName;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // One of the drives from Drives list can be selected to this property. 
    // This drive becomes active and all other properties and methods of the component will return / set information about this drive.
    property Drive: TFileName read FDrive write SetDrive;
    // Volume name of the selected drive.
    property VolumeName: string read GetVolumeName write SetVolumeName;
  end;

  // TCoolAnimate component can be used to create simple animation effects without using AVI or other special animated 
  // file formats. You do not have to create special "wide" bitmap with all the frames as well. Just use TCoolImages component as bitmaps storage.
  TCoolAnimate = class(TGraphicControl)
  private
    FAboutBox: TCCAboutBox;
    FActive: Boolean;
    FHandle: THandle;
    FCoolImageChangeLink: TCoolChangeLink;
    FCoolImages: TCoolImages;
    FInterval: Cardinal;
    FImageIndex: Integer;

    FBevelInner,
    FBevelOuter: TPanelBevel;

    FTransparent: Boolean;

    procedure SetActive(Value: Boolean);
    procedure SetCoolImages(Value: TCoolImages);
    procedure SetInterval(Value: Cardinal);
    procedure SetBevelInner(Value: TPanelBevel);
    procedure SetBevelOuter(Value: TPanelBevel);
    procedure UpdateTimer;
    procedure CoolImagesChange(Sender: TObject);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Loaded; override;
    procedure WndProc(var Message: TMessage); override;
    procedure Paint; override;
    {$IFDEF DELPHI4_OR_ABOVE}
    function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
    {$ENDIF}
  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 Active property to set state of the component. When Active is True animation occurs otherwise it does not.
    property Active: Boolean read FActive write SetActive default False;
    // Use BevelInner to specify whether the inner bevel has a raised, lowered, or flat look. 
    // 
    // The inner bevel appears immediately inside the outer bevel. If there is no outer bevel (BevelOuter is bvNone), the inner bevel appears immediately inside the border.
    property BevelInner: TPanelBevel read FBevelInner write SetBevelInner default bvNone;
    // Use BevelOuter to specify whether the outer bevel has a raised, lowered, or flat look. The outer bevel appears immediately inside the border and outside the inner bevel.
    property BevelOuter: TPanelBevel read FBevelOuter write SetBevelOuter default bvNone;
    // Use CoolImages property to specify  TCoolImages component will be used 
    // to load images for wallpapers from. TcoolImages acts much like 
    // TImageList that is behaves as placeholder for images. It can contain
    // images only but images of different sizes and color modes can be stored 
    // together in the same object.
    property CoolImages: TCoolImages read FCoolImages write SetCoolImages;
    // Use Interval property to control speed of the control frames updating.
    property Interval: Cardinal read FInterval write SetInterval default 200;
    // Determines whenever image should be drawn as transparent or not.
    property Transparent: Boolean read FTransparent write FTransparent default False;
    property Align;
    {$IFDEF DELPHI4_OR_ABOVE}
    property AutoSize;
    property Anchors;
    property BiDiMode;
    property Constraints;
    {$ENDIF}
    property DragCursor;
    {$IFDEF DELPHI4_OR_ABOVE}
    property DragKind;
    {$ENDIF}
    property DragMode;
    {$IFDEF DELPHI4_OR_ABOVE}
    property ParentBiDiMode;
    {$ENDIF}
    property ParentColor;
    property ParentShowHint;
    property ShowHint;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
  end;

  // Defines various animated effects for the TCoolAnimateEffects control.
  TAnimateEffect = (aeStripesDown,
                    aeStripesUp,
                    aeStripesLeft,
                    aeStripesRight,
                    aeStripesTBCenter,
                    aeStripesLRCenter,
                    aeStripesCenterTB,
                    aeStripesCenterLR,
                    aeStripesPartsHz,
                    aeStripesPartsVt);

  // Event to be fired when the single animation.
  TAnimationEvent = procedure(Sender: TObject; Index: Integer; var DoContinue: Boolean) of Object;

  TCoolAnimateEffects = class;

  // Contains the routines to draw single iteration of the effects.
  TAnimateThread = class(TThread)
  private
    R: TRect;
    FEffect: TAnimateEffect;
    FSourceBmp, FDestBmp: TBitmap;
    FHandle: THandle;
    FCanvas: TCanvas;
    FExclusive: Boolean;

    procedure CopyRect;

    procedure DoTopToBottom;
    procedure DoBottomToTop;
    procedure DoLeftToRight;
    procedure DoRightToLeft;
    procedure DoTopBottomToCenter;
    procedure DoLeftRightToCenter;
    procedure DoCenterToTopBottom;
    procedure DoCenterToLeftRight;
    procedure DoPartsHorizontally;
    procedure DoPartsVertically;
  protected
    function ReasonToStop: Boolean;
    procedure Execute; override;
  public
    constructor Create(Handle: THandle; SourceBmp, DestBmp: TBitmap; Effect: TAnimateEffect; Canvas: TCanvas; Exclusive: Boolean);
    destructor Destroy; override;
  end;

  // TCoolAnimateEffects can be used to display set of images with various fancy visual effects.
  TCoolAnimateEffects = class(TGraphicControl)
  private
    FAboutBox: TCCAboutBox;
    FActive: Boolean;
    FAnimateEffect: TAnimateEffect;
    FCoolImages: TCoolImages;
    FCoolImagesChangeLink: TCoolChangeLink;
    FHandle: THandle;
    FImageIndex: Integer;
    FBackground: TBitmap;
    FExclusive: Boolean;

    FThread: TAnimateThread;

    FOnAnimationStart: TAnimationEvent;
    FOnAnimationEnd: TAnimationEvent;

    procedure SetActive(Value: Boolean);
    procedure SetAnimateEffect(Value: TAnimateEffect);
    procedure SetCoolImages(Value: TCoolImages);

    procedure CoolImagesChange(Sender: TObject);
    procedure BackgroundChange(Sender: TObject);

    procedure StartProcess;
    procedure EndProcess;
    procedure UpdateTimer;

    procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
    procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Paint; override;
    procedure Loaded; override;
    procedure WndProc(var Message: TMessage); override;
    {$IFDEF DELPHI4_OR_ABOVE}
    function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
    {$ENDIF}
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // Fills he control's canvas with the specified color. Provides the way to clear the canvas.
    //
    // Parameters:
    //   AColor - Color to fill the canvas with.
    procedure FillTheControl(AColor: TColor);
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Use Active to either start or stop the process of images displaying.
    property Active: Boolean read FActive write SetActive default False;
    // Use to select the particular effect image will be displayed with.
    property AnimateEffect: TAnimateEffect read FAnimateEffect write SetAnimateEffect default aeStripesDown;
    // Use CoolImages property to specify  TCoolImages component will be used 
    // to load images for animation from. TcoolImages acts much like 
    // TImageList that is behaves as placeholder for images. It can contain
    // images only but images of different sizes and color modes can be stored 
    // together in the same object.
    property CoolImages: TCoolImages read FCoolImages write SetCoolImages;
    // Defines how the threading model will work. \Exclusive mode takes more resources but works much stable.
    property Exclusive: Boolean read FExclusive write FExclusive default False;
    // event occurs when new image is about to be displayed.
    property OnAnimationStart: TAnimationEvent read FOnAnimationStart write FOnAnimationStart;
    // event occurs when image was displayed.
    property OnAnimationEnd: TAnimationEvent read FOnAnimationEnd write FOnAnimationEnd;
    property Align;
    {$IFDEF DELPHI4_OR_ABOVE}
    property AutoSize;
    property Anchors;
    property BiDiMode;
    property Constraints;
    {$ENDIF}
    property Color;
    property DragCursor;
    {$IFDEF DELPHI4_OR_ABOVE}
    property DragKind;
    {$ENDIF}
    property DragMode;
    {$IFDEF DELPHI4_OR_ABOVE}
    property ParentBiDiMode;
    {$ENDIF}
    property ParentColor;
    property ParentShowHint;
    property ShowHint;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
  end;

  // Defines possible destination for the TCoolCaptionEffects component.
  //
  // <TABLE>
  // Value            Meaning
  // -------------    --------------------
  // etForm           Currently selected effect affects caption.
  // etApplication    Currently selected effect affects form's title.
  // </TABLE>          
  TEffectTarget = (etForm, etApplication);
  // Set of the flags defined in TEffectTarget type.
  TEffectTargets = set of TEffectTarget;
  // Defines types of possible visual effects.
  //
  // <TABLE>
  // Value                   Meaning
  // -------------           --------------------
  // ekCaptionScrolling      The caption/title text will scroll horizontally.
  // ekCaptionBlinking       The caption/title text will blink repeatedly.
  // ekBlinking              The form/application's button will blink repeatedly.
  // </TABLE>          
  TEffectKind = (ekCaptionScrolling, ekCaptionBlinking, ekBlinking);

  // TCoolCaptionEffects allows to display the caption text and/or application title (visible on the 
  // button on the task bar) in various ways. The caption text can be scrolled, caption or its text 
  // can flicker and more.
  TCoolCaptionEffects = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FFormScrollBy: Integer;
    FAppScrollBy: Integer;
    FFormReverse: Boolean;
    FAppReverse: Boolean;
    FFormCaption: string;
    FApplicationTitle: string;

    FTimer: TTimer;
    {$ifndef ver90}
    FForm: TCustomForm;
    {$else}
    FForm: TForm;
    {$endif}
    FActive: Boolean;
    FInterval: Cardinal;
    FEffectTargets: TEffectTargets;
    FEffectKind: TEffectKind;

    procedure SetActive(Value: Boolean);
    procedure SetInterval(Value: Cardinal);
    procedure SetEffectKind(Value: TEffectKind);
    procedure SetEffectTargets(Value: TEffectTargets);

    procedure ScrollFormCaption;
    procedure ScrollApplicationTitle;
    procedure TimerAction(Sender: TObject);
  protected
    procedure Loaded; 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 Active property to specify whether currently selected effect should be applied to the caption 
    // or application title on the task bar button.
    property Active: Boolean read FActive write SetActive default False;
    // Use EffectTarget to specify what element the chosen effect will be applied to.  Form's caption or application's title or both.
    // 
    // <TABLE>
    // Value               Meaning
    // --------------      ----------------  
    // etForm              Currently selected effect affects caption.
    // etApplication       Currently selected effect affects form's title.
    // </TABLE>
    // 
    // See Also:
    //   EffectKind 
    property EffectTargets: TEffectTargets read FEffectTargets write SetEffectTargets default [etForm];
    // EffectKind property determines what kind of a visual effect will be applied to the form's caption or application's title (depending on EffectTargets value).
    // 
    // <TABLE>          
    // Value                    Meaning
    // ------------------       -----------------------------
    // ekCaptionScrolling       The caption/title text will scroll horizontally.
    // ekCaptionBlinking        The caption/title text will blink repeatedly.
    // ekBlinking               The form/application's button will blink repeatedly.
    // </TABLE>          
    //
    // See Also:
    //   EffectTargets
    property EffectKind: TEffectKind read FEffectKind write SetEffectKind default ekCaptionScrolling;
    // All visual effects component comes with are continuously repeated. The interval between the iterations set in the Interval property.
    property Interval: Cardinal read FInterval write SetInterval default 200;
  end;

  // Defines possible shadow destinations.
  //
  // <TABLE>
  // Value                   Meaning
  // --------------          ---------------------------
  // soLeftTop               Shadow will be dropped to the left top corner
  // soRightTop              Shadow will be dropped to the right top corner
  // soLeftBottom            Shadow will be dropped to the left bottom corner
  // soRightBottom           Shadow will be dropped to the right bottom corner
  // </TABLE>
  TShadowOrientation = (soLeftTop, soRightTop, soLeftBottom, soRightBottom);

  // TcoolShadow provides with the easy way to add the shadow visual effect to any (most) VCL and third 
  // party visual controls. Place this component to the for and assign its ShadowControl basically nothing 
  // also requied to make the control drop shadow.
  TCoolShadow = class(TGraphicControl)
  private
    FAboutBox: TCCAboutBox;
    FShadowOrientation: TShadowOrientation;
    FShadowControl: TControl;
    FShadowSize: Integer;
    procedure SetShadowOrientation(Value: TShadowOrientation);
    procedure SetShadowControl(Value: TControl);
    procedure SetShadowSize(Value: Integer);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Paint; override;
    procedure ApplyShadow; virtual;
  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;
    // The ShadowOrientation property determines what kind of a shadow will be drawn. I.e. the direction shadow will be dropped to.
    // 
    // <TABLE>
    // Value             Meaning
    // -----------       --------------------
    // soLeftTop         Shadow will be dropped to the left top corner
    // soRightTop        Shadow will be dropped to the right top corner
    // soLeftBottom      Shadow will be dropped to the left bottom corner
    // soRightBottom     Shadow will be dropped to the right bottom corner
    // </TABLE>
    property ShadowOrientation: TShadowOrientation read FShadowOrientation write SetShadowOrientation default soRightBottom;
    // Specify the control you would like to apply shadow effect to. Can be  any TControl descendnat.
    property ShadowControl: TControl read FShadowControl write SetShadowControl default nil;
    // The size (in pixels)  of the shadow to be painted.
    property ShadowSize: Integer read FShadowSize write SetShadowSize default 10;
    property Color default clBtnShadow;
    property ParentColor;
    property ParentShowHint;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnEndDock;
    {$ENDIF}
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF DELPHI4_OR_ABOVE}
    property OnStartDock;
    {$ENDIF}
    property OnStartDrag;
  end;

  // Event to be fired when the component's buffer is full.
  TBufferFillEvent = procedure(Sender: TObject; Buffer: string) of Object;
  // Event to be fired when the WM_KEYDOWN/WM_KEYUP messages were sent.
  TKeyEventEx = procedure (Sender: TObject; var Key: Word; Shift: TShiftState; var Handled: Boolean) of object;
  // Event to be fired when the WM_CHAR message was sent.
  TKeyPressEventEx = procedure (Sender: TObject; var Key: Char; var Handled: Boolean) of object;
  // Defines the message to be monitored by the TCoolKeyboardSpy component.
  //
  // <TABLE>
  // Value            Meaning
  // ----------       ------------
  // mmKeyDown        Component will monitor the WM_KEYDOWN message.
  // mmKeyUp          Component will monitor the WM_KEYUP message.
  // mmKeyPress       Component will monitor the WM_CHAR message.
  // </TABLE>
  TMonitorMessage = (mmKeyDown, mmKeyUp, mmKeyPress);

  // TCoolKeyboardSpy component can be used to set the global keyboarh hook for
  // application. It can monitor the keyboard related messages in all forms and controls,
  // can inform about the key that was hit, can allow and disallow the particular keys work and
  // can collect user's input in a buffer.
  TCoolKeyboardSpy = class(TComponent)
  private
    FAboutBox: TCCAboutBox;

    FActive: Boolean;

    FOnKeyDown: TKeyEventEx;
    FOnKeyUp: TKeyEventEx;
    FOnKeyPress: TKeyPressEventEx;
    FOnBufferFill: TBufferFillEvent;
    FOnTimeOut: TBufferFillEvent;

    FMonitorMessage: TMonitorMessage;
    FBuffering: Boolean;
    FBuffer: string;

    FStartChar: Char;
    FFinalChar: Char;

    FStartKey: Word;
    FFinalKey: Word;

    FTimer: TTimer;
    function GetTimeOut: Cardinal;
    procedure SetTimeOut(Value: Cardinal);
    procedure TimerTimeOut(Sender: TObject);
  protected
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean); virtual;
  public
    // Run-time and read-only. Read Buffering to determine whether the buffering process ocuurs.
    property Buffering: Boolean read FBuffering;
    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 Active to enable or disable the component's work.
    property Active: Boolean read FActive write FActive default True;
    // Determines the message component will be monitoring. You can se the hook for one
    // of the messages below.
    //
    // <TABLE>
    // Value            Meaning
    // ----------       ------------
    // mmKeyDown        Component will monitor the WM_KEYDOWN message.
    // mmKeyUp          Component will monitor the WM_KEYUP message.
    // mmKeyPress       Component will monitor the WM_CHAR message.
    // </TABLE>
    property MonitorMessage: TMonitorMessage read FMonitorMessage write FMonitorMessage default mmKeyDown;
    // If the \timeout is not equal to 0 when component buffers the input upon elasping the \timeout value
    // \buffering will be terminated.
    property TimeOut: Cardinal read GetTimeOut write SetTimeOut default 0;

    // When MonitorMessage is mmKeyPress use StartChar to specify the character that
    // when hit will start the \buffering process. That is collecting of the user input
    // will be started.
    //
    // See Also:
    //   MonitorMessage
    property StartChar: Char read FStartChar write FStartChar;
    // When MonitorMessage is mmKeyPress use FinalChar to specify the character that
    // when hit will stop the \buffering process. That is collecting of the user input
    // will be finished.
    //
    // See Also:
    //   MonitorMessage
    property FinalChar: Char read FFinalChar write FFinalChar;
    // When MonitorMessage is either mmKeyDown or mmKeyUp use StartKey to specify the key that
    // when hit will start the \buffering process. That is collecting of the user input
    // will be started.
    //
    // See Also:
    //   MonitorMessage
    property StartKey: Word read FStartKey write FStartKey;
    // When MonitorMessage is either mmKeyDown or mmKeyUp use FinalKey to specify the key that
    // when hit will stop the \buffering process. That is collecting of the user input
    // will be finished.
    //
    // See Also:
    //   MonitorMessage
    property FinalKey: Word read FFinalKey write FFinalKey;

    // Event occurs when WM_KEYDOWN message received. Set Handle to True if you
    // do not want the message to be processed, otherwise leave it False.
    property OnKeyDown: TKeyEventEx read FOnKeyDown write FOnKeyDown;
    // Event occurs when WM_KEYUP message received. Set Handle to True if you
    // do not want the message to be processed, otherwise leave it False.
    property OnKeyUp: TKeyEventEx read FOnKeyUp write FOnKeyUp;
    // Event occurs when WM_CHAR message received. Set Handle to True if you
    // do not want the message to be processed, otherwise leave it False.
    property OnKeyPress: TKeyPressEventEx read FOnKeyPress write FOnKeyPress;
    // When \buffering was enabled and either FinalChar or FinalKey was hit use this
    // event to obtain the copy of the user's input.
    //
    // See Also:
    //   MonitorMessage
    //   StartKey
    //   StartChar
    //   FinalKey
    //   FinalChar
    property OnBufferFill: TBufferFillEvent read FOnBufferFill write FOnBufferFill;
    // When \buffering was enabled and timeout elasped use this
    // event to obtain the copy of the user's input.
    //
    // See Also:
    //   MonitorMessage
    //   StartKey
    //   StartChar
    //   FinalKey
    //   FinalChar
    property OnTimeOut: TBufferFillEvent read FOnTimeOut write FOnTimeOut;
  end;

  // TMemoryStreamEx class extands the TMemoryStream with the useful methods.
  TMemoryStreamEx = class(TMemoryStream)
  public
    // Writes Integer value into the stream.
    //
    // Parameters:
    //   Value - Integer to be written into the stream.
    procedure WriteInteger(Value: Integer);
    // Reads Integer value from the stream.
    //
    // Result:
    //   Integer read from the stream.
    function ReadInteger: Integer;
    // Writes Boolean value into the stream.
    //
    // Parameters:
    //   Value - Boolean to be written into the stream.
    procedure WriteBoolean(Value: Boolean);
    // Reads Boolen value from the stream.
    //
    // Result:
    //   Boolean read from the stream.
    function ReadBoolean: Boolean;
    {$IFDEF DELPHI4_OR_ABOVE}
    // Writes String value into the stream.
    //
    // Parameters:
    //   Value - String to be written into the stream.
    procedure WriteString(Value: string); overload;
    // Writes array of char value into the stream.
    //
    // Parameters:
    //   Value - array of char to be written into the stream.
    procedure WriteString(Value: array of Char); overload;
    {$ELSE}
    // Writes String value into the stream.
    //
    // Parameters:
    //   Value - String to be written into the stream.
    procedure WriteString(Value: string);
    // Writes array of char value into the stream.
    //
    // Parameters:
    //   Value - array of char to be written into the stream.
    procedure WriteStringEx(Value: array of Char);
    {$ENDIF}
    // Reads String value from the stream.
    //
    // Result:
    //   String read from the stream.
    function ReadString: string;
  end;

  // TCoolClipboardComponent provides methods to work with the Windows clipboard.
  TCoolClipboardComponent = class(TComponent)
  public
    // Clears the clipboard and 2deletes its contents.
    //
    // Result:
    //   Boolean value indicating function result.
    function ClearClipboard: Boolean;
    // Saves Clipboard contents into the stream.
    //
    // Parameters:
    //   Stream - TMemoryStreamEx object the clipboard will be saved to.
    //   Format - Format of the clipboard's data.
    procedure SaveClipboardToStream(Stream: TMemoryStreamEx; Format: Integer);
    // Saves clipboard's contents into the file.
    //
    // Parameters:
    //   FileName - Name of the file the clipboard's data will be saved to.
    procedure SaveClipboardToFile(FileName: TFileName);
    // Loads clipboard's contents from the stream.
    //
    // Parameters:
    //   Stream - TMemoryStreamEx object the clipboard will be loaded from.
    procedure LoadClipboardFromStream(Stream: TMemoryStreamEx);
    // Loads clipboard's contents from the file.
    //
    // Parameters:
    //   FileName - Name of the file the clipboard's data will be loaded from.
    procedure LoadClipboardFromFile(FileName: TFileName);
  end;

  // TCoolClipboardViewer is the visual control enabled to display the Windows
  // clipboard contents.
  TCoolClipboardViewer = class(TScrollBox)
  private
    FNextWnd: HWND;
    FCurrentViewer: TComponent;
    FOnChange: TNotifyEvent;
    FAboutBox: TCCAboutBox;

    function CreateCurrentViewerComponent(MyClass: TComponentClass): TComponent;
    procedure FreeCurrentViewerComponent;
    procedure RegisterClipboardViewer;
    procedure UnregisterClipboardViewer;

    procedure CenterControl(Control: TControl);

    procedure WMDrawClipboard(var Message: TMessage); message WM_DRAWCLIPBOARD;
    procedure WMChangeCBChain(var Message: TMessage); message WM_CHANGECBCHAIN;
    procedure WMDestroy(var Message: TMessage); message WM_DESTROY;
  protected
    procedure CreateWnd; override;
    procedure DestroyWindowHandle; override;
    procedure WndProc(var Message: TMessage); override;
    // Method used to paint the contents of the clipboard.
    procedure PaintContent; virtual;
  public
    // Clears the clipboard and 2deletes its contents.
    //
    // Result:
    //   Boolean value indicating function result.
    function ClearClipboard: Boolean;
    // Saves Clipboard contents into the stream.
    //
    // Parameters:
    //   Stream - TMemoryStreamEx object the clipboard will be saved to.
    //   Format - Format of the clipboard's data.
    procedure SaveClipboardToStream(Stream: TMemoryStreamEx; Format: Integer);
    // Saves clipboard's contents into the file.
    //
    // Parameters:
    //   FileName - Name of the file the clipboard's data will be saved to.
    procedure SaveClipboardToFile(FileName: TFileName);
    // Loads clipboard's contents from the stream.
    //
    // Parameters:
    //   Stream - TMemoryStreamEx object the clipboard will be loaded from.
    procedure LoadClipboardFromStream(Stream: TMemoryStreamEx);
    // Loads clipboard's contents from the file.
    //
    // Parameters:
    //   FileName - Name of the file the clipboard's data will be loaded from.
    procedure LoadClipboardFromFile(FileName: TFileName);

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    property Color default clWindow;
    property ParentColor default False;
    // Event fired when clipboard's contents is changed.
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  // TCoolTransparentArea control implements transparent areas (holes) in a parent control.
  TCoolTransparentArea = class(TGraphicControl)
  private
    FAboutBox: TCCAboutBox;
    FActive: Boolean;
    FPolygones: TPolygones;
    procedure SetActive(Value: Boolean);
    procedure SetPolygones(Value: TPolygones);
    function GetHandle: THandle;
    procedure SetPolyRegiones;
  protected
    procedure ApplyPolygones; virtual;
    procedure Paint; override;
    procedure Loaded; override;
  public
    // Handle property returns handle of a parent windowed control (if there's one) 
    // otherwise returned value will be 0.
    property Handle: THandle read GetHandle;
    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 Active property to control state of the control. Depending on Active property 
    // value control will or will not display transparent holes in a parent control (form).
    property Active: Boolean read FActive write SetActive default False;
    // Use Polygones to access the collection of the TSinglePolygon object previously created and
    // contained by the control.
    property Polygones: TPolygones read FPolygones write SetPolygones;
  end;

  // TSearchFileThread is thread object that performs search process in a file.
  TSearchFileThread = class(TThread)
  private
    FStringToSearch: string;
    FFileName: string;
    FCaseSensitive: Boolean;
    FStringFound: Boolean;
    FOnStartProcess: TNotifyEvent;
    FOnEndProcess: TNotifyEvent;
    function IsStringFound: Boolean;
  protected
    procedure Execute; override;
  public
    // Run-time and read-only. Indicates whether the specified string was found in the specified file.
    //
    // See Also:
    //   FileName
    property StringFound: Boolean read FStringFound;
    // Run-time and read-only. Name of the file to perform the search in.
    property FileName: string read FFileName;
    // Run-time and read-only. String to be searched in the file.
    //
    // See Also:
    //   FileName
    property StringToSearch: string read FStringToSearch;
    // Run-time and read-only. Determines whether the search will be case sensetive.
    property CaseSensitive: Boolean read FCaseSensitive;
    // Event fired when search process begins.
    property OnStartProcess: TNotifyEvent read FOnStartProcess write FOnStartProcess;
    // Event fired when search process ends.
    property OnEndProcess: TNotifyEvent read FOnEndProcess write FOnEndProcess;
    constructor Create(AFileName, AStringToSearch: string; ACaseSensitive: Boolean);
  end;

  // Defines the folders to be processed.
  //
  // 
  // <TABLE>
  // Value                       Meaning
  // --------------------        -------------------------
  // ssCurrentFolderOnly         Only current folder (One specified in FolderName) will be checked.
  // ssIncludeSubFolders         Current folder and all its subfolders will be processed.
  // </TABLE>     
  TSearchScope = (ssCurrentFolderOnly, ssIncludeSubFolders);
  // Event fired when the folder processed.
  TProcessEvent = procedure(Sender: TObject; CurName: string) of object;

  // TSearchFolderThread is thread object that performs search process in a folder.
  TSearchFolderThread = class(TThread)
  private
    FStringToSearch: string;
    FFolderName: string;
    FFileMask: string;
    FValidFiles: TStringList;
    FCaseSensitive: Boolean;
    FSearchScope: TSearchScope;
    FFileNamesOnly: Boolean;
    FOnFileProcess: TProcessEvent;
    FOnFolderProcess: TProcessEvent;
    FOnFileFound: TProcessEvent;
    FOnStartProcess: TNotifyEvent;
    FOnEndProcess: TNotifyEvent;
    procedure ProcessFolder(DirName: string);
    function IsStringFound(FileName: string): Boolean;
  protected
    procedure Execute; override;
  public
    // Run-time and read-only. Determines whether the search will be case sensetive.
    property CaseSensitive: Boolean read FCaseSensitive;
    // Run-time and read-only. The list of the files that match specified criteria.
    property ValidFiles: TStringList read FValidFiles;
    // Run-time and read-only. Use FolderName to specify the folder that will be browsed for the file.
    property FolderName: string read FFolderName;
    // Run-time and read-only. You may want to limit the files count to these matching the mask given. 
    // Any valid DOS mask acceptable.
    property FileMask: string read FFileMask;
    // Run-time and read-only. Whether we should search the file for the StringToSearch or
    // it's enough that the file name matches the criteria.
    //
    // See Also:
    //   StringToSearch
    property FileNamesOnly: Boolean read FFileNamesOnly write FFileNamesOnly;
    // Use SearhScope to limit the number of folders to be processed:
    // 
    // <TABLE>
    // Value                        Meaning
    // ---------------------        ---------------------------------------- 
    // ssCurrentFolderOnly          Only current folder (One specified in FolderName) will be checked.
    // ssIncludeSubFolders          Current folder and all its subfolders will be processed.
    // </TABLE>
    property SearchScope: TSearchScope read FSearchScope write FSearchScope default ssCurrentFolderOnly;
    // Run-time and read-only. String to be searched in the file.
    property StringToSearch: string read FStringToSearch;
    // Event fired when the file is being searched for the entry.
    property OnFileProcess: TProcessEvent read FOnFileProcess write FOnFileProcess;
    // Event fired when the folder is being searched for the entry.
    property OnFolderProcess: TProcessEvent read FOnFolderProcess write FOnFolderProcess;
    // Event fired when file matching the criteria found.
    property OnFileFound: TProcessEvent read FOnFileFound write FOnFileFound;
    // Event fired when search peocess started.
    property OnStartProcess: TNotifyEvent read FOnStartProcess write FOnStartProcess;
    // Event fired when the search process is over.
    property OnEndProcess: TNotifyEvent read FOnEndProcess write FOnEndProcess;

    constructor Create(AFolderName, AFileMask, AStringToSearch: string; ACaseSensitive: Boolean; ASearchScope: TSearchScope; AFileNamesOnly: Boolean);
    destructor Destroy; override;
  end;

  // TcoolFileFinder does the threaded file search on your disks.
  TCoolFileFinder = class(TComponent)
  private
    FAboutBox: TCCAboutBox;
    FStringToSearch: string;
    FFolderName: string;
    FFileMask: string;
    FCaseSensitive: Boolean;
    FSearchScope: TSearchScope;
    FFileNamesOnly: Boolean;
    FOnFileProcess: TProcessEvent;
    FOnFolderProcess: TProcessEvent;
    FOnFileFound: TProcessEvent;
    FOnStartProcess: TNotifyEvent;
    FOnEndProcess: TNotifyEvent;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function Execute(WaitForEnd: Boolean): Boolean; virtual;
  published
    // Displays information about the control and package version.
    property About: TCCAboutBox read FAboutBox write FAboutBox;
    // Determines whether the search will be case sensetive.
    property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive default False;
    // Use FolderName to specify the folder that will be browsed for the file.
    property FolderName: string read FFolderName write FFolderName;
    // 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 FFileMask;
    // Whether we should search the file for the StringToSearch or
    // it's enough that the file name matches the criteria.
    //
    // See Also:
    //   StringToSearch
    property FileNamesOnly: Boolean read FFileNamesOnly write FFileNamesOnly default False;
    // Use SearhScope to limit the number of folders to be processed:
    // 
    // <TABLE>
    // Value                        Meaning
    // ---------------------        ---------------------------------------- 
    // ssCurrentFolderOnly          Only current folder (One specified in FolderName) will be checked.
    // ssIncludeSubFolders          Current folder and all its subfolders will be processed.
    // </TABLE>
    property SearchScope: TSearchScope read FSearchScope write FSearchScope default ssCurrentFolderOnly;
    // Run-time and read-only. String to be searched in the file.
    property StringToSearch: string read FStringToSearch write FStringToSearch;
    // Event fired when the file is being searched for the entry.
    property OnFileProcess: TProcessEvent read FOnFileProcess write FOnFileProcess;
    // Event fired when the folder is being searched for the entry.
    property OnFolderProcess: TProcessEvent read FOnFolderProcess write FOnFolderProcess;
    // Event fired when file matching the criteria found.
    property OnFileFound: TProcessEvent read FOnFileFound write FOnFileFound;
    // Event fired when search peocess started.
    property OnStartProcess: TNotifyEvent read FOnStartProcess write FOnStartProcess;
    // Event fired when the search process is over.
    property OnEndProcess: TNotifyEvent read FOnEndProcess write FOnEndProcess;
  end;

implementation

{$R CoolClipboard.res}

const
  WM_NOTIFYPARAMSTR =  WM_USER + 400;

type
  {THookList}
  THookList = class(TList)
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  end;

const
  TIMER_INTERVAL =  50;
  DELAY_INTERVAL =   4;
  ICON_ID 	 =   0;
  PARTS_VALUE    =  20;

var
  HookList: THookList;
  PrevHook: HHook;

function CallWindowsHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  Handled: Boolean;
begin
  if Code = HC_ACTION then
  begin
    Handled := wParam = PM_NOREMOVE;
    HookList.AppMessage(PMSG(lParam)^, Handled);
    if Handled then
      GetMessage(PMSG(lParam)^, 0, 0, 0);
  end;
  Result := CallNextHookEx(PrevHook, Code, wParam, lParam);
end;

{THookList}
constructor THookList.Create;
begin
  inherited Create;
  PrevHook := SetWindowsHookEx(WH_GETMESSAGE, CallWindowsHookProc, 0, GetCurrentThreadID);
end;

destructor THookList.Destroy;
begin
  UnhookWindowsHookEx(PrevHook);
  inherited Destroy;
end;

procedure THookList.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
  I: Integer;
begin
  for I := Pred(Count) downto 0 do
    TCoolKeyboardSpy(Items[I]).AppMessage(Msg, Handled);
end;

{TCoolKeyboardSpy}
constructor TCoolKeyboardSpy.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  if not DesignTime(Self) then
  begin
    if not Assigned(HookList) then
      HookList := THookList.Create;

    HookList.Add(Self);
  end;

  FActive := True;
  FMonitorMessage := mmKeyDown;
  FTimer := TTimer.Create(Self);
  FTimer.OnTimer := TimerTimeOut;
  FTimer.Enabled := False;
  TimeOut := 0;
end;

destructor TCoolKeyboardSpy.Destroy;
begin
  if not DesignTime(Self) and Assigned(HookList) then
  begin
    HookList.Remove(Self);
    if HookList.Count = 0 then
    begin
      HookList.Free;
      HookList := nil;
    end;
  end;
  FTimer.Free;
  inherited Destroy;
end;

procedure TCoolKeyboardSpy.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
  Ch: Char;
  Key: Word;
  InBuff: Boolean;

  procedure ProcessKeyDown;
  begin
    if Assigned(FOnKeyDown) then
    begin
      Handled := (Key = StartKey) or (Key = FinalKey);

      FOnKeyDown(Self, Key, CurrentShiftState, Handled);
      Msg.wParam := Key;
    end;
  end;

  procedure ProcessKeyUp;
  begin
    if Assigned(FOnKeyUp) then
    begin
      Handled := (Key = StartKey) or (Key = FinalKey);

      FOnKeyUp(Self, Key, CurrentShiftState, Handled);
      Msg.wParam := Key;
    end;
  end;

  procedure ProcessKeyPress;
  begin
    if Assigned(FOnKeyPress) then
    begin
      Handled := (Ch = StartChar) or (Ch = FinalChar);

      FOnKeyPress(Self, Ch, Handled);
      Msg.wParam := Ord(Ch);
    end;
  end;

begin
  case Msg.Message of
    WM_KEYDOWN:
      begin
        Key := Msg.wParam;
        InBuff := FBuffering;

        if FMonitorMessage <> mmKeyDown then
          ProcessKeyDown else
          if FActive then
          begin
            if not FBuffering then
            begin
              FBuffering := Key = FStartKey;
              ProcessKeyDown;
            end else
            begin
              ProcessKeyDown;
              FBuffering := Key <> FFinalKey;
            end;

            FTimer.Enabled := FBuffering and (TimeOut <> 0);

            if FBuffering and ((Key <> FStartKey) or InBuff)  then
              FBuffer := FBuffer + Chr(Key)
            else
              if FBuffer <> '' then
              begin
                if Assigned(FOnBufferFill) then
                  FOnBufferFill(Self, FBuffer);

                FBuffer := '';
              end;
          end;
      end;
    WM_KEYUP:
      begin
        Key := Msg.wParam;
        InBuff := FBuffering;

        if FMonitorMessage <> mmKeyUp then
          ProcessKeyUp else
          if FActive then
          begin
            if not FBuffering then
            begin
              FBuffering := Key = FStartKey;
              ProcessKeyUp;
            end else
            begin
              ProcessKeyUp;
              FBuffering := Key <> FFinalKey;
            end;

            FTimer.Enabled := FBuffering and (TimeOut <> 0);

            if FBuffering and ((Key <> FStartKey) or InBuff) then
              FBuffer := FBuffer + Chr(Key)
            else
              if FBuffer <> '' then
              begin
                if Assigned(FOnBufferFill) then
                  FOnBufferFill(Self, FBuffer);

                FBuffer := '';
              end;
          end;
      end;
    WM_CHAR:
      begin
        Ch := Chr(Msg.wParam);
        InBuff := FBuffering;

        if FMonitorMessage <> mmKeyPress then
          ProcessKeyPress else
          if FActive then
          begin
            if not FBuffering then
            begin
              FBuffering := Ch = FStartChar;
              ProcessKeyPress;
            end else
            begin
              ProcessKeyPress;
              FBuffering := Ch <> FFinalChar;
            end;

            FTimer.Enabled := FBuffering and (TimeOut <> 0);

            if FBuffering and ((Ch <> FStartChar) or InBuff) then
              FBuffer := FBuffer + Ch
            else
              if FBuffer <> '' then
              begin
                if Assigned(FOnBufferFill) then
                  FOnBufferFill(Self, FBuffer);

                FBuffer := '';
              end;
          end;
      end;
  end;
end;

function TCoolKeyboardSpy.GetTimeOut: Cardinal;
begin
  Result := FTimer.Interval;
end;

procedure TCoolKeyboardSpy.SetTimeOut(Value: Cardinal);
begin
  FTimer.Interval := Value;
end;

procedure TCoolKeyboardSpy.TimerTimeOut(Sender: TObject);
begin
  if Assigned(FOnTimeOut) then
    FOnTimeOut(Self, FBuffer);

  FBuffer := '';
  FBuffering := False;
  FTimer.Enabled := False;
end;

{TCoolDesktop}
constructor TCoolDesktop.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 FRestartType := rwShutdown;
 FDisplayFrequency := df75Hertz;
end;

destructor TCoolDesktop.Destroy;
begin
  inherited Destroy;
end;

function TCoolDesktop.GetWindowsDirectoryValue: TFileName;
var
  buff: array[0..MAX_PATH] of Char;
begin
  GetWindowsDirectory(buff, MAX_PATH);
  Result := buff;
  Result := Result + '\';
end;

function TCoolDesktop.GetSystemDirectoryValue: TFileName;
var
  buff: array[0..MAX_PATH] of Char;
begin
  GetSystemDirectory(buff, MAX_PATH);
  Result := buff;
  Result := Result + '\';
end;

function TCoolDesktop.GetCurrentDirectoryValue: TFileName;
var
  buff: array[0..MAX_PATH] of Char;
begin
  GetCurrentDirectory(MAX_PATH, buff);
  Result := buff;
  Result := Result + '\';
end;

function TCoolDesktop.RestartWindows: Boolean;
var
  Flag: Integer;
begin
  case FRestartType of
    rwForced:   Flag := EWX_FORCE;
    rwLogOff:   Flag := EWX_LOGOFF;
    rwPowerOff: Flag := EWX_POWEROFF;
    rwReboot:   Flag := EWX_REBOOT;
    rwShutdown: Flag := EWX_SHUTDOWN;
    else Flag := 0;
  end;

  Result := ExitWindowsEx(Flag, 0);
end;

function TCoolDesktop.ColorModeToInt(Value: TColorMode): Integer;
begin
  case Value of
    cm4bit: Result := 4;
    cm8bit: Result := 8;
    cm16bit: Result := 16;
    cm24bit: Result := 24;
    cm32bit: Result := 32;
    else Result := -1;
  end;
end;

function TCoolDesktop.IntToColorMode(Value: Integer): TColorMode;
begin
  case Value of
    4 : Result := cm4bit;
    8 : Result := cm8bit;
    16: Result := cm16bit;
    24: Result := cm24bit;
    32: Result := cm32bit;
    else Result := cmError;
  end;
end;

function TCoolDesktop.IntToDisplayFrequency(Value: Integer): TDisplayFrequency;
begin
  case Value of
    56: Result := df56Hertz;
    60: Result := df60Hertz;
    70: Result := df70Hertz;
    72: Result := df72Hertz;
    75: Result := df75Hertz;
    85: Result := df85Hertz;
    90: Result := df90Hertz;
    100: Result := df100Hertz;
    120: Result := df120Hertz;
    else Result := dfError;
  end;
end;

function TCoolDesktop.DisplayFrequencyToInt(Value: TDisplayFrequency): Integer;
begin
  case Value of
    df56Hertz: Result := 56;
    df60Hertz: Result := 60;
    df70Hertz: Result := 70;
    df72Hertz: Result := 72;
    df75Hertz: Result := 75;
    df85Hertz: Result := 85;
    df90Hertz: Result := 90;
    df100Hertz: Result := 100;
    df120Hertz: Result := 120;
    else Result := -1;
  end;
end;

function TCoolDesktop.DisplayResolutionToWidth(Value: TDisplayResolution): Integer;
begin
  case Value of
    dr640x480: Result := 640;
    dr800x600: Result := 800;
    dr1024x768: Result := 1024;
    dr1152x864: Result := 1152;
    dr1280x960: Result := 1280;
    dr1280x1024: Result := 1280;
    else Result := Screen.Width;
  end;
end;

function TCoolDesktop.DisplayResolutionToHeight(Value: TDisplayResolution): Integer;
begin
  case Value of
    dr640x480: Result := 480;
    dr800x600: Result := 600;
    dr1024x768: Result := 768;
    dr1152x864: Result := 864;
    dr1280x960: Result := 960;
    dr1280x1024: Result := 1024;
    else Result := Screen.Height;
  end;
end;

procedure TCoolDesktop.SetDisplayResolution(Value: TDisplayResolution);
var
  DevMode: TDeviceMode;
begin
  if not (csLoading in ComponentState) then
  begin
    if Assigned (FOnDisplaySettingsChange) then
      FOnDisplaySettingsChange(Self);

    DevMode.dmSize := SizeOf(TDeviceMode);
    with DevMode do
    begin
      dmPelsHeight := DisplayResolutionToHeight(Value);
      dmPelsWidth := DisplayResolutionToWidth(Value);
      dmBitsPerPel := ColorModeToInt(ColorMode);
      dmDisplayFrequency := DisplayFrequencyToInt(DisplayFrequency);
      dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFREQUENCY;
    end;
    if ChangeDisplaySettings(DevMode, CDS_TEST) = DISP_CHANGE_SUCCESSFUL then
      ChangeDisplaySettings(DevMode, CDS_UPDATEREGISTRY)
    else
      DisplayResolution := TDisplayResolution(Ord(DisplayResolution) - 1);
  end;
end;

function TCoolDesktop.GetDisplayResolution: TDisplayResolution;
begin
  with Screen do
  begin
    if (Width = 640) and (Height = 480) then
      Result := dr640x480 else
    if (Width = 800) and (Height = 600) then
      Result := dr800x600 else
    if (Width = 1024) and (Height = 768) then
      Result := dr1024x768 else
    if (Width = 1152) and (Height = 864) then
      Result := dr1152x864 else
    if (Width = 1280) and (Height = 960) then
      Result := dr1280x960 else
    if (Width = 1280) and (Height = 1024) then
      Result := dr1280x1024 else
    begin
      raise Exception.Create('Running with unknown display resolution');
      Result := drError;
    end;
  end;
end;

procedure TCoolDesktop.SetColorMode(Value: TColorMode);
var
  DevMode: TDeviceMode;
begin
  if not (csLoading in ComponentState) then
  begin
    if Assigned (FOnDisplaySettingsChange) then
      FOnDisplaySettingsChange(Self);

    DevMode.dmSize := SizeOf(TDeviceMode);
    with DevMode do
    begin
      dmPelsHeight := DisplayResolutionToHeight(DisplayResolution);
      dmPelsWidth := DisplayResolutionToWidth(DisplayResolution);
      dmBitsPerPel := ColorModeToInt(Value);
      dmDisplayFrequency := DisplayFrequencyToInt(DisplayFrequency);
      dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFREQUENCY;
    end;
    if ChangeDisplaySettings(DevMode, CDS_TEST) = DISP_CHANGE_SUCCESSFUL then
      ChangeDisplaySettings(DevMode, CDS_UPDATEREGISTRY)
    else
      ColorMode := TColorMode(Ord(ColorMode) - 1);
  end;
end;

function TCoolDesktop.GetColorMode: TColorMode;
var
  CurMode: Integer;
  ScreenDC: HDC;
begin
  ScreenDC := GetDC(0);
  CurMode := GetDeviceCaps(ScreenDC, BitsPixel);
  ReleaseDC(0, ScreenDC);

  if (CurMode < 4) or (CurMode > 32) then
  begin
    ColorMode := cmError;
    raise Exception.Create('Running in unknown color mode')
  end else
    Result := IntToColorMode(CurMode);
end;

procedure TCoolDesktop.SetDisplayFrequency(Value: TDisplayFrequency);
var
  DevMode: TDeviceMode;
begin
  if not (csLoading in ComponentState) then
  begin
    if Assigned (FOnDisplaySettingsChange) then
      FOnDisplaySettingsChange(Self);

    FDisplayFrequency := Value;
    DevMode.dmSize := SizeOf(TDeviceMode);
    with DevMode do
    begin
      dmPelsHeight := DisplayResolutionToHeight(DisplayResolution);
      dmPelsWidth := DisplayResolutionToWidth(DisplayResolution);
      dmBitsPerPel := ColorModeToInt(ColorMode);
      dmDisplayFrequency := DisplayFrequencyToInt(Value);
      dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFREQUENCY;
    end;
    if ChangeDisplaySettings(DevMode, CDS_TEST) = DISP_CHANGE_SUCCESSFUL then
      ChangeDisplaySettings(DevMode, CDS_UPDATEREGISTRY)
    else
      DisplayFrequency := TDisplayFrequency(Ord(DisplayFrequency) - 1);
  end;
end;

function TCoolDesktop.GetDisplayFrequency: TDisplayFrequency;
begin
  Result := FDisplayFrequency;
end;

function TCoolDesktop.GetFileDirList(FDirectory, Filter: TFileName; Attr: Integer): TStringList;
begin
  Result := CoolUtils.GetFileDirList(FDirectory, Filter, Attr);
end;

function TCoolDesktop.GetDirList(FDirectory, Filter: TFileName; Attr: Integer): TStringList;
var
  I: Integer;
begin
  Result := CoolUtils.GetFileDirList(FDirectory, Filter, Attr);
  try
    if FDirectory[Length(FDirectory)] <> '\' then
      FDirectory := FDirectory + '\';

    for I := Pred(Result.Count) downto 0 do
      if not DirectoryExists(FDirectory + Result[I]) then
        Result.Delete(I);
  except
    Result.Free;
  end;
end;

function TCoolDesktop.GetFileList(FDirectory, Filter: TFileName; Attr: Integer): TStringList;
var
  I: Integer;
begin
  Result := CoolUtils.GetFileDirList(FDirectory, Filter, Attr);
  try
    if FDirectory[Length(FDirectory)] <> '\' then
      FDirectory := FDirectory + '\';

    for I := Pred(Result.Count) downto 0 do
      if not FileExists(FDirectory + Result[I]) then
        Result.Delete(I);
  except
    Result.Free;
  end;
end;

function TCoolDesktop.GetFileNamesOnly(AList: TStringList): TStringList;
var
  Index: Integer;
  TmpStr: string;
begin
  Result := AList;

  for Index := 0 to Result.Count-1 do
  begin
    TmpStr := Result.Strings[Index];
    Result.Delete(Index);
    Result.Insert(Index, ExtractFileName(TmpStr));
  end;
end;

function TCoolDesktop.GetWindowsBitmaps(NamesOnly: Boolean): TStringList;
var
  FBuff: array [0..255] of Char;
begin
  GetWindowsDirectory(FBuff, SizeOf(FBuff));
  Result := GetFileList(FBuff, '*.bmp', faAnyFile);
  if NamesOnly then
    GetFileNamesOnly(Result);
end;

procedure TCoolDesktop.SetWallpaper(AWallpaper: TFileName; ATiled: Boolean);
begin
  with TRegIniFile.Create('') do
  try
    WriteString('Control Panel\Desktop', 'Wallpaper', AWallpaper);
    WriteBool('Control Panel\Desktop', 'TileWallpaper', ATiled);
    SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, PChar(AWallpaper), SPIF_SENDWININICHANGE);
  finally
    Free;
  end;
end;

function TCoolDesktop.GetWallpaper: TFileName;
var
  FBuff: array [0..255] of Char;
begin
  with TRegIniFile.Create('') do
  try
    Result := ReadString('Control Panel\Desktop', 'Wallpaper', '');
    if ExtractFilePath(Result) = '' then
    begin
      GetWindowsDirectory(FBuff, SizeOf(FBuff));
      Result := string(FBuff) + '\' + Result;
    end;
  finally
    Free;
  end;
end;

function TCoolDesktop.GetWallpaperIsTile: Boolean;
begin
  with TRegIniFile.Create('') do
  try
    Result := ReadBool('Control Panel\Desktop', 'TileWallpaper', True);
  finally
    Free;
  end;
end;

function TCoolDesktop.GetPatterns: TStringList;
var
  FBuff: array [0..255] of Char;
begin
  Result := TStringList.Create;
  try
    GetWindowsDirectory(FBuff, SizeOf(FBuff));
    with TIniFile.Create(FBuff + '\control.ini') do
    try
      ReadSection('Patterns', Result);
    finally
      Free;
    end;
  except
    Result.Free;
  end;
end;

procedure TCoolDesktop.SetPattern(APattern: string);
var
  FIniFile: TIniFile;
  FRegFile: TRegIniFile;
  FBuff: array [0..255] of Char;
begin
  GetWindowsDirectory(FBuff, SizeOf(FBuff));
  FIniFile := TIniFile.Create(FBuff + '\control.ini');
  try
    APattern := FIniFile.ReadString('Patterns', APattern, '');

    FRegFile := TRegIniFile.Create('');
    try
      FRegFile.WriteString('Control Panel\Desktop', 'Pattern', APattern);
      SystemParametersInfo(SPI_SETDESKPATTERN, 0, PChar(APattern), SPIF_SENDWININICHANGE);
    finally
      FRegFile.Free;
    end;

  finally
    FIniFile.Free;
  end;
end;

function TCoolDesktop.GetPattern: string;
var
  FIniFile: TIniFile;
  FRegFile: TRegIniFile;
  FBuff: array [0..255] of Char;
  FList: TStringList;
  FCurrentPattern: string;
  Index: Integer;
begin
  FList := TStringList.Create;
  try
    GetWindowsDirectory(FBuff, SizeOf(FBuff));

    FIniFile := TIniFile.Create(FBuff + '\control.ini');
    try
      FIniFile.ReadSectionValues('Patterns', FList);

      FRegFile := TRegIniFile.Create('');
      try
        FCurrentPattern := FRegFile.ReadString('Control Panel\Desktop', 'Pattern', '');

        for Index := 0 to FList.Count-1 do
          if Pos(FCurrentPattern, FList.Strings[Index]) <> 0 then
          begin
            Result := Copy(FList.Strings[Index], 0, Pos('=', FList.Strings[Index])-1);
            break;
          end;

      finally
        FRegFile.Free;
      end;

    finally
      FIniFile.Free;
    end;

  finally
    FList.Free;
  end;
end;

function TCoolDesktop.GetShellFolders: TStringList;
begin
  Result := TStringList.Create;
  try
    with TRegIniFile.Create('') do
    try
      ReadSectionValues('Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders', Result);
    finally
      Free;
    end;
  except
    Result.Free;
  end;
end;

{$IFNDEF ver90}
procedure TCoolDesktop.SetFile(AFileName, AFolder, AParam, AName: string);
var
  MyObject: IUnknown;
  MySLink: IShellLink;
  MyPFile: IPersistFile;
  WFileName: WideString;
begin
  MyObject := CreateComObject(CLSID_ShellLink);
  MySLink := MyObject as IShellLink;
  MyPFile := MyObject as IPersistFile;

  with MySLink do
  begin
    SetArguments(PChar(AParam));
    SetPath(PChar(AFileName));
    SetWorkingDirectory(PChar(AFolder));
  end;

  WFileName := AFolder + '\' + AName;
  MyPFile.Save(PWChar(WFileName), False);
end;

procedure TCoolDesktop.SetDesktopFile(AFileName, AParam, AName: string);
begin
  with TRegIniFile.Create('') do
  try
    SetFile(AFileName, ReadString('Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders', 'Desktop', ''), AParam, AName);
  finally
    Free;
  end;
end;

procedure TCoolDesktop.SetFavoritesFile(AFileName, AParam, AName: string);
begin
  with TRegIniFile.Create('') do
  try
    SetFile(AFileName, ReadString('Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders', 'Favorites', ''), AParam, AName);
  finally
    Free;
  end;
end;

function TCoolDesktop.GetDesktopDirectory: TFileName;
var
  PIDL: PItemIDList;
  Path: LPSTR;
begin
  Path := StrAlloc(MAX_PATH);
  try
    SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, PIDL);
    if SHGetPathFromIDList(PIDL, Path) then
      Result := string(Path) + '\';
  finally
    StrDispose(Path);
  end;
end;

function StrRetToString(Name: TStrRet; pidl: PItemIDList): string;
begin
  case Name.uType of
    STRRET_CSTR: Result := Name.cStr;
    STRRET_OFFSET: Result:= StrPas(PChar(pidl) + Name.UOffset);
    STRRET_WSTR: Result := Name.pOleStr;
  end;
end;

function TCoolDesktop.GetDesktopFiles: TStringList;
var
  ppFolder: IShellFolder;
  ppList: IEnumIdList;
  NextIDList: PItemIDList;
  IDFetched: ULONG;
  Name: TStrRet;
begin
  Result := TStringList.Create;
  try
    SHGetDesktopFolder(ppFolder);
    ppFolder.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN or SHCONTF_NONFOLDERS, ppList);
    while ppList.Next(1, NextIDList, IDFetched) = S_OK do
    begin
      ppFolder.GetDisplayNameOf(NextIDList, SHGDN_NORMAL, Name);
      Result.Add(StrRetToString(Name, NextIDList));
    end;
  except
    Result.Free;
  end;
end;

function TCoolDesktop.DeleteDesktopFile(AFileDesc: string): Boolean;
var
  ppFolder: IShellFolder;
  ppList: IEnumIdList;
  NextIDList: PItemIDList;
  IDFetched: ULONG;
  Name: TStrRet;

  MyObject: IUnknown;
  MySLink: IShellLink;

  Data: TWin32FindData;
  Buff: array [0..255] of Char;
begin
  Result := False;
  SHGetDesktopFolder(ppFolder);
  ppFolder.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN or SHCONTF_NONFOLDERS, ppList);
  while ppList.Next(1, NextIDList, IDFetched) = S_OK do
  begin
    ppFolder.GetDisplayNameOf(NextIDList, SHGDN_NORMAL, Name);
    if StrRetToString(Name, NextIDList) = AFileDesc then
    begin
      MyObject := CreateComObject(CLSID_ShellLink);
      MySLink := MyObject as IShellLink;

      MySLink.SetIDList(NextIDList);
      MySLink.GetPath(Buff, SizeOf(Buff), Data, SLGP_UNCPRIORITY);
      Result := DeleteFile(Buff);
      Break;
    end;
  end;
end;
{$ENDIF}

function TCoolDesktop.OpenFile(AFileName: TFileName): Boolean;
begin
  Result := ShellExecute(GetDesktopWindow(), 'open', PChar(AFileName), nil, nil, SW_SHOWNORMAL) > 32;
end;

procedure TCoolDesktop.SetStartupProgram(ATitle, ACmdLine: string; AOnce: Boolean);
begin
  with TRegIniFile.Create('') do
  try
    RootKey := HKEY_LOCAL_MACHINE;
    if AOnce then
      WriteString('Software\Microsoft\Windows\CurrentVersion\RunOnce', ATitle, ACmdLine) else
        WriteString('Software\Microsoft\Windows\CurrentVersion\Run', ATitle, ACmdLine);
  finally
    Free;
  end;
end;

procedure TCoolDesktop.DeleteStartupProgram(ATitle: string; AIsOnce: Boolean);
begin
  with TRegIniFile.Create('') do
  try
    RootKey := HKEY_LOCAL_MACHINE;
    if AIsOnce then
      DeleteKey('Software\Microsoft\Windows\CurrentVersion\RunOnce', ATitle) else
        DeleteKey('Software\Microsoft\Windows\CurrentVersion\Run', ATitle);
  finally
    Free;
  end;
end;

procedure TCoolDesktop.RegisterFileType(AExtension, ATitle, ACmdLine: string);
begin
  with TRegIniFile.Create('') do
  try
    RootKey := HKEY_CLASSES_ROOT;
    WriteString(AExtension, '', Copy(AExtension, 2, Length(AExtension)) + 'file');
    WriteString(Copy(AExtension, 2, Length(AExtension)) + 'file', '', ATitle);
    WriteString(Copy(AExtension, 2, Length(AExtension)) + 'file\Shell\Open\Command', '', ACmdLine + ' %1');
  finally
    Free;
  end;
end;

procedure TCoolDesktop.UnRegisterFileType(AExtension: string);
begin
  with TRegIniFile.Create('') do
  try
    RootKey := HKEY_CLASSES_ROOT;
    EraseSection(AExtension);
    EraseSection(Copy(AExtension, 2, Length(AExtension)) + 'file');
  finally
    Free;
  end;
end;

function TCoolDesktop.ExecuteApp(FAppName: TFileName; FAppParams: string): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  FillChar(StartupInfo, Sizeof(StartupInfo), #0);
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_SHOWNORMAL;

  Result := CreateProcess(nil,
                          PChar(FAppName + ' ' + FAppParams),
                          nil,
                          nil,
                          False,
                          CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
                          nil,
                          nil,
                          StartupInfo,
                          ProcessInfo);
end;

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

  FWindowHook := TWndHook.Create(Self);
  FWindowHook.OnBeforeMessage := BeforeMessage;
  FWindowHook.OnAfterMessage := AfterMessage;
  FWindowHook.OnChangeWinControl := ChangeControl;

  FTimer := TTimer.Create(Self);
  FTimer.Enabled := False;
  FTimer.Interval := TIMER_INTERVAL;
  FTimer.OnTimer := TimeredAction;
end;

destructor TCoolLocker.Destroy;
begin
  Options := [];
  FWindowHook.Free;
  FTimer.Free;
  inherited Destroy;
end;

procedure TCoolLocker.SetFlags(Value: TLockerOptions);
const
  Visibles: array[Boolean] of Integer = (SW_SHOW, SW_HIDE);
  Exists: array[Boolean] of Integer = (WM_USER, WM_CLOSE);
  Topmosts: array[Boolean] of THandle = (HWND_NOTOPMOST, HWND_TOPMOST);
var
  R: TRect;
  OldVal: LongInt;
begin
  if not (csDesigning in ComponentState) then
  begin
    //Task bar visible
    if not (loTaskBarAutoHide in Value) then
      ShowWindow(FindWindow('Shell_TrayWnd', nil), Visibles[loHideTaskBar in Value]);

    //Start button visible
    ShowWindow(FindWindowEx(FindWindow('Shell_TrayWnd', nil), 0, 'Button', ''), Visibles[loHideStartBtn in Value]);

    //Start button exists
    SendMessage(FindWindowEx(FindWindow('Shell_TrayWnd', nil), 0, 'Button', ''), Exists[loPreventStartBtnExisting in Value], 0, 0);

    //Program Manager
    ShowWindow(FindWindow('Progman', nil), Visibles[loHideProgman in Value]);
    if loHideProgman in Value then
      PostMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);

    //Timer...
    FTimer.Enabled := (loPreventCursorLoosing in Value) or (loTaskBarAutoHide in Value);

    //System keys
    if Win32Platform <> VER_PLATFORM_WIN32_NT then
      SystemParametersInfo(SPI_SCREENSAVERRUNNING, Word(loPreventSystemKeysWork in Value), @OldVal, SPIF_SENDWININICHANGE) else
        if loPreventSystemKeysWork in Value then
          RegisterHotKey(Application.Handle, SPI_SCREENSAVERRUNNING, MOD_ALT, VK_TAB) else
            UnregisterHotKey(Application.Handle, SPI_SCREENSAVERRUNNING);

    //Top most window
    if Assigned(Form) and Form.HandleAllocated then
      SetWindowPos(Form.Handle, Topmosts[loAlwaysOnTopPosition in Value], 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);

    //Cursor routine
    if (loPreventCursorLoosing in Value) and Assigned(Form) then
    begin
      GetWindowRect(Form.Handle, R);
      ClipCursor(@R);
    end else
    begin
      R := Rect(0, 0, Screen.Width, Screen.Height);
      ClipCursor(@R);
    end;

    //AutoHide sets client area...
    if (loTaskBarAutoHide in Value) then
    begin
      R := Rect(0, 0, Screen.Width, Screen.Height);
      SystemParametersInfo(SPI_SETWORKAREA, 0, @R, SPIF_UPDATEINIFILE);
    end else
    begin
      GetWindowRect(FindWindow('Shell_TrayWnd', nil), R);
      SubtractRect(R, Rect(0, 0, Screen.Width, Screen.Height), R);
      SystemParametersInfo(SPI_SETWORKAREA, 0, @R, SPIF_UPDATEINIFILE);
    end;
  end;
end;

procedure TCoolLocker.SetEnabled(Value: Boolean);
begin
  if FEnabled <> Value then
  begin
    FEnabled := Value;

    if FEnabled then
      SetFlags(FOptions) else
      SetFlags([]);
  end;
end;

procedure TCoolLocker.SetOptions(Value: TLockerOptions);
begin
  if FEnabled then
    SetFlags(Value);

  FOptions := Value;
end;

procedure TCoolLocker.Loaded;
begin
  inherited Loaded;
  //For a while... Gotta be fixed later.
  FWindowHook.WinControl := TWinControl(Owner);
  FWindowHook.Active := True;

  SetFlags(FOptions);
end;

procedure TCoolLocker.TimeredAction(Sender: TObject);

  function StartMenuActive: Boolean;
  var
    MENUCLASS_ID: PChar;
    OsVersionInfo: TOsVersionInfo;
  begin
    OsVersionInfo.dwOsVersionInfoSize := SizeOf(TOsVersionInfo);
    GetVersionEx(OsVersionInfo);
    with OsVersionInfo do
      if (dwMinorVersion = 10) and
         (dwMajorVersion = 4) and
         (dwPlatformId = VER_PLATFORM_WIN32_WINDOWS) then
               MENUCLASS_ID := 'BaseBar' else
               MENUCLASS_ID := '#32768';

    {$IFDEF DELPHI4_OR_ABOVE}
    Result := IsWindowVisible(FindWindow(MENUCLASS_ID, nil));
    {$ELSE}
    Result := (GetWindow(FindWindow(MENUCLASS_ID, nil), GW_OWNER) = 0) and IsWindowVisible(FindWindow(MENUCLASS_ID, nil));
    {$ENDIF}
  end;

var
  P: TPoint;
  R: TRect;
  ForeWND: THandle;
begin
  ForeWND := GetForegroundWindow;

  {Cursor and System modal routine}
  if (loPreventCursorLoosing in FOptions) and Assigned(Form) then
    if (ForeWND = Form.Handle) or (loAlwaysOnTopPosition in FOptions) then
    begin
      GetWindowRect(Form.Handle, R);
      ClipCursor(@R);
    end else
    begin
      R := Rect(0, 0, Screen.Width, Screen.Height);
      ClipCursor(@R);
    end;

  {Taskbar auto hide}
  if (loTaskBarAutoHide in FOptions) then
  begin
    GetCursorPos(P);
    GetWindowRect(FindWindow('Shell_TrayWnd', nil), R);

    if PtInRect(R, P) then
    begin
      //We're in taskbar area and it isn't visible so we must show it.
      if not IsWindowVisible(FindWindow('Shell_TrayWnd', nil)) then
        SetWindowPos(FindWindow('Shell_TrayWnd', nil), HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
    end else
    begin
      //We're not in taskbar area but it still visible so we must hide it.
      if IsWindowVisible(FindWindow('Shell_TrayWnd', nil)) and not StartMenuActive then
        SetWindowPos(FindWindow('Shell_TrayWnd', nil), HWND_TOPMOST, 0, 0, 0, 0, SWP_HIDEWINDOW or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE) else
          if StartMenuActive then
            SetWindowPos(FindWindow('Shell_TrayWnd', nil), HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
    end;
  end;
end;

procedure TCoolLocker.BeforeMessage(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
begin
  Handled := False;

  if Assigned(Form) and Form.HandleAllocated then
  try
    case Msg.msg of

      //no way to minimize from task bar
      WM_SHOWWINDOW:
        if FEnabled then
          with TWMShowWindow(Msg) do
            if (loPreventAppMinimizing in FOptions) and (Status <> 0) then
              Show := True;

      //no way to minimize from system menu/button
      WM_SYSCOMMAND:
        if FEnabled then
          with TWMSysCommand(Msg) do
            if ((CmdType = SC_MINIMIZE) and (loPreventAppMinimizing in FOptions)) or ((CmdType = SC_CLOSE) and (loPreventAppClosing in FOptions)) then
              CmdType := 0;

    end;
  except
    Application.HandleException(Self);
  end;
end;

procedure TCoolLocker.AfterMessage(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
begin
end;

procedure TCoolLocker.ChangeControl(Sender: TObject);
begin
  Form := TCoolForm(Sender);
end;

{TCoolCapture}
constructor TCoolCapture.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCaptureObject := coClipboard;
  FCaptureSize := csDefault;
  FWindowHandle := 0;
  FFileName := '';
  FBuffer := TBitmap.Create;
  FZoomRatio := 100;
  FCopyMode := cmSrcCopy;
end;

destructor TCoolCapture.Destroy;
begin
  FBuffer.Free;
  inherited Destroy;
end;

procedure TCoolCapture.SetZoomRatio(Value: Cardinal);
begin
  if FZoomRatio <> Value then
  begin
    FZoomRatio := Value;
    if FZoomRatio = 0 then
      Inc(FZoomRatio);
  end;
end;

procedure TCoolCapture.Capture;
var
  ImageDC: HDC;
  MyFormat: Word;
  AData: THandle;
  APalette: HPALETTE;
begin
  ImageDC := GetWindowDC(FWindowHandle);
  with FBuffer do
  try
    // If Default then whole window...
    if FCaptureSize = csDefault then
      GetWindowRect(FWindowHandle, FCaptureRect);

    with FCaptureRect do
    begin
      // If Default then adjust sizes...
      if FCaptureSize = csDefault then
        if GetWindowLong(FWindowHandle, GWL_STYLE) and WS_MAXIMIZE <> 0 then
          SetRect(FCaptureRect, Abs(Left), Abs(Top), Abs(Right), Abs(Bottom)) else
            OffsetRect(FCaptureRect, -Left, -Top);

      // Dimensions of our bitmap.
      Width := Round((Right - Left) / 100 * FZoomRatio);
      Height := Round((Bottom - Top) / 100 * FZoomRatio);

      // Some background...
      FillRect(Canvas.Handle, Rect(0, 0, Width, Height), GetStockObject(BLACK_BRUSH));

      StretchBlt(Canvas.Handle, 0, 0, Width, Height, ImageDC, Left, Top, Right - Left, Bottom - Top, FCopyMode);
    end;

    case FCaptureObject of
      coFile:
        SaveToFile(FFileName);
      coClipboard:
        begin
          SaveToClipBoardFormat(MyFormat, AData, APalette);
          ClipBoard.SetAsHandle(MyFormat, AData)
        end;
      coDevice:
        BitBlt(FDeviceContext,
               FDeviceRect.Left, FDeviceRect.Top, FDeviceRect.Right - FDeviceRect.Left, FDeviceRect.Bottom - FDeviceRect.Top,
               Canvas.Handle,
               0, 0, SRCCOPY);
    end;
  finally
    ReleaseDC(FWindowHandle, ImageDC);
  end;
end;

{TCoolLoupe}
constructor TCoolLoupe.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FTimer := TTimer.Create(Self);
  FTimer.OnTimer := TimerEvent;

  FCoolCapture := TCoolCapture.Create(Self);

  FActive := False;
  FInterval := 100;
  FZoomRatio := 100;
  FCopyMode := cmSrcCopy;
  FLoupeType := ltDynamic;

  FBevelInner := bvNone;
  FBevelOuter := bvNone;

  SetBounds(Left, Top, 100, 100);
  UpdateTimer;
end;

destructor TCoolLoupe.Destroy;
begin
  FTimer.Free;
  FCoolCapture.Free;
  inherited Destroy;
end;

procedure TCoolLoupe.SetZoomRatio(Value: Cardinal);
begin
  if FZoomRatio <> Value then
  begin
    FZoomRatio := Value;
    if FZoomRatio = 0 then
      Inc(FZoomRatio);
  end;
end;

procedure TCoolLoupe.SetActive(Value: Boolean);
begin
  if FActive <> Value then
  begin
    FActive := Value;
    UpdateTimer;
    Invalidate;
  end;
end;

procedure TCoolLoupe.SetInterval(Value: Cardinal);
begin
  if FInterval <> Value then
  begin
    FInterval := Value;
    UpdateTimer;
    Invalidate;
  end;
end;

procedure TCoolLoupe.SetBevelInner(Value: TPanelBevel);
begin
  if FBevelInner <> Value then
  begin
    FBevelInner := Value;
    Invalidate;
  end;
end;

procedure TCoolLoupe.SetBevelOuter(Value: TPanelBevel);
begin
  if FBevelOuter <> Value then
  begin
    FBevelOuter := Value;
    Invalidate;
  end;
end;

procedure TCoolLoupe.TimerEvent(Sender: TObject);
var
  P: TPoint;
  R: TRect;
  Offset: Real;
begin
  with FCoolCapture do
  begin
    R := ClientRect;
    InflateRect(R, -2, -2);

    WindowHandle := GetDesktopWindow;
    DeviceContext := Canvas.Handle;
    DeviceRect := R;
    ZoomRatio := Self.FZoomRatio;
    CopyMode := Self.FCopyMode;

    case FLoupeType of
      ltDynamic:
        GetCursorPos(P);
      ltStatic:
        P := FLoupePosition;
    end;

    Offset := 2 * (ZoomRatio / 100);
    CaptureObject := coDevice;
    CaptureSize := csCustom;
    CaptureRect := Rect(P.X - Round(Width / Offset),
                        P.Y - Round(Height / Offset),
                        P.X + Round(Width / Offset),
                        P.Y + Round(Height / Offset));
    Capture;

    if Assigned(FOnTotalMouseMove) then
      FOnTotalMouseMove(Self, [], P.X, P.Y);
  end;
end;

procedure TCoolLoupe.UpdateTimer;
begin
  FTimer.Interval := FInterval;
  FTimer.Enabled := (FInterval > 0) and FActive;
end;

procedure TCoolLoupe.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
end;

procedure TCoolLoupe.Paint;
const
  {$IFDEF DELPHI4_OR_ABOVE}
  FInnerEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER, 0);
  FOuterEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER, 0);
  {$ELSE}
  FInnerEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER);
  FOuterEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER);
  {$ENDIF}
var
  R: TRect;
begin
  inherited Paint;
  R := ClientRect;

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

  {$IFDEF DELPHI4_OR_ABOVE}
  if not ((FBevelInner in [bvNone, bvSpace]) and (FBevelOuter in [bvNone, bvSpace])) then
  {$ELSE}
  if not ((FBevelInner = bvNone) and (FBevelOuter = bvNone)) then
  {$ENDIF}
    DrawEdge(Canvas.Handle, R, FInnerEdges[FBevelInner] or FOuterEdges[FBevelOuter], BF_RECT);
end;

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

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

{TCoolLoupePolygones}
constructor TCoolLoupePolygones.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FActive := False;

  SetBounds(Left, Top, 100, 100);

  FCoolLoupe := TCoolLoupe.Create(Self);
  FCoolLoupe.Align := alClient;
  FCoolLoupe.Parent := Self;

  FActive := False;

  FPolygones := TPolygones.Create(Self);
end;

destructor TCoolLoupePolygones.Destroy;
begin
  FCoolLoupe.Free;
  FPolygones.Free;
  inherited Destroy;
end;

procedure TCoolLoupePolygones.SetActive(Value: Boolean);
begin
  if FActive <> Value then
  begin
    FActive := Value;
    FCoolLoupe.Active := Value;
    ApplyPolygones;
  end;
end;

procedure TCoolLoupePolygones.SetCopyMode(Value: TCopyMode);
begin
  FCoolLoupe.CopyMode := Value;
end;

function TCoolLoupePolygones.GetCopyMode: TCopyMode;
begin
  Result := FCoolLoupe.CopyMode;
end;

procedure TCoolLoupePolygones.SetInterval(Value: Cardinal);
begin
  FCoolLoupe.Interval := Value;
end;

function TCoolLoupePolygones.GetInterval: Cardinal;
begin
  Result := FCoolLoupe.Interval;
end;

procedure TCoolLoupePolygones.SetZoomRatio(Value: Cardinal);
begin
  FCoolLoupe.ZoomRatio := Value;
end;

function TCoolLoupePolygones.GetZoomRatio: Cardinal;
begin
  Result := FCoolLoupe.ZoomRatio;
end;

function TCoolLoupePolygones.GetLoupeType: TLoupeType;
begin
  Result := FCoolLoupe.LoupeType;
end;

procedure TCoolLoupePolygones.SetLoupeType(Value: TLoupeType);
begin
  FCoolLoupe.LoupeType := Value;
end;

function TCoolLoupePolygones.GetLoupePosition: TPoint;
begin
  Result := FCoolLoupe.LoupePosition;
end;

procedure TCoolLoupePolygones.SetLoupePosition(Value: TPoint);
begin
  FCoolLoupe.LoupePosition := Value;
end;

procedure TCoolLoupePolygones.SetPolygones(Value: TPolygones);
begin
  FPolygones.Assign(Value);
  ApplyPolygones;
end;

procedure TCoolLoupePolygones.SetPolyRegiones;
var
  PointsArray: array [0..MaxWord] of TPoint;
  Verteces: array [0..MaxWord] of Integer;
  Rgn: HRGN;
  I,K,N: Integer;
begin
  if FPolygones.Count <> 0 then
  begin
    N := 0;
    for I := 0 to Pred(FPolygones.Count) do
    begin
      Verteces[I] := FPolygones[I].Points.Count;
      for K := 0 to Pred(FPolygones[I].Points.Count) do
      begin
        PointsArray[N + K] := FPolygones[I].Points[K];
      end;
      N := N + Verteces[I];
    end;

    Rgn := CreatePolyPolygonRgn(PointsArray, Verteces, FPolygones.Count, ALTERNATE);
    SetWindowRgn(Handle, Rgn, True);
    DeleteObject(Rgn);
  end;
end;

procedure TCoolLoupePolygones.ApplyPolygones;
begin
  if FActive then
    SetPolyRegiones else
      SetWindowRgn(Handle, 0, True);
end;

procedure TCoolLoupePolygones.Loaded;
begin
  inherited Loaded;
  ApplyPolygones;
end;

procedure TCoolLoupePolygones.Paint;
begin
  inherited Paint;
end;

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

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

{TCoolWindowsInformant}
constructor TCoolWindowsInformant.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FWinList := TList.Create;
  FParentHandle := 0;
  FHandle := AllocateHWnd(WndProc);
  FInterval := 1000;
  FTimered := False;
end;

destructor TCoolWindowsInformant.Destroy;
begin
  ClearList;
  FWinList.Free;
  Timered := False;
  DeallocateHWnd(FHandle);
  inherited Destroy;
end;

procedure TCoolWindowsInformant.Loaded;
begin
  inherited Loaded;
end;

procedure TCoolWindowsInformant.SetTimered(Value: Boolean);
begin
  if FTimered <> Value then
  begin
    FTimered := Value;
    UpdateTimer;
  end; 
end;

procedure TCoolWindowsInformant.SetInterval(Value: Cardinal);
begin
  if FInterval <> Value then
  begin
    FInterval := Value;
    UpdateTimer;
  end;
end;

function TCoolWindowsInformant.GetWindow(Index: Integer): PWindowInfo;
begin
  if (Index >= 0) and (Index <= Pred(FWinList.Count)) then
    Result := FWinList[Index] else
      Result := nil;
end;

function TCoolWindowsInformant.GetCount: Integer;
begin
  Result := FWinList.Count;
end;

procedure TCoolWindowsInformant.ClearList;
var
  I: Integer;
begin
  for I := Pred(FWinList.Count) downto 0 do
  begin
    FreeMem(FWinList[I], SizeOf(TWindowInfo));
    FWinList.Delete(I);
  end;
end;

procedure TCoolWindowsInformant.UpdateTimer;
begin
  KillTimer(FHandle, 0);
  if (FInterval <> 0) and FTimered then
    if SetTimer(FHandle, 0, FInterval, nil) = 0 then
      raise EOutOfResources.Create('Not enough timers available');
end;

function EnumProc(H: HWND; Info: Pointer): BOOL; stdcall;
var
  WindowInfo: PWindowInfo;
begin
  Result := True;
  with TCoolWindowsInformant(Info) do
  begin
    GetMem(WindowInfo, SizeOf(TWindowInfo));
    CertainWindowInfo(H, WindowInfo);
    FWinList.Add(WindowInfo);
  end;
end;

procedure TCoolWindowsInformant.UpdateWindows;
begin
  if Assigned(FOnWindowsUpdating) then
    FOnWindowsUpdating(Self);

  ClearList;

  if FParentHandle = 0 then
    EnumWindows(@EnumProc, Longint(Self)) else
      EnumChildWindows(FParentHandle, @EnumProc, Longint(Self));

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

procedure TCoolWindowsInformant.CertainWindowInfo(AHandle: THandle; var AInfo: PWindowInfo);
begin
  with AInfo^ do
  begin
    //Initial values
    wTitle := '';
    wClassName := '';
    wWindowRect := Rect(0, 0, 0, 0);
    wClientRect := Rect(0, 0, 0, 0);
    wStyle := 0;
    wExStyle := 0;
    wEnabled := False;
    wVisible := False;
    wMaximized := False;
    wMinimized := False;

    //Real values
    wHandle := AHandle;

    FillChar(wClassName, SizeOf(wClassName), #0);
    GetClassName(wHandle, wClassName, SizeOf(wClassName));

    FillChar(wTitle, SizeOf(wTitle), #0);
    GetWindowText(wHandle, wTitle, SizeOf(wTitle));

    GetWindowRect(wHandle, wWindowRect);
    GetClientRect(wHandle, wClientRect);

    wStyle := GetWindowLong(wHandle, GWL_STYLE);
    wExStyle := GetWindowLong(wHandle, GWL_EXSTYLE);

    wEnabled := IsWindowEnabled(wHandle);
    wVisible := IsWindowVisible(wHandle);
    wMaximized := IsZoomed(wHandle);
    wMinimized := IsIconic(wHandle);
  end;
end;

procedure TCoolWindowsInformant.WndProc(var Msg: TMessage);
begin
  with Msg do
    if Msg = WM_TIMER then
      try
        UpdateWindows;
      except
        Application.HandleException(Self);
      end
    else
      Result := DefWindowProc(FHandle, Msg, wParam, lParam);
end;

{TCoolTrayIcon}
constructor TCoolTrayIcon.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FImageChangeLink := TChangeLink.Create;
  FImageChangeLink.OnChange := IconsChange;

  FHandle := AllocateHWnd(WndProc);

  FIcon := TIcon.Create;
  FIcon.OnChange := IconChange;

  FActive := False;
  FAnimated := False;
  FToolTip := '';
  FInterval := 200;
  FIconIndex := 0;
  FOwnerDrawMenu := False;
  FPreview := False;
end;

destructor TCoolTrayIcon.Destroy;
begin
  Active := False;
  FImageChangeLink.Free;
  DeallocateHWnd(FHandle);
  FIcon.Free;
  inherited Destroy;
end;

procedure TCoolTrayIcon.SetActive(Value: Boolean);
begin
  if FActive <> Value then
  begin
    FActive := Value;
    UpdateTimer;
    UpdateIcon;
  end;
end;

procedure TCoolTrayIcon.SetAnimated(Value: Boolean);
begin
  if FAnimated <> Value then
  begin
    FAnimated := Value;
    UpdateTimer;
    UpdateIcon;
  end;
end;

procedure TCoolTrayIcon.SetIcon(Value: TIcon);
begin
  if FIcon <> Value then
    FIcon.Assign(Value);
end;

procedure TCoolTrayIcon.SetToolTip(Value: string);
begin
  if Length(Value) > 63 then
    SetLength(Value, 63);

  if FToolTip <> Value then
  begin
    FToolTip := Value;
    UpdateTimer;
    UpdateIcon;
  end;
end;

procedure TCoolTrayIcon.SetIcons(Value: TImageList);
begin
  if Assigned(Icons) then
    Icons.UnRegisterChanges(FImageChangeLink);

  FIcons := Value;

  if Assigned(Icons) then
    Icons.RegisterChanges(FImageChangeLink);

  UpdateTimer;
  UpdateIcon;
end;

procedure TCoolTrayIcon.SetInterval(Value: Cardinal);
begin
  if FInterval <> Value then
  begin
    FInterval := Value;
    UpdateTimer;
    UpdateIcon;
  end;
end;

procedure TCoolTrayIcon.SetPopupMenu(Value: TPopupMenu);
begin
  if FPopupMenu <> Value then
    FPopupMenu := Value;
end;

procedure TCoolTrayIcon.SetPreview(Value: Boolean);
begin
  if FPreview <> Value then
  begin
    FPreview := Value;
    UpdateTimer;
    UpdateIcon;
  end;
end;

function TCoolTrayIcon.GetPreview: Boolean;
begin
  Result := not (csDesigning in ComponentState);
  if not Result then
    Result := FPreview;
end;

procedure TCoolTrayIcon.IconChange(Sender: TObject);
begin
  UpdateTimer;
  UpdateIcon;
end;

procedure TCoolTrayIcon.IconsChange(Sender: TObject);
begin
  UpdateTimer;
  UpdateIcon;
end;

procedure TCoolTrayIcon.UpdateTimer;
begin
  KillTimer(FHandle, 1);
  if (FInterval <> 0) and FActive and FAnimated and Assigned(FIcons) then
    if SetTimer(FHandle, 1, FInterval, nil) = 0 then
      raise EOutOfResources.Create('Low resources');
end;

procedure TCoolTrayIcon.UpdateIcon;
var
  IconData: TNotifyIconData;
begin
  with IconData do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd := FHandle;
    uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
    hIcon := FIcon.Handle;
    StrPCopy(szTip, FToolTip);
    uCallbackMessage := CM_TRAYICONEVENT;
    uID := ICON_ID;
  end;

  if Preview and FActive and (not FIcon.Empty or (FAnimated and Assigned(FIcons))) then
  begin
    Shell_NotifyIcon(NIM_ADD, @IconData);
    Shell_NotifyIcon(NIM_MODIFY, @IconData);
  end
  else Shell_NotifyIcon(NIM_DELETE, @IconData);
end;

procedure TCoolTrayIcon.ModifyIcon(AIcon: TIcon);
var
  IconData: TNotifyIconData;
begin
  with IconData do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd := FHandle;
    uFlags := NIF_ICON;
    hIcon := AIcon.Handle;
    uID := ICON_ID;
  end;
  Shell_NotifyIcon(NIM_MODIFY, @IconData);
end;

procedure TCoolTrayIcon.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and Assigned(FIcons) and (AComponent = FIcons) then
    FIcons := nil;
  if (Operation = opRemove) and Assigned(FPopupMenu) and (AComponent = FPopupMenu) then
    FPopupMenu := nil;
end;

procedure TCoolTrayIcon.Loaded;
begin
  inherited Loaded;
  UpdateTimer;
  UpdateIcon;
end;

procedure TCoolTrayIcon.WndProc(var Message: TMessage);
var
  AIcon: TIcon;
begin
  with Message do
  try
    case Msg of
      CM_TRAYICONEVENT:
        case lParam of
          WM_RBUTTONDOWN: MouseDown(mbRight);
          WM_LBUTTONDOWN: MouseDown(mbLeft);
          WM_RBUTTONUP: MouseUp(mbRight);
          WM_LBUTTONUP: MouseUp(mbLeft);
          WM_LBUTTONDBLCLK: DoubleClick(mbLeft);
          WM_RBUTTONDBLCLK: DoubleClick(mbRight);
        end;

      WM_TIMER:
        if Assigned(FIcons) and (wParam = 1) then
        begin
          AIcon := TIcon.Create;
          try
            FIcons.GetIcon(FIconIndex, AIcon);
            ModifyIcon(AIcon);
          finally
            AIcon.Free;
          end;

          if FIconIndex < Pred(FIcons.Count) then
            Inc(FIconIndex) else
              FIconIndex := 0;
        end;
    end;
    Result := DefWindowProc(FHandle, Msg, wParam, lParam);
  except
    Application.HandleException(Self);
  end;
end;

procedure TCoolTrayIcon.MouseDown(Button: TMouseButton);
var
  P: TPoint;
begin
  GetCursorPos(P);
  if Assigned(FOnMouseDown) then
    FOnMouseDown(Self, Button, [], P.X, P.Y);
end;

procedure TCoolTrayIcon.MouseUp(Button: TMouseButton);
var
  P: TPoint;
begin
  GetCursorPos(P);

  if Assigned(FPopupMenu) then
  begin
    SetForegroundWindow(FHandle);

    if not FOwnerDrawMenu then
      FPopupMenu.Popup(P.X, P.Y) else
        TrackPopupMenu(FPopupMenu.Handle, TPM_LEFTALIGN or TPM_RIGHTBUTTON,
          P.X, P.Y, 0, (FPopupMenu.Owner as TWinControl).Handle, nil);

    SetForegroundWindow(FHandle);
  end;

  if Assigned(FOnMouseUp) then
    FOnMouseUp(Self, Button, [], P.X, P.Y);
end;

procedure TCoolTrayIcon.DoubleClick(Button: TMouseButton);
var
  P: TPoint;
begin
  GetCursorPos(P);
  if Assigned(FOnDoubleClick) then
    FOnDoubleClick(Self, Button, [], P.X, P.Y);
end;

{TCoolInstancesChecker}
constructor TCoolInstancesChecker.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FInstanceAction := iaSwitchToPrevious;
  FInstanceID := -1;
end;

destructor TCoolInstancesChecker.Destroy;
begin
  if FInstanceID <> -1 then
    GlobalDeleteAtom(FInstanceID);

  inherited Destroy;
end;

procedure TCoolInstancesChecker.Loaded;
begin
  inherited Loaded;
  if GlobalFindAtom(PChar(Application.ExeName)) = 0 then
    FInstanceID := GlobalAddAtom(PChar(Application.ExeName)) else
      InstancesCheck;
end;

procedure TCoolInstancesChecker.InstancesCheck;
var
  I: Integer;
  Info: PWindowInfo;
  InfoList: TList;
begin
  if not (csDesigning in ComponentState) then
  begin
    with TCoolWindowsInformant.Create(Self) do
    try
      Info := New(PWindowInfo);
      try
        CertainWindowInfo(Application.Handle, Info);

        ParentHandle := GetDesktopWindow;
        UpdateWindows;

        InfoList := TList.Create;
        try
          for I := 0 to Pred(Count) do
            if (Window[I]^.wTitle = Info^.wTitle) and (Window[I]^.wClassName = Info^.wClassName) and (Window[I]^.wHandle <> Application.Handle) then
              InfoList.Add(Window[I]);

          if InfoList.Count <> 0 then
            case FInstanceAction of
              iaStartNew:
                ;
              iaSwitchToPrevious:
                begin
                  SetForegroundWindow(GetLastActivePopup(PWindowInfo(InfoList[Pred(InfoList.Count)])^.wHandle));
                  SendMessage(GetLastActivePopup(PWindowInfo(InfoList[Pred(InfoList.Count)])^.wHandle), WM_NOTIFYPARAMSTR, 0, LongInt(CmdLine));
                  Application.Terminate;
                end;
              iaCloseAll:
                begin
                  for I := 0 to Pred(InfoList.Count) do
                    SendMessage(PWindowInfo(InfoList[I])^.wHandle, WM_CLOSE, 0, 0);

                  Application.Terminate;
                end;
            end;
        finally
          InfoList.Free;
        end;

      finally
        Dispose(Info);
      end;
    finally
      Free;
    end;
  end;
end;

{TCoolDisksInformant}
constructor TCoolDisksInformant.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FDrives := TStringList.Create;
end;

destructor TCoolDisksInformant.Destroy;
begin
  FDrives.Free;
  inherited Destroy;
end;

procedure TCoolDisksInformant.SetDrive(Value: TFileName);
begin
  if FDrive <> Value then
  begin
    if Drives.IndexOf(Value) <> -1 then
      FDrive := Value else
      FDrive := '';
  end;
end;

function TCoolDisksInformant.GetDrives: TStringList;
var
  I: Integer;
  S: string;
  buff: array[0..254] of Char;
begin
  FillChar(buff, SizeOf(buff), #0);
  S := '';
  FDrives.Clear;

  GetLogicalDriveStrings(SizeOf(buff), buff);
  for I := 0 to Pred(SizeOf(buff)) do
    if buff[I] <> #0 then
      S := S + buff[I] else
        if S <> '' then
        begin
          FDrives.Add(S);
          S := '';
        end;

  Result := FDrives;
end;

function TCoolDisksInformant.GetDriveType: TDriveType;
var
  DrvType: Integer;
begin
  Result := dtNoDrive;
  if FDrive <> '' then
  begin
    DrvType := Windows.GetDriveType(PChar(FDrive));
    case DrvType of
      0:               Result := dtUnknown;
      DRIVE_REMOVABLE: Result := dtFloppy;
      DRIVE_FIXED:     Result := dtFixed;
      DRIVE_REMOTE:    Result := dtNetwork;
      DRIVE_CDROM:     Result := dtCDROM;
      DRIVE_RAMDISK:   Result := dtRAM;
    end;
  end;
end;

function TCoolDisksInformant.GetDriveTypeStr: string;
var
  DrvType: Integer;
begin
  Result := 'DOES NOT EXIST';
  if FDrive <> '' then
  begin
    DrvType := Windows.GetDriveType(PChar(FDrive));
    case DrvType of
      0:               Result := 'UNKNOWN';
      DRIVE_REMOVABLE: Result := 'REMOVABLE';
      DRIVE_FIXED:     Result := 'FIXED';
      DRIVE_REMOTE:    Result := 'NETWORKING';
      DRIVE_CDROM:     Result := 'CD-ROM';
      DRIVE_RAMDISK:   Result := 'RAM';
    end;
  end;
end;

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolDisksInformant.GetTotalBytes: int64;
var
  FreeAvailable, TotalSpace: TLargeInteger;
  TotalFree: PLargeInteger;
begin
  Result := 0;
  if FDrive <> '' then
  begin
    FreeAvailable := 0;
    TotalSpace := 0;
    TotalFree := nil;

    GetDiskFreeSpaceEx(PChar(FDrive), FreeAvailable, TotalSpace, TotalFree);
    Result := TotalSpace;
  end;
end;

function TCoolDisksInformant.GetFreeBytes: int64;
var
  FreeAvailable, TotalSpace: TLargeInteger;
  TotalFree: PLargeInteger;
begin
  Result := 0;
  if FDrive <> '' then
  begin
    FreeAvailable := 0;
    TotalSpace := 0;
    TotalFree := nil;

    GetDiskFreeSpaceEx(PChar(FDrive), FreeAvailable, TotalSpace, TotalFree);
    Result := FreeAvailable;
  end;
end;
{$ELSE}
function TCoolDisksInformant.GetTotalBytes: DWORD;
var
  lpSectors, lpBytes, lpFreeClusters, lpTotalClusters: DWORD;
begin
  Result := 0;
  if FDrive <> '' then
  begin
    GetDiskFreeSpace(PChar(FDrive), lpSectors, lpBytes, lpFreeClusters, lpTotalClusters);
    Result := lpSectors * lpBytes * lpTotalClusters;
  end;
end;

function TCoolDisksInformant.GetFreeBytes: DWORD;
var
  lpSectors, lpBytes, lpFreeClusters, lpTotalClusters: DWORD;
begin
  Result := 0;
  if FDrive <> '' then
  begin
    GetDiskFreeSpace(PChar(FDrive), lpSectors, lpBytes, lpFreeClusters, lpTotalClusters);
    Result := lpSectors * lpBytes * lpFreeClusters;
  end;
end;
{$ENDIF}

function TCoolDisksInformant.GetVolumeName: string;
var
  buffVolumeName: array[0..254] of Char;
  lpVolSerialNum: DWORD;
  lpMaxNameLength: DWORD;
  lpFlag: DWORD;
  buffSystemName: array[0..254] of Char;
begin
  Result := '';
  if FDrive <> '' then
  begin
    GetVolumeInformation(PChar(FDrive), buffVolumeName, SizeOf(buffVolumeName),
                         @lpVolSerialNum, lpMaxNameLength, lpFlag,
                         buffSystemName, SizeOf(buffSystemName));
    Result := buffVolumeName;
  end;
end;

const
  VOLUME_LENGTH = 11;

procedure TCoolDisksInformant.SetVolumeName(Value: string);
begin
  if FDrive <> '' then
  begin
    if Length(Value) > VOLUME_LENGTH then
      SetLength(Value, VOLUME_LENGTH);

    SetVolumeLabel(PChar(FDrive), PChar(Value));
  end;
end;

function TCoolDisksInformant.GetFileSystemName: string;
var
  buffVolumeName: array[0..254] of Char;
  lpVolSerialNum: DWORD;
  lpMaxNameLength: DWORD;
  lpFlag: DWORD;
  buffSystemName: array[0..254] of Char;
begin
  Result := '';
  if FDrive <> '' then
  begin
    GetVolumeInformation(PChar(FDrive), buffVolumeName, SizeOf(buffVolumeName),
                         @lpVolSerialNum, lpMaxNameLength, lpFlag,
                         buffSystemName, SizeOf(buffSystemName));
    Result := buffSystemName;
  end;
end;

{TCoolAnimate}
constructor TCoolAnimate.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCoolImageChangeLink := TCoolChangeLink.Create;
  FCoolImageChangeLink.OnChange := CoolImagesChange;
  FHandle := AllocateHWnd(WndProc);

  FBevelInner := bvNone;
  FBevelOuter := bvNone;

  FImageIndex := 0;
  FActive := False;
  FInterval := 200;
  FTransparent := False;
  SetBounds(Left, Top, 100, 100);
end;

destructor TCoolAnimate.Destroy;
begin
  Active := False;
  FCoolImageChangeLink.Free;
  DeallocateHWnd(FHandle);
  inherited Destroy;
end;

procedure TCoolAnimate.SetActive(Value: Boolean);
begin
  if FActive <> Value then
  begin
    FActive := Value;
    UpdateTimer;
    Invalidate;
  end;
end;

procedure TCoolAnimate.SetCoolImages(Value: TCoolImages);
begin
  if Assigned(CoolImages) then
    CoolImages.UnRegisterChanges(FCoolImageChangeLink);

  FCoolImages := Value;

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

  UpdateTimer;
end;

procedure TCoolAnimate.SetInterval(Value: Cardinal);
begin
  if FInterval <> Value then
  begin
    FInterval := Value;
    UpdateTimer;
  end;
end;

procedure TCoolAnimate.SetBevelInner(Value: TPanelBevel);
begin
  if FBevelInner <> Value then
  begin
    FBevelInner := Value;
    Invalidate;
  end;
end;

procedure TCoolAnimate.SetBevelOuter(Value: TPanelBevel);
begin
  if FBevelOuter <> Value then
  begin
    FBevelOuter := Value;
    Invalidate;
  end;
end;

procedure TCoolAnimate.CoolImagesChange(Sender: TObject);
begin
  Active := False;
  {$IFDEF DELPHI4_OR_ABOVE}
  AdjustSize;
  {$ENDIF}
end;

procedure TCoolAnimate.UpdateTimer;
begin
  KillTimer(FHandle, 1);
  if (FInterval <> 0) and FActive and Assigned(FCoolImages) then
    if SetTimer(FHandle, 1, FInterval, nil) = 0 then
      raise EOutOfResources.Create('Low resources');
end;

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

procedure TCoolAnimate.Loaded;
begin
  inherited Loaded;
end;

procedure TCoolAnimate.WndProc(var Message: TMessage);
var
  baseBitmap: TBitmap;
  tempBitmap: TBitmap;
begin
  inherited WndProc(Message);
  with Message do
  try
    case Msg of
      WM_TIMER:
        if Assigned(FCoolImages) and (wParam = 1) then
        begin
          if (FCoolImages.Images.Count > 0) and Assigned(FCoolImages.Images.Items[FImageIndex].Bitmap) and not FCoolImages.Images.Items[FImageIndex].Bitmap.Empty then
          begin
            baseBitmap := TBitmap.Create;
            try
              if FTransparent then
              begin
                baseBitmap.Width := Parent.Width;
                baseBitmap.Height := Parent.Height;

                SendMessage(Parent.Handle, WM_ERASEBKGND, baseBitmap.Canvas.Handle, 0);
                SendMessage(Parent.Handle, WM_PAINT, baseBitmap.Canvas.Handle, 0);

                tempBitmap := FCoolImages.Images.Items[FImageIndex].Bitmap;

                TransparentStretchBltEx(baseBitmap.Canvas.Handle, tempBitmap.Canvas.Handle,
                  Rect(Left + Pred((Width - tempBitmap.Width) div 2), Top + Pred((Height - tempBitmap.Height) div 2), Left + Pred((Width - tempBitmap.Width) div 2) + tempBitmap.Width, Top + Pred((Height - tempBitmap.Height) div 2) + tempBitmap.Height),
                  Rect(0, 0, tempBitmap.Width, tempBitmap.Height),
                  tempBitmap.TransparentColor);

                Canvas.CopyRect(Rect(0, 0, Width, Height), baseBitmap.Canvas, Rect(Left, Top, Left + Width, Top + Height));
              end else
              begin
                baseBitmap.Assign(FCoolImages.Images.Items[FImageIndex].Bitmap);
                Canvas.Draw(Pred((Width - baseBitmap.Width) div 2), Pred((Height - baseBitmap.Height) div 2), baseBitmap);
              end;
            finally
              baseBitmap.Free;
            end;
          end;

          if FImageIndex < Pred(FCoolImages.Images.Count) then
            Inc(FImageIndex) else
              FImageIndex := 0;
        end;
    end;
  except
    Application.HandleException(Self);
  end;
end;

procedure TCoolAnimate.Paint;
const
  {$IFDEF DELPHI4_OR_ABOVE}
  FInnerEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER, 0);
  FOuterEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER, 0);
  {$ELSE}
  FInnerEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER);
  FOuterEdges: array[TPanelBevel] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER);
  {$ENDIF}
var
  R: TRect;
begin
  inherited Paint;
  R := ClientRect;

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

  {$IFDEF DELPHI4_OR_ABOVE}
  if not ((FBevelInner in [bvNone, bvSpace]) and (FBevelOuter in [bvNone, bvSpace])) then
  {$ELSE}
  if not ((FBevelInner = bvNone) and (FBevelOuter = bvNone)) then
  {$ENDIF}
    DrawEdge(Canvas.Handle, R, FInnerEdges[FBevelInner] or FOuterEdges[FBevelOuter], BF_RECT);
end;

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolAnimate.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
var
  Bmp: TBitmap;
begin
  Result := True;

  if AutoSize and Assigned(FCoolImages) then
  begin
    Bmp := FCoolImages.Images.Items[FImageIndex].Bitmap;

    if Assigned(Bmp) and (Bmp.Width > 0) and (Bmp.Height > 0) then
    begin
      if Align in [alNone, alLeft, alRight] then
        NewWidth := Bmp.Width;

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

{TAnimateThread}
constructor TAnimateThread.Create(Handle: THandle; SourceBmp, DestBmp: TBitmap; Effect: TAnimateEffect; Canvas: TCanvas; Exclusive: Boolean);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  Priority := tpNormal;
  FSourceBmp := SourceBmp;
  FDestBmp := DestBmp;
  FEffect := Effect;
  FHandle := Handle;
  FCanvas := Canvas;
  FExclusive := Exclusive;
end;

destructor TAnimateThread.Destroy;
begin
  inherited Destroy;
end;

function TAnimateThread.ReasonToStop: Boolean;
begin
  try
    Result := Terminated or Application.Terminated or (FDestBmp = nil) or FDestBmp.Empty or (FSourceBmp = nil) or FSourceBmp.Empty or (FCanvas = nil);
  except
    Application.HandleException(Self);
    Result := True;
  end;
end;

procedure TAnimateThread.CopyRect;
begin
  if ReasonToStop then
  begin
    Terminate;
  end else
  begin
    {$IFNDEF VER90}
    if (FDestBmp.Canvas.LockCount = 0) then
    {$ENDIF}
    begin
      {$IFNDEF VER90}
      FDestBmp.Canvas.TryLock;
      {$ENDIF}
      FDestBmp.Canvas.CopyRect(R, FSourceBmp.Canvas, R);
      {$IFNDEF VER90}
      FDestBmp.Canvas.UnLock;
      {$ENDIF}
    end;
    {$IFNDEF VER90}
    if (FCanvas.LockCount = 0) then
    {$ENDIF}
    begin
      {$IFNDEF VER90}
      FCanvas.TryLock;
      {$ENDIF}
      FCanvas.CopyRect(R, FSourceBmp.Canvas, R);
      {$IFNDEF VER90}
      FCanvas.UnLock;
      {$ENDIF}
    end;
  end;
end;

procedure TAnimateThread.DoTopToBottom;
var
  Y: Integer;
begin
  for Y := 0 to Pred(FSourceBmp.Height) do
  begin
    R := Rect(0, Y, FSourceBmp.Width, Succ(Y));
    Sleep(DELAY_INTERVAL);
    Synchronize(CopyRect);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoBottomToTop;
var
  Y: Integer;
begin
  for Y := Pred(FSourceBmp.Height) downto 0 do
  begin
    R := Rect(0, Pred(Y), FSourceBmp.Width, Y);
    Sleep(DELAY_INTERVAL);
    Synchronize(CopyRect);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoLeftToRight;
var
  X: Integer;
begin
  for X := 0 to Pred(FSourceBmp.Width) do
  begin
    R := Rect(X, 0, Succ(X), FSourceBmp.Height);
    Sleep(DELAY_INTERVAL);
    Synchronize(CopyRect);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoRightToLeft;
var
  X: Integer;
begin
  for X := Pred(FSourceBmp.Width) downto 0 do
  begin
    R := Rect(Pred(X), 0, X, FSourceBmp.Height);
    Sleep(DELAY_INTERVAL);
    Synchronize(CopyRect);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoTopBottomToCenter;
var
  Y, Y1: Integer;
begin
  Y := 0;
  Y1 := Pred(FSourceBmp.Height);

  while (Y <= FSourceBmp.Height div 2) and (Y1 >= FSourceBmp.Height div 2) do
  begin
    Sleep(DELAY_INTERVAL);

    R := Rect(0, Y, FSourceBmp.Width, Succ(Y));
    Synchronize(CopyRect);

    R := Rect(0, Pred(Y1), FSourceBmp.Width, Y1);
    Synchronize(CopyRect);

    Inc(Y);
    Dec(Y1);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoLeftRightToCenter;
var
  X, X1: Integer;
begin
  X := 0;
  X1 := Pred(FSourceBmp.Width);

  while (X <= FSourceBmp.Width div 2) and (X1 >= FSourceBmp.Width div 2) do
  begin
    Sleep(DELAY_INTERVAL);

    R := Rect(X, 0, Succ(X), FSourceBmp.Height);
    Synchronize(CopyRect);

    R := Rect(Pred(X1), 0, X1, FSourceBmp.Height);
    Synchronize(CopyRect);

    Inc(X);
    Dec(X1);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoCenterToTopBottom;
var
  Y, Y1: Integer;
begin
  Y := Pred(FSourceBmp.Height) div 2;
  Y1 := Pred(FSourceBmp.Height) div 2;

  while (Y >= 0) and (Y1 <= Pred(FSourceBmp.Height)) do
  begin
    Sleep(DELAY_INTERVAL);

    R := Rect(0, Y, FSourceBmp.Width, Succ(Y));
    Synchronize(CopyRect);

    R := Rect(0, Pred(Y1), FSourceBmp.Width, Y1);
    Synchronize(CopyRect);

    Dec(Y);
    Inc(Y1);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoCenterToLeftRight;
var
  X, X1: Integer;
begin
  X := Pred(FSourceBmp.Width) div 2;
  X1 := Pred(FSourceBmp.Width) div 2;

  while (X >= 0) and (X1 <= Pred(FSourceBmp.Width)) do
  begin
    Sleep(DELAY_INTERVAL);

    R := Rect(X, 0, Succ(X), FSourceBmp.Height);
    Synchronize(CopyRect);

    R := Rect(Pred(X1), 0, X1, FSourceBmp.Height);
    Synchronize(CopyRect);

    Dec(X);
    Inc(X1);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoPartsHorizontally;
var
  Y, Y1: Integer;
begin
  Y := 0;
  while Y < PARTS_VALUE do
  begin
    Y1 := 0;
    while Y1 < Pred(FSourceBmp.Height) do
    begin
      R := Rect(0, Y1, FSourceBmp.Width, Y1 + Y + 1);

      Sleep(DELAY_INTERVAL);
      Synchronize(CopyRect);

      Y1 := Y1 + PARTS_VALUE;
    end;
    Inc(Y);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.DoPartsVertically;
var
  X, X1: Integer;
begin
  X := 0;
  while X < PARTS_VALUE do
  begin
    X1 := 0;
    while X1 < Pred(FSourceBmp.Width) do
    begin
      R := Rect(X1, 0, X + X1 + 1, FSourceBmp.Height);

      Sleep(DELAY_INTERVAL);
      Synchronize(CopyRect);

      X1 := X1 + PARTS_VALUE;
    end;
    Inc(X);

    if ReasonToStop then
      Break;
  end;
end;

procedure TAnimateThread.Execute;
begin
  try
    if FExclusive then
    try
      case FEffect of
        aeStripesDown: Synchronize(DoTopToBottom);
        aeStripesUp: Synchronize(DoBottomToTop);
        aeStripesLeft: Synchronize(DoRightToLeft);
        aeStripesRight: Synchronize(DoLeftToRight);
        aeStripesTBCenter: Synchronize(DoTopBottomToCenter);
        aeStripesLRCenter: Synchronize(DoLeftRightToCenter);
        aeStripesCenterTB: Synchronize(DoCenterToTopBottom);
        aeStripesCenterLR: Synchronize(DoCenterToLeftRight);
        aeStripesPartsHz: Synchronize(DoPartsHorizontally);
        aeStripesPartsVt: Synchronize(DoPartsVertically);
      end;
    finally
      SendMessage(FHandle, CM_THREADOVER, 0, 0);
    end else
    try
      case FEffect of
        aeStripesDown: DoTopToBottom;
        aeStripesUp: DoBottomToTop;
        aeStripesLeft: DoRightToLeft;
        aeStripesRight: DoLeftToRight;
        aeStripesTBCenter: DoTopBottomToCenter;
        aeStripesLRCenter: DoLeftRightToCenter;
        aeStripesCenterTB: DoCenterToTopBottom;
        aeStripesCenterLR: DoCenterToLeftRight;
        aeStripesPartsHz: DoPartsHorizontally;
        aeStripesPartsVt: DoPartsVertically;
      end;
    finally
      SendMessage(FHandle, CM_THREADOVER, 0, 0);
    end;
  except
    Application.HandleException(Self);
  end;
end;

{TCoolAnimateEffects}
constructor TCoolAnimateEffects.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csOpaque];
  FHandle := AllocateHWnd(WndProc);
  SetBounds(Left, Top, 100, 100);

  FCoolImagesChangeLink := TCoolChangeLink.Create;
  FCoolImagesChangeLink.OnChange := CoolImagesChange;

  FBackground := TBitmap.Create;
  FBackground.OnChange := BackgroundChange;

  FImageIndex := 0;
  FActive := False;
  FAnimateEffect := aeStripesDown;
  FExclusive := False;
end;

destructor TCoolAnimateEffects.Destroy;
begin
  if FThread <> nil then
  begin
    FThread.Terminate;
    repeat
      Application.ProcessMessages;
    until FThread = nil;
  end;

  Active := False;
  FCoolImagesChangeLink.Free;
  FBackground.Free;
  DeallocateHWnd(FHandle);
  inherited Destroy;
end;

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

  FCoolImages := Value;
  {$IFDEF DELPHI4_OR_ABOVE}
  AdjustSize;
  {$ENDIF}

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

  UpdateTimer;
end;

procedure TCoolAnimateEffects.CoolImagesChange(Sender: TObject);
begin
  Active := False;
  {$IFDEF DELPHI4_OR_ABOVE}
  AdjustSize;
  {$ENDIF}
end;

procedure TCoolAnimateEffects.BackgroundChange(Sender: TObject);
begin
end;

procedure TCoolAnimateEffects.SetActive(Value: Boolean);
begin
  if FActive <> Value then
  begin
    FActive := Value;
    UpdateTimer;
    Invalidate;
  end;
end;

procedure TCoolAnimateEffects.SetAnimateEffect(Value: TAnimateEffect);
begin
  if FAnimateEffect <> Value then
    FAnimateEffect := Value;
end;

{$IFDEF DELPHI4_OR_ABOVE}
function TCoolAnimateEffects.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
var
  Bmp: TBitmap;
begin
  Result := True;

  if AutoSize and Assigned(FCoolImages) then
  begin
    Bmp := FCoolImages.Images.Items[FImageIndex].Bitmap;

    if Assigned(Bmp) and (Bmp.Width > 0) and (Bmp.Height > 0) then
    begin
      if Align in [alNone, alLeft, alRight] then
        NewWidth := Bmp.Width;

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

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

procedure TCoolAnimateEffects.Paint;
var
  R: TRect;
begin
  with Canvas do
    if DesignTime(Self) then
    begin
      R := ClientRect;
      Pen.Style := psDash;
      Brush.Color := Color;
      Rectangle(R.Left, R.Top, R.Right, R.Bottom);
    end else
    begin
      Draw(0, 0, FBackground);
    end;
end;

procedure TCoolAnimateEffects.Loaded;
begin
  inherited Loaded;
end;

procedure TCoolAnimateEffects.WndProc(var Message: TMessage);
begin
  with Message do
  try
    case Msg of
      CM_THREADOVER:
        if FThread <> nil then
          EndProcess;
      WM_TIMER:
        if FThread = nil then
          StartProcess;
    end;
  except
    Application.HandleException(Self);
  end;
  inherited WndProc(Message);
end;

//ping...
procedure TCoolAnimateEffects.StartProcess;
var
  IsContinue: Boolean;
begin
  IsContinue := Active;
  try
    if Assigned(FOnAnimationStart) then
      FOnAnimationStart(Self, FImageIndex, IsContinue);
  finally
    Active := IsContinue;
  end;

  if FActive and Assigned(FCoolImages) and (Pred(FCoolImages.Images.Count) >= FImageIndex) then
  begin
    FThread := TAnimateThread.Create(FHandle, FCoolImages.Images.Items[FImageIndex].Bitmap, FBackground, FAnimateEffect, Canvas, FExclusive);
    FThread.Resume;
    Invalidate;
  end;
end;

//pong...
procedure TCoolAnimateEffects.EndProcess;
var
  IsContinue: Boolean;
begin
  FThread := nil;

  IsContinue := Active;
  try
    if Assigned(FOnAnimationEnd) then
      FOnAnimationEnd(Self, FImageIndex, IsContinue);
  finally
    Active := IsContinue;
  end;

  if FActive then
    if FImageIndex = Pred(FCoolImages.Images.Count) then
      FImageIndex := 0 else
        Inc(FImageIndex);
end;

procedure TCoolAnimateEffects.UpdateTimer;
begin
  KillTimer(FHandle, 1);
  if FActive and (FCoolImages <> nil) and not DesignTime(Self) then
    if SetTimer(FHandle, 1, 100, nil) = 0 then
      raise EOutOfResources.Create('Low resources');
end;

procedure TCoolAnimateEffects.CMColorChanged(var Message: TMessage);
begin
  inherited;
  if Assigned(FBackground) then
  begin
    FBackground.Canvas.Brush.Color := Color;
    FBackground.Canvas.FillRect(ClientRect);
    Invalidate;
  end;
end;

procedure TCoolAnimateEffects.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
  inherited;
  if Assigned(FBackground) then
  begin
    FBackground.Width := Width;
    FBackground.Height := Height;
    Invalidate;
  end;
end;

procedure TCoolAnimateEffects.FillTheControl(AColor: TColor);
begin
  with FBackground.Canvas do
  begin
    Brush.Color := AColor;
    FillRect(ClientRect);
  end;
end;

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

  FTimer := TTimer.Create(Self);
  FTimer.Interval := 200;
  FTimer.Enabled := False;
  FTimer.OnTimer := TimerAction;

  FInterval := 200;
  FActive := False;
  {$ifndef ver90}
  FForm := Owner as TCustomform;
  {$else}
  FForm := Owner as TForm;
  {$endif}
  FEffectTargets := [etForm];
  FEffectKind := ekCaptionScrolling;

  FFormScrollBy := 1;
  FAppScrollBy := 1;
  FFormReverse := False;
  FAppReverse := False;
  FFormCaption := FForm.Caption;
  FApplicationTitle := Application.Title;
end;

destructor TCoolCaptionEffects.Destroy;
begin
  FTimer.Free;
  inherited Destroy;
end;

procedure TCoolCaptionEffects.SetActive(Value: Boolean);
begin
  if FActive <> Value then
  begin
    FActive := Value;
    FTimer.Enabled := FActive;
  end;
end;

procedure TCoolCaptionEffects.SetInterval(Value: Cardinal);
begin
  if FInterval <> Value then
  begin
    FInterval := Value;
    FTimer.Interval := FInterval;
  end;
end;

procedure TCoolCaptionEffects.SetEffectTargets(Value: TEffectTargets);
begin
  if FEffectTargets <> Value then
  begin
    FEffectTargets := Value;
  end;
end;

procedure TCoolCaptionEffects.SetEffectKind(Value: TEffectKind);
begin
  if FEffectKind <> Value then
  begin
    FEffectKind := Value;
  end;
end;

procedure TCoolCaptionEffects.ScrollFormCaption;
const
  SB_SPACE = ' ';
var
  L, I: Integer;
  S: string;
begin
  L := Length(FFormCaption);
  if FFormReverse then
  begin
    for I := 0 to (L-FFormScrollBy-1) do S := S + SB_SPACE;
    S := Copy(FFormCaption, L - (L-FFormScrollBy), L) + S;
    FForm.Caption := S;
  end else
  begin
    for I := 0 to (L-FFormScrollBy-1) do S := S + SB_SPACE;
    S := S + Copy(FFormCaption, 1, L - (L-FFormScrollBy));
    FForm.Caption := S;
  end;

  Inc(FFormScrollBy);
  if FFormScrollBy = L then
  begin
    FFormReverse := not FFormReverse;
    FFormScrollBy := 1;
  end;
end;

procedure TCoolCaptionEffects.ScrollApplicationTitle;
const
  SB_SPACE = ' ';
var
  L, I: Integer;
  S: string;
begin
  L := Length(FApplicationTitle);
  if FAppReverse then
  begin
    for I := 0 to (L-FAppScrollBy-1) do S := S + SB_SPACE;
    S := Copy(FApplicationTitle, L - (L-FAppScrollBy), L) + S;
    Application.Title := S;
  end else
  begin
    for I := 0 to (L-FAppScrollBy-1) do S := S + SB_SPACE;
    S := S + Copy(FApplicationTitle, 1, L - (L-FAppScrollBy));
    Application.Title := S;
  end;

  Inc(FAppScrollBy);
  if FAppScrollBy = L then
  begin
    FAppReverse := not FAppReverse;
    FAppScrollBy := 1;
  end;
end;

procedure TCoolCaptionEffects.TimerAction(Sender: TObject);
begin
  if not (csDesigning in ComponentState) then
    if FEffectKind = ekCaptionScrolling then
    begin
      if etForm in FEffectTargets then
        ScrollFormCaption;

      if etApplication in FEffectTargets then
        ScrollApplicationTitle;
    end else
    if FEffectKind = ekCaptionBlinking then
    begin
      if etForm in FEffectTargets then
        if FForm.Caption = '' then
          FForm.Caption := FFormCaption
        else
          FForm.Caption := '';

      if etApplication in FEffectTargets then
        if Application.Title = '' then
          Application.Title := FApplicationTitle
        else
          Application.Title := '';
    end else
    if FEffectKind = ekBlinking then
    begin
      if etForm in FEffectTargets then
        FlashWindow(FForm.Handle, True);

      if etApplication in FEffectTargets then
        FlashWindow(Application.Handle, True);
    end;
end;

procedure TCoolCaptionEffects.Loaded;
begin
  inherited Loaded;
  if FActive and not (csDesigning in ComponentState) and (FEffectKind <> ekBlinking) then
  begin
    if etForm in FEffectTargets then
      FForm.Caption := '';

    if etApplication in FEffectTargets then
      Application.Title := '';
  end else
  begin
    FForm.Caption := FFormCaption;
    Application.Title := FApplicationTitle;
  end;
end;

{TCoolShadow}
constructor TCoolShadow.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FShadowOrientation := soRightBottom;
  FShadowControl := nil;
  FShadowSize := 10;
  Color := clBtnShadow;
  SetBounds(Left, Top, 50, 50);
end;

destructor TCoolShadow.Destroy;
begin
  inherited Destroy;
end;

procedure TCoolShadow.SetShadowOrientation(Value: TShadowOrientation);
begin
  if FShadowOrientation <> Value then
  begin
    FShadowOrientation := Value;
    ApplyShadow;
    Invalidate;
  end;
end;

procedure TCoolShadow.SetShadowControl(Value: TControl);
begin
  if FShadowControl <> Value then
  begin
    FShadowControl := Value;
    Visible := Assigned(FShadowControl) and Assigned(FShadowControl.Parent);

    if Visible then
    begin
      Parent := FShadowControl.Parent;
      ApplyShadow;
      SendToBack;
      Invalidate;
    end;
  end;
end;

procedure TCoolShadow.SetShadowSize(Value: Integer);
begin
  if FShadowSize <> Value then
  begin
    FShadowSize := Value;
    ApplyShadow;
    Invalidate;
  end;
end;

procedure TCoolShadow.ApplyShadow;
begin
  if Assigned(FShadowControl) then
    with FShadowControl do
      case FShadowOrientation of
        soLeftTop:
          Self.SetBounds(Left-FShadowSize, Top-FShadowSize, Width, Height);
        soRightTop:
          Self.SetBounds(Left+FShadowSize, Top-FShadowSize, Width, Height);
        soLeftBottom:
          Self.SetBounds(Left-FShadowSize, Top+FShadowSize, Width, Height);
        soRightBottom:
          Self.SetBounds(Left+FShadowSize, Top+FShadowSize, Width, Height);
      end;
end;

procedure TCoolShadow.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and Assigned(FShadowControl) and (AComponent = FShadowControl) then
  begin
    FShadowControl := nil;
    Invalidate;
  end;
end;

procedure TCoolShadow.Paint;
var
  R: TRect;
begin
  inherited Paint;
  R := ClientRect;

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

  if Assigned(FShadowControl) then
  begin
    Canvas.Brush.Color := Color;
    Canvas.FillRect(R);
  end;
end;

{TMemoryStreamEx}
procedure TMemoryStreamEx.WriteInteger(Value: Integer);
begin
  Write(Value, SizeOf(Value));
end;

function TMemoryStreamEx.ReadInteger: Integer;
begin
  Read(Result, SizeOf(Result));
end;

procedure TMemoryStreamEx.WriteBoolean(Value: Boolean);
begin
  WriteInteger(Integer(Value));
end;

function TMemoryStreamEx.ReadBoolean: Boolean;
begin
  Result := Boolean(ReadInteger);
end;

procedure TMemoryStreamEx.WriteString(Value: string);
var
  StrLength: Integer;
begin
  StrLength := Length(Value);
  WriteInteger(StrLength);
  WriteBuffer(Value[1], StrLength);
end;

{$IFDEF DELPHI4_OR_ABOVE}
procedure TMemoryStreamEx.WriteString(Value: array of Char);
{$ELSE}
procedure TMemoryStreamEx.WriteStringEx(Value: array of Char);
{$ENDIF}
var
  S: string;
begin
  S := Value;
  WriteString(S);
end;

function TMemoryStreamEx.ReadString: string;
var
  StrLength: Integer;
begin
  StrLength := ReadInteger;
  SetLength(Result, StrLength);
  ReadBuffer(Result[1], StrLength);
end;

{TCoolClipboardComponent}
function TCoolClipboardComponent.ClearClipboard: Boolean;
begin
  OpenClipboard(Application.Handle);
  try
    Result := EmptyClipboard;
  finally
    CloseClipboard;
  end;
end;

procedure TCoolClipboardComponent.SaveClipboardToStream(Stream: TMemoryStreamEx; Format: Integer);
var
  Data: THandle;
  DataPtr: Pointer;
  DataSize: LongInt;
  buff: array[0..127] of Char;
  CustomFormat: Boolean;
begin
  OpenClipboard(Application.Handle);
  try
    Data := GetClipboardData(Format);
    if Data <> 0 then
    begin
      DataPtr := GlobalLock(Data);
      if DataPtr <> nil then
      begin
        DataSize := GlobalSize(Data);
        try
          FillChar(buff, SizeOf(buff), #0);
          CustomFormat := GetClipboardFormatName(Format, @buff, SizeOf(buff)) <> 0;
          Stream.WriteBoolean(CustomFormat);

          if CustomFormat then
            Stream.WriteString(buff) else
              Stream.WriteInteger(Format);

          Stream.WriteInteger(DataSize);
          Stream.WriteBuffer(DataPtr^, DataSize);
        finally
          GlobalUnlock(Data);
        end;
      end;
    end;
  finally
    CloseClipboard;
  end;
end;

procedure TCoolClipboardComponent.SaveClipboardToFile(FileName: TFileName);
var
  I: Integer;
  Stream: TMemoryStreamEx;
begin
  Stream := TMemoryStreamEx.Create;
  try
    for I := 0 to Pred(Clipboard.FormatCount) do
      SaveClipboardToStream(Stream, Clipboard.Formats[I]);

    Stream.SaveToFile(FileName);
  finally
    Stream.Free;
  end;
end;

procedure TCoolClipboardComponent.LoadClipboardFromStream(Stream: TMemoryStreamEx);
var
  Data: THandle;
  DataPtr: Pointer;
  DataSize: LongInt;
  Format: Integer;
  FormatName: string;
  CustomFormat: Boolean;
begin
  OpenClipboard(Application.Handle);
  try
    CustomFormat := Stream.ReadBoolean;
    if CustomFormat then
    begin
      FormatName := Stream.ReadString;
      Format := RegisterClipboardFormat(PChar(FormatName));
    end else
    begin
      Format := Stream.ReadInteger;
    end;

    DataSize := Stream.ReadInteger;

    Data := GlobalAlloc(GMEM_MOVEABLE, DataSize);
    try
      DataPtr := GlobalLock(Data);
      try
        Stream.ReadBuffer(DataPtr^, DataSize);
        SetClipboardData(Format, Data);
      finally
        GlobalUnlock(Data);
      end;
    except
      GlobalFree(Data);
      raise;
    end;
  finally
    CloseClipboard;
  end;
end;

procedure TCoolClipboardComponent.LoadClipboardFromFile(FileName: TFileName);
var
  Stream: TMemoryStreamEx;
begin
  Stream := TMemoryStreamEx.Create;
  try
    Stream.LoadFromFile(FileName);
    Stream.Position := 0;

    ClearClipboard;

    while Stream.Position < Stream.Size do
      LoadClipboardFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

{TCoolClipboardViewer}
constructor TCoolClipboardViewer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FreeCurrentViewerComponent;
  FNextWnd := 0;
  ParentColor := False;
  Color := clWindow;
end;

destructor TCoolClipboardViewer.Destroy;
begin
  FreeCurrentViewerComponent;
  inherited Destroy;
end;

function TCoolClipboardViewer.ClearClipboard: Boolean;
begin
  with TCoolClipboardComponent.Create(Self) do
  try
    Result := ClearClipboard;
  finally
    Free;
  end;
end;

procedure TCoolClipboardViewer.SaveClipboardToStream(Stream: TMemoryStreamEx; Format: Integer);
begin
  with TCoolClipboardComponent.Create(Self) do
  try
    SaveClipboardToStream(Stream, Format);
  finally
    Free;
  end;
end;

procedure TCoolClipboardViewer.SaveClipboardToFile(FileName: TFileName);
begin
  with TCoolClipboardComponent.Create(Self) do
  try
    SaveClipboardToFile(FileName);
  finally
    Free;
  end;
end;

procedure TCoolClipboardViewer.LoadClipboardFromStream(Stream: TMemoryStreamEx);
begin
  with TCoolClipboardComponent.Create(Self) do
  try
    LoadClipboardFromStream(Stream);
  finally
    Free;
  end;
end;

procedure TCoolClipboardViewer.LoadClipboardFromFile(FileName: TFileName);
begin
  with TCoolClipboardComponent.Create(Self) do
  try
    LoadClipboardFromFile(FileName);
  finally
    Free;
  end;
end;

function TCoolClipboardViewer.CreateCurrentViewerComponent(MyClass: TComponentClass): TComponent;
begin
  if FCurrentViewer = nil then
    Result := MyClass.Create(Self)
  else
    Result := FCurrentViewer;
end;

procedure TCoolClipboardViewer.FreeCurrentViewerComponent;
begin
  if FCurrentViewer <> nil then
  begin
    FCurrentViewer.Free;
    FCurrentViewer := nil;
  end;
end;

procedure TCoolClipboardViewer.RegisterClipboardViewer;
begin
  if (Handle <> 0) and (FNextWnd = 0) then
    FNextWnd := SetClipboardViewer(Handle);
end;

procedure TCoolClipboardViewer.UnregisterClipboardViewer;
begin
  if (Handle <> 0) and (FNextWnd <> 0) then
  begin
    ChangeClipboardChain(Handle, FNextWnd);
    FNextWnd := 0;
  end;
end;

procedure TCoolClipboardViewer.CreateWnd;
begin
  inherited CreateWnd;
  RegisterClipboardViewer;
end;

procedure TCoolClipboardViewer.DestroyWindowHandle;
begin
  inherited DestroyWindowHandle;
end;

procedure TCoolClipboardViewer.PaintContent;
begin
  FreeCurrentViewerComponent;
  if Clipboard.FormatCount <> 0 then
  begin
    if Clipboard.HasFormat(CF_TEXT) then
    begin
      FCurrentViewer := CreateCurrentViewerComponent(TMemo);
      with TMemo(FCurrentViewer) do
      begin
        Align := alClient;
        ScrollBars := ssBoth;
        BorderStyle := bsNone;
        Parent := Self;
        PasteFromclipboard;
        ReadOnly := True;
      end;
    end else
    if Clipboard.HasFormat(CF_PICTURE) then
    begin
      FCurrentViewer := CreateCurrentViewerComponent(TImage);
      with TImage(FCurrentViewer) do
      begin
        Picture.Assign(Clipboard);
        AutoSize := True;
        Parent := Self;
      end;
    end else
    if Clipboard.HasFormat(CF_WAVE) then
    begin
      FCurrentViewer := CreateCurrentViewerComponent(TImage);
      with TImage(FCurrentViewer) do
      begin
        Picture.Icon.Handle := LoadIcon(HInstance, 'SOUND_DATA_ICON');
        AutoSize := True;
        Parent := Self;
      end;
    end else
    begin
      FCurrentViewer := CreateCurrentViewerComponent(TImage);
      with TImage(FCurrentViewer) do
      begin
        Picture.Icon.Handle := LoadIcon(HInstance, 'UNKNOWN_DATA_ICON');
        AutoSize := True;
        Parent := Self;
      end;
    end;
    CenterControl(FCurrentViewer as TControl);
  end;
end;

procedure TCoolClipboardViewer.CenterControl(Control: TControl);
begin
  if Assigned(Control) then
  begin
    if Control.Width < Width then
      Control.Left := (Width - Control.Width) div 2;

    if Control.Height < Height then
      Control.Top := (Height - Control.Height) div 2;
  end;
end;

procedure TCoolClipboardViewer.WndProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_CHANGECBCHAIN, WM_DRAWCLIPBOARD:
      if FNextWnd <> 0 then
        SendMessage(FNextWnd, Message.Msg, Message.wParam, Message.lParam);
  end;
  inherited WndProc(Message);
end;

procedure TCoolClipboardViewer.WMDrawClipboard(var Message: TMessage);
begin
  inherited;
  PaintContent;

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

procedure TCoolClipboardViewer.WMChangeCBChain(var Message: TMessage);
begin
  inherited;
  if HWND(Message.wParam) = FNextWnd then
    FNextWnd := HWND(Message.lParam);
end;

procedure TCoolClipboardViewer.WMDestroy(var Message: TMessage);
begin
  UnregisterClipboardViewer;
  inherited;
end;

{TCoolTransparentArea}
constructor TCoolTransparentArea.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FPolygones := TPolygones.Create(Self);
  SetBounds(Left, Top, 100, 100);
  ControlStyle := ControlStyle + [csOpaque];
  FActive := False;
end;

destructor TCoolTransparentArea.Destroy;
begin
  FPolygones.Free;
  inherited Destroy;
end;

procedure TCoolTransparentArea.SetActive(Value: Boolean);
var
  I: Integer;
begin
  if FActive <> Value then
  begin
    FActive := Value;
    ApplyPolygones;
  end;

  if Parent <> nil then
  begin
    for I := 0 to Pred(Parent.ControlCount) do
      if (Parent.Controls[I] is TCoolTransparentArea) and (Parent.Controls[I] <> Self) then
        TCoolTransparentArea(Parent.Controls[I]).ApplyPolygones;
  end;
end;

procedure TCoolTransparentArea.SetPolygones(Value: TPolygones);
begin
  FPolygones.Assign(Value);
  Active := False;
end;

function TCoolTransparentArea.GetHandle: THandle;
begin
  Result := 0;
  if Assigned(Parent) and Parent.HandleAllocated then
    Result := Parent.Handle
end;

procedure TCoolTransparentArea.Paint;
var
  R: TRect;
begin
  inherited Paint;
  R := ClientRect;

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

procedure TCoolTransparentArea.SetPolyRegiones;
var
  PointsArray: array [0..MaxWord] of TPoint;
  Verteces: array [0..MaxWord] of Integer;
  WindowRgn, Rgn: HRGN;
  I,K,N: Integer;
begin
  if FPolygones.Count <> 0 then
  begin
    N := 0;
    for I := 0 to Pred(FPolygones.Count) do
    begin
      Verteces[I] := FPolygones[I].Points.Count;
      for K := 0 to Pred(FPolygones[I].Points.Count) do
      begin
        PointsArray[N + K] := FPolygones[I].Points[K];
      end;
      N := N + Verteces[I];
    end;

    if Handle <> 0 then
    begin
      WindowRgn := CreateRectRgn(0, 0, Parent.Width, Parent.Height);
      GetWindowRgn(Handle, WindowRgn);

      Rgn := CreatePolyPolygonRgn(PointsArray, Verteces, FPolygones.Count, ALTERNATE);
      OffsetRgn(Rgn, Left + (Parent.Width - Parent.ClientWidth), Top + (Parent.Height - Parent.ClientHeight));

      CombineRgn(WindowRgn, WindowRgn, Rgn, RGN_DIFF);
      SetWindowRgn(Handle, WindowRgn, True);

      DeleteObject(Rgn);
      DeleteObject(WindowRgn);
    end;
  end;
end;

procedure TCoolTransparentArea.ApplyPolygones;
begin
  if FActive then
    SetPolyRegiones else
      SetWindowRgn(Handle, 0, True);
end;

procedure TCoolTransparentArea.Loaded;
begin
  inherited Loaded;
  ApplyPolygones;
end;

{TSearchFileThread}
constructor TSearchFileThread.Create(AFileName, AStringToSearch: string; ACaseSensitive: Boolean);
begin
  inherited Create(True);
  FStringToSearch := AStringToSearch ;
  FFileName := AFileName;
  FStringFound := False ;
  FCaseSensitive := ACaseSensitive;

  FreeOnTerminate := False;
  Priority := tpLowest;
end;

//We read file content and fill the string. Then we
//just use Pos() function.
function TSearchFileThread.IsStringFound: Boolean;
var
  FileHandle: THandle;
  FileSize: Integer;
  SearchString: string;
begin
  FileHandle := FileOpen(FFileName, fmOpenRead or fmShareDenyWrite);

  if FileHandle <> 0 then
  try
    FileSize := GetFileSize(FileHandle, nil);
    SetLength(SearchString, FileSize);
    FileRead(FileHandle, Pointer(SearchString)^, FileSize);
  finally
    CloseHandle(FileHandle);
  end;

  if not FCaseSensitive then
    Result := Pos(UpperCase(FStringToSearch), UpperCase(SearchString)) <> 0 else
    Result := Pos(FStringToSearch, SearchString) <> 0;
end;

procedure TSearchFileThread.Execute;
begin
  if Assigned(FOnStartProcess) then
    FOnStartProcess(Self);

  FStringFound := IsStringFound;
  Terminate;

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

{TSearchFolderThread}
constructor TSearchFolderThread.Create(AFolderName, AFileMask, AStringToSearch: string; ACaseSensitive: Boolean; ASearchScope: TSearchScope; AFileNamesOnly: Boolean);
begin
  inherited Create(True);
  FFolderName :=  AFolderName;
  FFileMask := AFileMask;
  FStringToSearch := AStringToSearch;
  FCaseSensitive := ACaseSensitive;
  FSearchScope := ASearchScope;
  FFileNamesOnly := AFileNamesOnly;

  FValidFiles := TStringList.Create;

  FreeOnTerminate := False;
  Priority := tpLowest;
end;

destructor TSearchFolderThread.Destroy;
begin
  FValidFiles.Free;
  inherited Destroy;
end;

function DirectoryExistsEx(FolderName: string): Boolean;
begin
  Result := (Pos('.', FolderName) = 0) and DirectoryExists(FolderName);
end;

function TSearchFolderThread.IsStringFound(FileName: string): Boolean;
var
  FileHandle: THandle;
  FileSize: Integer;
  SearchString: string;
begin
  FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyNone);

  if FileHandle <> 0 then
  try
    FileSize := GetFileSize(FileHandle, nil);
    SetLength(SearchString, FileSize);
    FileRead(FileHandle, Pointer(SearchString)^, FileSize);
  finally
    CloseHandle(FileHandle);
  end;

  if not FCaseSensitive then
    Result := Pos(UpperCase(FStringToSearch), UpperCase(SearchString)) <> 0 else
    Result := Pos(FStringToSearch, SearchString) <> 0;
end;

procedure TSearchFolderThread.ProcessFolder(DirName: string);
var
  ARec: TSearchRec;
  Res: Integer;
begin
  if DirName[Length(DirName)] <> '\' then
    DirName := DirName + '\';

  Res := FindFirst(DirName + FFileMask, faAnyFile, ARec);
  while (Res = 0) and not Terminated and not Application.Terminated do
  begin
    Application.ProcessMessages;
    if FileExists(DirName + ARec.Name) then
    begin
      if Assigned(FOnFileProcess) then
        FOnFileProcess(Self, DirName + ARec.Name);

      if FFileNamesOnly then
      begin
        if Assigned(FOnFileFound) then
          FOnFileFound(Self, DirName + ARec.Name);

        FValidFiles.Add(DirName + ARec.Name);
      end else
      begin
        if IsStringFound(DirName + ARec.Name) then
        begin
          if Assigned(FOnFileFound) then
            FOnFileFound(Self, DirName + ARec.Name);

          FValidFiles.Add(DirName + ARec.Name);
        end;
      end;
    end;
    Res := FindNext(ARec);
  end;
  FindClose(ARec);

  Res := FindFirst(DirName + '*.*', faDirectory, ARec);
  while (Res = 0) and not Terminated and not Application.Terminated do
  begin
    Application.ProcessMessages;
    if DirectoryExistsEx(DirName + ARec.Name) and (FSearchScope = ssIncludeSubFolders) then
    begin
      if Assigned(FOnFolderProcess) then
        FOnFolderProcess(Self, DirName + ARec.Name);

      ProcessFolder(DirName + ARec.Name);
    end;
    Res := FindNext(ARec);
  end;
  FindClose(ARec);
end;

procedure TSearchFolderThread.Execute;
begin
  if Assigned(FOnStartProcess) then
    FOnStartProcess(Self);

  ProcessFolder(FFolderName);

  Terminate;

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

{TCoolFileFinder}
constructor TCoolFileFinder.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FStringToSearch := '';
  FFolderName := '';
  FFileMask := '';
  FCaseSensitive := False;
  FSearchScope := ssCurrentFolderOnly;;
  FFileNamesOnly := False;
end;

destructor TCoolFileFinder.Destroy;
begin
  inherited Destroy;
end;

function TCoolFileFinder.Execute(WaitForEnd: Boolean): Boolean;
var
  SFT: TSearchFolderThread;
begin
  Result := True;
  try
    SFT := TSearchFolderThread.Create(FFolderName, FFileMask, FStringToSearch, FCaseSensitive, FSearchScope, FFileNamesOnly);
    SFT.FOnFileProcess := FOnFileProcess;
    SFT.FOnFolderProcess := FOnFolderProcess;
    SFT.FOnFileFound := FOnFileFound;
    SFT.FOnStartProcess := FOnStartProcess;
    SFT.FOnEndProcess := FOnEndProcess;
    SFT.Resume;

    if WaitForEnd then
    begin
      while not SFT.Terminated and not Application.Terminated do
        Application.ProcessMessages;

      SFT.Free;
    end else
    begin
      SFT.FreeOnTerminate := True;
    end;
  except
    Result := False;
  end;
end;

end.
