unit sSkinProvider;
{$I sDefs.inc}
{.$DEFINE LOGGED}
{.$DEFINE TESTBGCHANGED}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Forms, Dialogs, sDefaults, menus, sSkinMenus, sSkinManager, acPNG, ExtCtrls, acGlow, Buttons,
  sConst, sCommondata, Controls, acSBUtils{$IFDEF TNTUNICODE}, TntWideStrUtils, TntMenus, TntStdCtrls{$ENDIF};

type
{$IFNDEF NOTFORHELP}
  TacGraphItem = class(TPersistent)
  public
    Ctrl : TControl;
    SkinData : TsCommonData;
    Adapter : TObject;
    Handler : TacSpeedButtonHandler;
    constructor Create; virtual;
    destructor Destroy; override;
    procedure DoHook(Control : TControl); virtual;
  end;

  TacAdapterItem = class(TPersistent)
  public
    WinCtrl : TWinControl;
    SkinData : TsCommonData;
    OldFontColor : integer;
    Adapter : TObject;
    ScrollWnd : TacMainWnd;
    constructor Create; virtual;
    destructor Destroy; override;
    procedure DoHook(Control : TWinControl); virtual;
  end;
{$ENDIF} // NOTFORHELP

  TAddItemEvent = procedure(Item: TComponent; var CanBeAdded: boolean; var SkinSection: string) of object;
  TsSkinProvider = class;
{$IFNDEF NOTFORHELP}
  TacBorderForm = class;
  TacSBAnimation = class;
{$ENDIF}

  TsGripMode = (gmNone, gmRightBottom);
  TsResizeMode = (rmStandard, rmBorder);

{$IFNDEF NOTFORHELP}
  TsSystemMenu = class;
  TsCaptionButton = record
    State : integer;
    ImageIndex : integer;
    Rect : TRect;
    HaveAlignment : boolean;
    GlowID : integer;
    Timer : TacSBAnimation;
    HitCode : Cardinal;
  end;

  PsCaptionButton = ^TsCaptionButton;
{$ENDIF} // NOTFORHELP

  TsTitleButton = class(TCollectionItem)
{$IFNDEF NOTFORHELP}
  private
    FUseSkinData: boolean;
    FName: string;
    FGlyph: TBitmap;
    FOnMouseUp: TMouseEvent;
    FOnMouseDown: TMouseEvent;
    FEnabled: boolean;
    FHint: string;
    procedure SetGlyph(const Value: TBitmap);
    procedure SetName(const Value: string);
    procedure MouseDown(BtnIndex : integer; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure MouseUp(BtnIndex : integer; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  public
    HintWnd : THintWindow;
    BtnData : TsCaptionButton;
    procedure AssignTo(Dest: TPersistent); override;
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    function GetDisplayName: string; override;
  published
{$ENDIF} // NOTFORHELP
    property Enabled : boolean read FEnabled write FEnabled default True;
    property Glyph : TBitmap read FGlyph write SetGlyph;
    property Hint : string read FHint write FHint;
    property Name : string read FName write SetName;
    property UseSkinData : boolean read FUseSkinData write FUseSkinData default True;
    property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
    property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;
  end;

  TsTitleButtons = class(TCollection)
{$IFNDEF NOTFORHELP}
  private
    FOwner: TsSkinProvider;
    function GetItem(Index: Integer): TsTitleButton;
    procedure SetItem(Index: Integer; Value: TsTitleButton);
  protected
    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create(AOwner: TsSkinProvider);
    destructor Destroy; override;
{$ENDIF} // NOTFORHELP
    property Items[Index: Integer]: TsTitleButton read GetItem write SetItem; default;
  end;

  TsTitleIcon = class (TPersistent)
{$IFNDEF NOTFORHELP}
  private
    FGlyph: TBitmap;
    FHeight: integer;
    FWidth: integer;
    procedure SetGlyph(const Value: TBitmap);
    procedure SetHeight(const Value: integer);
    procedure SetWidth(const Value: integer);
  public
    constructor Create;
    destructor Destroy; override;
  published
{$ENDIF} // NOTFORHELP
    property Glyph : TBitmap read FGlyph write SetGlyph;
    property Height : integer read FHeight write SetHeight default 0;
    property Width : integer read FWidth write SetWidth default 0;
  end;

  TsSkinProvider = class(TComponent)
{$IFNDEF NOTFORHELP}
  private
    ArOR : TAOR;
    RgnChanged : boolean;
    CurrentHT : integer;
    TempBmp : TBitmap;

    FMakeSkinMenu: boolean;
    FShowAppIcon: boolean;
    ControlsChanged : boolean;
    HaveSysMenu : boolean;

    FCaptionAlignment: TAlignment;
    FTitleIcon: TsTitleIcon;
    FTitleButtons: TsTitleButtons;
    FGripMode: TsGripMode;
    FCommonData: TsCommonData;
    FResizeMode: TsResizeMode;
    FirstInitialized : boolean;
    FScreenSnap: boolean;
    FSnapBuffer: integer;
    FUseGlobalColor: boolean;
    FTitleSkin: TsSkinSection;
    FMenuLineSkin: TsSkinSection;
    UserBtnIndex : integer;
    FOnSkinItem: TAddItemEvent;
    FDrawNonClientArea: boolean;
    FAllowExtBorders: boolean;

    procedure SetCaptionAlignment(const Value: TAlignment);
    procedure SetShowAppIcon(const Value: boolean);
    procedure SetTitleButtons(const Value: TsTitleButtons);
    procedure SetUseGlobalColor(const Value: boolean);
    function GetLinesCount : integer; // Returns a count of menu lines
    procedure SetTitleSkin(const Value: TsSkinSection);
    procedure SetMenuLineSkin(const Value: TsSkinSection);
    procedure SetDrawNonClientArea(const Value: boolean);
    procedure SetAllowExtBorders(const Value: boolean);
  protected
    LockCount : integer;
    ClearButtons : boolean;
    MenusInitialized : boolean;
    RegionChanged : boolean;
    CaptChanged : boolean;
    CaptRgnChanged : boolean;

    ButtonMin : TsCaptionButton;
    ButtonMax : TsCaptionButton;
    ButtonClose : TsCaptionButton;
    ButtonHelp : TsCaptionButton;
    MDIMin : TsCaptionButton;
    MDIMax : TsCaptionButton;
    MDIClose : TsCaptionButton;

    LastClientRect : TRect;
    FSysExHeight : boolean;

    procedure AssignTo(Dest: TPersistent); override;
    procedure AdapterRemove;
    procedure AdapterCreate; virtual;
    procedure SendToAdapter(Message : TMessage);
    // Painting procedures <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    procedure PaintAll;
    procedure PaintForm(DC : hdc; SendUpdated : boolean = True);
    procedure PaintCaption(dc : hdc);
    procedure PrepareCaption(CI : TCacheInfo; R : TRect);
    procedure PaintBorderIcons;
    procedure RepaintButton(i : integer);
    procedure RepaintMenuItem(mi : TMenuItem; R : TRect; State : TOwnerDrawState);
    procedure MakeTitleBG;
    procedure SaveBGForBtns(Full : boolean = False);
    procedure RestoreBtnsBG;

    procedure OurPaintHandler(const Msg : TWMPaint);
    procedure AC_WMEraseBkGnd(const aDC: hdc);
    procedure AC_WMNCPaint;
    procedure AC_WMNCCalcSize(var Message : TWMNCCalcSize);
    procedure AC_WMGetMinMaxInfo(var Message : TWMGetMinMaxInfo);

//    procedure AC_WMDrawItem(var Message : TWMDrawItem);
    procedure AC_WMInitMenuPopup(var Message : TWMInitMenuPopup);
//    procedure AC_WMWindowPosChanged(const Msg : TWMWindowPosMsg);

    // Special calculations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    function HTProcess(var Message : TWMNCHitTest) : integer;
    function CursorToPoint(x, y : integer) : TPoint;
    function MDIButtonsNeeded : boolean;
    function RBGripPoint(ImgIndex : integer) : TPoint;
    function IconRect : TRect;
    function FormLeftTop : TPoint;
    function SysButtonsCount : integer;
    function SmallButtonWidth : integer;
    function ButtonHeight : integer;
    function SmallButtonHeight : integer;

    function SysButtonWidth(Btn : TsCaptionButton) : integer;
    function TitleBtnsWidth : integer;
    function UserButtonWidth(Btn : TsTitleButton) : integer;
    function BarWidth(i : integer) : integer;
    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    procedure KillAnimations;
    procedure UpdateIconsIndexes;

    procedure StartMove(X, Y: Integer);                             // MarkB
    procedure StopMove(X, Y: Integer);                              // MarkB
    procedure DrawFormBorder(X, Y: Integer);                        // MarkB

    procedure SetHotHT(i : integer; Repaint : boolean = True);
    procedure SetPressedHT(i : integer);

    function FormChanged : boolean;
    function IconVisible : boolean;
    function TitleSkinSection : string;
    procedure CheckSysMenu(const Skinned : boolean);
    procedure InitExBorders(const Active : boolean);
  public
    AeroInvalidate : boolean;
    InMenu : boolean;
    FInAnimation : boolean;
    ShowAction : TShowAction;

    fAnimating : boolean;
    ListSW : TacScrollWnd;
    Adapter : TObject;

    RgnChanging : boolean;

    MenuChanged : boolean;
    OldWndProc: TWndMethod;
    MDIForm : TObject;
    FormActive : boolean;

    MenuLineBmp : TBitmap;

    Form : TForm;
    FLinesCount : integer;
    SystemMenu : TsSystemMenu;
    TitleBG : TBitmap;
    CaptForm : TForm;
    OldCaptFormProc : TWndMethod;
    BorderForm : TacBorderForm;

    constructor Create(AOwner : TComponent); override;
    procedure DropSysMenu(x, y : integer);
    destructor Destroy; override;
    procedure AfterConstruction; override;
    procedure Loaded; override;
    procedure PrepareForm;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;

    function OffsetX : integer;
    function OffsetY : integer;
    function ShadowSize : TRect;

    procedure NewWndProc(var Message: TMessage); // Main window procedure hook
    procedure DsgnWndProc(var Message: TMessage); // Main window procedure hook for design-time
    procedure HookMDI(Active : boolean = True);
    function HeaderHeight : integer;  // Height of the header + menu lines
    function BorderHeight(CheckSkin : boolean = True): integer;
    function BorderWidth(CheckSkin : boolean = True): integer;
    function CaptionHeight(CheckSkin : boolean = True) : integer;
    function CaptionWidth : integer;
    function MenuHeight : integer;
    function MenuPresent : boolean;
    function FormColor : TColor;

//    procedure StartSBAnimation(const Btn : PsCaptionButton; const State : integer; const Iterations : integer; const ToUp : boolean);
    procedure MdiIcoFormPaint(Sender : TObject);
    procedure CaptFormPaint(Sender : TObject);
    procedure NewCaptFormProc(var Message: TMessage);


    function UpdateMenu : boolean;
    procedure InitMenuItems(A: boolean);
    procedure RepaintMenu;
    property LinesCount : integer read GetLinesCount;
  published
{$ENDIF} // NOTFORHELP
    property AllowExtBorders : boolean read FAllowExtBorders write SetAllowExtBorders default True;
    property CaptionAlignment : TAlignment read FCaptionAlignment write SetCaptionAlignment default taLeftJustify;
    property DrawNonClientArea : boolean read FDrawNonClientArea write SetDrawNonClientArea default True;
    property SkinData : TsCommonData read FCommonData write FCommonData;
    property GripMode : TsGripMode read FGripMode write FGripMode default gmNone;
    property MakeSkinMenu : boolean read FMakeSkinMenu write FMakeSkinMenu default DefMakeSkinMenu;
    property MenuLineSkin : TsSkinSection read FMenuLineSkin write SetMenuLineSkin;
    property ResizeMode : TsResizeMode read FResizeMode write FResizeMode default rmStandard; // MarkB
    property ScreenSnap : boolean read FScreenSnap write FScreenSnap default False;
    property SnapBuffer : integer read FSnapBuffer write FSnapBuffer default 10;
    property ShowAppIcon : boolean read FShowAppIcon write SetShowAppIcon default True;
    property TitleButtons : TsTitleButtons read FTitleButtons write SetTitleButtons;
    property TitleIcon : TsTitleIcon read FTitleIcon write FTitleIcon;
    property TitleSkin : TsSkinSection read FTitleSkin write SetTitleSkin;
    property UseGlobalColor : boolean read FUseGlobalColor write SetUseGlobalColor default True;
    property OnSkinItem: TAddItemEvent read FOnSkinItem write FOnSkinItem;
  end;

{$IFNDEF NOTFORHELP}

  TacSBAnimation = class(TTimer)
  public
    BorderForm : TacBorderForm;
    SkinData : TsCommonData;
    FormHandle : hwnd;

    PBtnData : PsCaptionButton;
    CurrentLevel : integer;
    CurrentState : integer;
    Up : boolean;
    MaxIterations : integer;
    AForm : TForm;
    ABmp : TBitmap;
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    function GetFormBounds : TRect;
    function Offset : integer;
    function Step : integer;
    procedure MakeForm;
    procedure UpdateForm(const Blend: integer);
    procedure StartAnimation(NewState : integer; ToUp : boolean);
    procedure ChangeState(NewState : integer; ToUp : boolean);
    procedure MakeImg;
    procedure CheckMouseLeave;
    procedure OnAnimTimer(Sender: TObject);
  end;

  TacBorderForm = class(TPersistent)
    FOwner : TObject;
    SkinData : TsCommonData;
  public
    acInMouseMsg : boolean;
    AForm : TForm;
    OldBorderProc: TWndMethod;
    ExBorderShowing : boolean;
    ShadowTemplate : TBitmap;
    constructor Create(AOwner : TObject);
    destructor Destroy; override;
    procedure KillAnimations;
    function OffsetX : integer;
    function OffsetY : integer;

    // Access from owners
    function ButtonMin : TsCaptionButton;
    function ButtonMax : TsCaptionButton;
    function ButtonClose : TsCaptionButton;
    function ButtonHelp : TsCaptionButton;
    function OwnerHandle : hwnd;
    function ShadowSize : TRect;
    function CaptionHeight(CheckSkin : boolean = True) : integer;
    function MenuHeight : integer;
    function IconRect : TRect;
    procedure SetHotHT(const i: integer; Repaint : boolean = True);
    procedure PaintAll;
    function MakeRgn : HRGN;

    function MouseAboveTheShadow(Message : TWMMouse) : boolean;
    procedure BorderProc(var Message : TMessage);
    procedure UpdateExBordersPos(Redraw : boolean = True; Blend : byte = MaxByte);
    function Ex_WMNCHitTest(var Message : TWMNCHitTest) : integer;
    function Ex_WMSetCursor(var Message: TWMSetCursor) : boolean;

    procedure FinishAnimation(const BtnIndex : integer);
  end;

{$IFDEF TNTUNICODE}
  TsCustomSysMenu = class(TTntPopupMenu)
{$ELSE}
  TsCustomSysMenu = class(TPopupMenu)
{$ENDIF}
    function VisibleClose : boolean; virtual; abstract;
    function VisibleMax : boolean; virtual; abstract;
    function VisibleMin : boolean; virtual; abstract;

    function EnabledMax : boolean; virtual; abstract;
    function EnabledMin : boolean; virtual; abstract;
    function EnabledRestore : boolean; virtual; abstract;
  end;

  TsSystemMenu = class(TsCustomSysMenu)
  public
    ExtItemsCount : integer;
    FOwner : TsSkinProvider;
    FForm : TCustomForm;
    ItemRestore : TMenuItem;
    ItemMove : TMenuItem;
    ItemSize : TMenuItem;
    ItemMinimize : TMenuItem;
    ItemMaximize : TMenuItem;
    ItemClose : TMenuItem;

    constructor Create(AOwner : TComponent); override;
    procedure Generate;
    procedure UpdateItems(Full : boolean = False);
    procedure UpdateGlyphs;
    procedure MakeSkinItems;

    function VisibleRestore : boolean;
    function VisibleSize : boolean;
    function VisibleMin : boolean; override;
    function VisibleMax : boolean; override;
    function VisibleClose : boolean; override;

    function EnabledRestore : boolean; override;
    function EnabledMove    : boolean;
    function EnabledSize    : boolean;
    function EnabledMin     : boolean; override;
    function EnabledMax     : boolean; override;

    procedure RestoreClick(Sender: TObject);
    procedure MoveClick(Sender: TObject);
    procedure SizeClick(Sender: TObject);
    procedure MinClick(Sender: TObject);
    procedure MaxClick(Sender: TObject);
    procedure CloseClick(Sender: TObject);
    procedure SkinSelect(Sender: TObject);
    procedure ExtClick(Sender: TObject);
  end;

{$IFNDEF NOTFORHELP}
  TacAdapterItems = array of TacAdapterItem;
  TacGraphItems = array of TacGraphItem;
{$ENDIF}

  TacCtrlAdapter = class(TPersistent)
{$IFNDEF NOTFORHELP}
  public
    CtrlClass : TsCtrlClass;
    DefaultSection : string;
    Items : TacAdapterItems;
    GraphItems : TacGraphItems;
    Provider : TsSkinProvider;
    function IsControlSupported(Control : TComponent) : boolean; virtual;
    function Count : integer;
    constructor Create(AProvider: TsSkinProvider);
    destructor Destroy; override;
    function GetItem(Index : integer) : TacAdapterItem; virtual;
    function GetCommonData(Index : integer) : TsCommonData; virtual;
    function IndexOf(Ctrl : TWinControl) : integer;
    procedure AfterConstruction; override;
{$ENDIF} // NOTFORHELP
    procedure AddAllItems(OwnerCtrl : TWinControl = nil);// CheckHandle : boolean = True);
    procedure AddNewItem(const Ctrl : TSpeedButton); overload; virtual;
    procedure AddNewItem(const Ctrl : TWinControl); overload; virtual;
    procedure AddNewItem(const Ctrl : TWinControl; const SkinSection : string); overload; virtual;
    procedure RemoveItem(Index : integer); virtual;
    procedure RemoveAllItems;
    procedure CleanItems;
    procedure WndProc(var Message: TMessage); virtual;
  end;

const
  UserButtonsOffset = 8;
  ScrollWidth = 18;
  IconicHeight = 26;
  HTUDBTN = 1000;

var
  acM : TMessage;
  Style : LongInt;
  HotItem : TMenuItemData;
  SelectedMenuItem : TMenuItem;
{$IFDEF TESTBGCHANGED}  
  iTestCount : integer = 0; // Used for testing of form cache
{$ENDIF}
{$IFNDEF ALITE}
  acTaskBarChanging : boolean = False;
{$ENDIF}

  bInProcess  : boolean = False;
  DoStartMove : boolean = False;
  bCapture    : Boolean = False;
  bFlag       : boolean = False;
  bRemoving   : boolean = False;
  bMode       : Boolean; // True - move, False - size
  deskwnd     : HWND;
  formDC      : HDC;
  ntop, nleft, nbottom, nright, nX, nY, nDirection, nMinHeight, nMinWidth, nDC : Integer;

  hDWMAPI: HMODULE = 0;

function AeroIsEnabled : boolean;
//function UseAero : boolean;
procedure InitDwmApi;
procedure InitDwm(const Handle : THandle; const Skinned : boolean; const Repaint : boolean = False);
function BigButtons(sp : TsSkinProvider) : boolean;
function IsBorderUnchanged(const BorderIndex : integer; const sm : TsSkinManager) : boolean;
function IsGripVisible(const sp : TsSkinProvider) : boolean;
function InAnimation(const sp : TsSkinProvider) : boolean;
procedure PaintGrip(const aDC : hdc; const sp : TsSkinProvider);
function CtrlIsReadyForHook(const Ctrl : TWinControl) : boolean;
procedure UpdateRgn(sp : TsSkinProvider; Repaint : boolean = True);
procedure FillArOR(sp : TsSkinProvider);
function GetRgnFromArOR(sp : TsSkinProvider; X : integer = 0; Y : integer = 0) : hrgn;
procedure UpdateSkinCaption(SkinProvider : TsSkinProvider);
function GetSkinProvider(Cmp : TComponent) : TsSkinProvider;
procedure DrawAppIcon(SkinProvider : TsSkinProvider);
function GetWindowWidth(Handle : hwnd) : integer;
function GetClientWidth(Handle : hwnd) : integer;
function GetWindowHeight(Handle : hwnd) : integer;
function GetClientHeight(Handle : hwnd) : integer;
procedure ForbidDrawing(sp : TsSkinProvider; MDIAlso : boolean = False);
procedure PermitDrawing(sp : TsSkinProvider; MDIAlso : boolean = False);
function HaveBorder(sp : TsSkinProvider) : boolean;
procedure UpdateMainForm(UpdateNow : boolean = True);

function SkinMenuOffset(const sp : TsSkinProvider) : TPoint;
function SkinTitleHeight(const BorderForm : TacBorderForm) : integer;
function SkinBorderWidth(const BorderForm : TacBorderForm) : integer;
function DiffTitle(const BorderForm : TacBorderForm) : integer;
function DiffBorder(const BorderForm : TacBorderForm) : integer;
function SysBorderWidth(const Handle : hwnd; const BorderForm : TacBorderForm; CheckSkin : boolean = True): integer;
function SysBorderHeight(const Handle : hwnd; const BorderForm : TacBorderForm; CheckSkin : boolean = True): integer;
//procedure CheckDefShadows(const SkinManager : TsSkinManager; const Required : boolean);

procedure StartSBAnimation(const Btn: PsCaptionButton; const State: integer; const Iterations : integer; const ToUp : boolean; const SkinProvider : TsSkinProvider; acDialog : pointer = nil);

{$ENDIF} // NOTFORHELP

implementation

uses math, sVclUtils, sBorders, sGraphUtils, sSkinProps, sGradient, sLabel, FlatSB, StdCtrls,
  sMaskData, acntUtils, sMessages, sStyleSimply, sStrings, {$IFDEF LOGGED} sDebugMsgs,{$ENDIF}
  sMDIForm{$IFDEF CHECKXP}, UxTheme, Themes{$ENDIF}, sAlphaGraph, ComCtrls, Grids, acDials,
  sSpeedButton, CommCtrl{$IFNDEF ALITE}, sFrameAdapter{$ENDIF};

var
  biClicked : boolean = False;
  MDICreating : boolean = False;
  ChildProvider : TsSkinProvider = nil;
  MDIIconsForm : TForm = nil;

_DwmSetWindowAttribute: function(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HResult; stdcall;
_DwmIsCompositionEnabled: function (out pfEnabled: BOOL): HResult; stdcall;

const
  ModName = 'DWMAPI.DLL';

procedure StartSBAnimation(const Btn: PsCaptionButton; const State: integer; const Iterations : integer; const ToUp : boolean; const SkinProvider : TsSkinProvider; acDialog : pointer = nil);
begin
  if Btn^.Timer = nil then begin
    if SkinProvider <> nil then begin
      Btn^.Timer := TacSBAnimation.Create(SkinProvider);
      Btn^.Timer.BorderForm := SkinProvider.BorderForm;
      Btn^.Timer.FormHandle := SkinProvider.Form.Handle;
      Btn^.Timer.SkinData := SkinProvider.SkinData;
    end
    else
    if acDialog <> nil then with TacDialogWnd(acDialog) do begin
      Btn^.Timer := TacSBAnimation.Create(Application);
      Btn^.Timer.BorderForm := BorderForm;
      Btn^.Timer.FormHandle := CtrlHandle;
      Btn^.Timer.SkinData := SkinData;
    end
    else Exit;
    Btn^.Timer.Enabled := False;
    Btn^.Timer.PBtnData := Btn;
    Btn^.Timer.MaxIterations := Iterations;
    Btn^.Timer.Interval := 12;
    Application.ProcessMessages; // 'No timers available' fix
    Btn^.Timer.StartAnimation(State, True);
  end
  else begin
    if ToUp then Btn^.Timer.CurrentState := State;
    Btn^.Timer.MaxIterations := Iterations;
    Btn^.Timer.Up := ToUp;
    Btn^.Timer.Enabled := True;
    if State = 2 then begin
      Btn^.Timer.CurrentLevel := Iterations;
      FreeAndNil(Btn^.Timer.ABmp);
      FreeAndNil(Btn^.Timer.AForm);
      Btn^.Timer.MakeForm;
      Btn^.Timer.MakeImg;
    end;
  end;
end;

function SysBorderWidth(const Handle : hwnd; const BorderForm : TacBorderForm; CheckSkin : boolean = True): integer;
var
  Style : Longint;
begin
  Result := 0;
  if CheckSkin then Result := SkinBorderWidth(BorderForm);
  if Result = 0 then begin
    Style := GetWindowLong(Handle, GWL_STYLE);
    if (Style and WS_THICKFRAME = WS_THICKFRAME) then Result := GetSystemMetrics(SM_CXSIZEFRAME) else if (Style and WS_BORDER = WS_BORDER) then Result := GetSystemMetrics(SM_CXFIXEDFRAME);
  end
end;

function SysBorderHeight(const Handle : hwnd; const BorderForm : TacBorderForm; CheckSkin : boolean = True): integer;
begin
  Result := 0;
  if BorderForm = nil {Used in caption only when borders are std} then Result := SysBorderWidth(Handle, BorderForm, CheckSkin);
end;

function HaveDefShadow(const sp : TsSkinProvider) : boolean;
begin
  Result := True;
end;

function SkinTitleHeight(const BorderForm : TacBorderForm) : integer;
begin
  if BorderForm <> nil then begin
    Result := BorderForm.SkinData.SkinManager.SkinData.ExTitleHeight;
  end
  else Result := 0;
end;

function SkinBorderWidth(const BorderForm : TacBorderForm) : integer;
begin
  if BorderForm <> nil then Result := BorderForm.SkinData.SkinManager.SkinData.ExBorderWidth else Result := 0;
end;

function SkinMenuOffset(const sp : TsSkinProvider) : TPoint;
begin
  if sp.BorderForm <> nil then begin
    Result.Y := sp.CaptionHeight - sp.CaptionHeight(False) + SysBorderHeight(sp.Form.Handle, sp.BorderForm) - SysBorderHeight(sp.Form.Handle, sp.BorderForm, False);
    Result.X := SysBorderWidth(sp.Form.Handle, sp.BorderForm) - SysBorderWidth(sp.Form.Handle, sp.BorderForm, False);
  end
  else begin
    Result := Point(0, 0);
  end;
end;

function DiffTitle(const BorderForm : TacBorderForm) : integer;
begin
  if BorderForm <> nil then begin
    Result := BorderForm.CaptionHeight - BorderForm.CaptionHeight(False) - SysBorderWidth(BorderForm.OwnerHandle, BorderForm, False)
  end
  else Result := 0;
end;

function DiffBorder(const BorderForm : TacBorderForm) : integer;
var
  i, j : integer;
begin
  if BorderForm <> nil then begin
    i := SysBorderWidth(BorderForm.OwnerHandle, BorderForm);
    j := SysBorderWidth(BorderForm.OwnerHandle, BorderForm, False);
    Result := i - j
  end
  else Result := 0;
end;

procedure InitDwmApi;
begin
  if hDWMAPI = 0 then hDWMAPI := LoadLibrary(ModName);
end;

function DwmSetWindowAttribute(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HResult;
begin
  if Assigned(_DwmSetWindowAttribute) then Result := _DwmSetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute) else begin
    InitDwmApi;
    Result := E_NOTIMPL;
    if hDWMAPI > 0 then begin
      _DwmSetWindowAttribute := GetProcAddress(hDWMAPI, 'DwmSetWindowAttribute');
      if Assigned(_DwmSetWindowAttribute) then
        Result := _DwmSetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute);
    end;
  end;
end;

function AeroIsEnabled : boolean;
var
  b : Longbool;
begin
  Result := False;
  if (Win32MajorVersion >= 6) then begin
    b := False;
    if Assigned(_DwmIsCompositionEnabled) then Result := _DwmIsCompositionEnabled(b) = S_OK else begin
      InitDwmApi;
      if hDWMAPI > 0 then begin
        _DwmIsCompositionEnabled := GetProcAddress(hDWMAPI, 'DwmIsCompositionEnabled');
        if Assigned(_DwmIsCompositionEnabled) then Result := _DwmIsCompositionEnabled(b) = S_OK;
      end
    end;
  end;
  Result := Result and b;
end;

procedure InitDwm(const Handle : THandle; const Skinned : boolean; const Repaint : boolean = False);
var
  Policy : Longint;
begin
  if AeroIsEnabled then begin
    if Skinned then begin
      Policy := 1; // DWMNCRP_DISABLED
      DwmSetWindowAttribute(Handle, 3{DWMWA_TRANSITIONS_FORCEDISABLED}, @Policy, Sizeof(Policy));
//      Policy := 1; // DWMNCRP_DISABLED
//      DwmSetWindowAttribute(Handle, 2{DWMWA_NCRENDERING_POLICY}, @Policy, Sizeof(Policy));
    end
    else begin
      Policy := 0; // DWMNCRP_USEWINDOWSTYLE
      DwmSetWindowAttribute(Handle, 3{DWMWA_TRANSITIONS_FORCEDISABLED}, @Policy, Sizeof(Policy));
//      Policy := 2; // DWMNCRP_ENABLED
//      DwmSetWindowAttribute(Handle, 2{DWMWA_NCRENDERING_POLICY}, @Policy, Sizeof(Policy));
    end;
  end
end;

function BigButtons(sp : TsSkinProvider) : boolean;
begin
  Result := sp.Form.BorderStyle in [bsSingle, bsSizeable]
end;

function IsBorderUnchanged(const BorderIndex : integer; const sm : TsSkinManager) : boolean;
begin
  Result := (BorderIndex < 0) or (sm.ma[BorderIndex].ImageCount = 1)
end;

function IsGripVisible(const sp : TsSkinProvider) : boolean;
begin
  Result := (sp.GripMode = gmRightBottom) and (sp.Form.WindowState <> wsMaximized) and (GetWindowLong(sp.Form.Handle, GWL_STYLE) and WS_SIZEBOX = WS_SIZEBOX)
end;

function InAnimation(const sp : TsSkinProvider) : boolean;
begin
  Result := sp.FInAnimation; // Will be changed later for optimizing
end;

procedure PaintGrip(const aDC : hdc; const sp : TsSkinProvider);
var
  i, w1, w2, dx, h1, h2, dy : integer;
  Bmp : TBitmap;
  p : TPoint;
  BG : TacBGInfo;
begin
  i := sp.FCommonData.SkinManager.GetMaskIndex(sp.FCommonData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_GripImage);
  if sp.FCommonData.SkinManager.IsValidImgIndex(i) then begin
    Bmp := CreateBmp24(WidthOfImage(sp.FCommonData.SkinManager.ma[i]), HeightOfImage(sp.FCommonData.SkinManager.ma[i]));
    p := sp.RBGripPoint(i);
    BG.R := Rect(0, 0, Bmp.Width, Bmp.Height);
    BG.PleaseDraw := False;
    sp.FCommonData.FCacheBmp.Canvas.Lock;
    GetBGInfo(@BG, sp.Form);
    if BG.BgType = btFill then begin
      FillDC(Bmp.Canvas.Handle, BG.R, BG.Color);
      w1 := sp.SkinData.SkinManager.MaskWidthRight(sp.SkinData.BorderIndex);
      h1 := sp.SkinData.SkinManager.MaskWidthBottom(sp.SkinData.BorderIndex);
      w2 := SysBorderWidth(sp.Form.Handle, sp.BorderForm);
      h2 := w2;
      dx := w1 - w2;
      dy := h1 - h2;
      if (dx > 0) and (dy > 0) then
        // Right border
        BitBlt(Bmp.Canvas.Handle, Bmp.Width - dx, 0, dx, Bmp.Height,
          sp.SkinData.FCacheBmp.Canvas.Handle, sp.SkinData.FCacheBmp.Width - w1 - sp.ShadowSize.Right, sp.SkinData.FCacheBmp.Height - h2 - Bmp.Height - sp.ShadowSize.Bottom, SRCCOPY);
        // Bottom border
        BitBlt(Bmp.Canvas.Handle, 0, Bmp.Height - dy, Bmp.Width, dy,
                     sp.SkinData.FCacheBmp.Canvas.Handle, sp.SkinData.FCacheBmp.Width - w2 - Bmp.Width - sp.ShadowSize.Right, sp.SkinData.FCacheBmp.Height - h1 - sp.ShadowSize.Bottom, SRCCOPY);
    end
    else BitBlt(Bmp.Canvas.Handle, 0, 0, BG.R.Right, BG.R.Bottom,
                     sp.SkinData.FCacheBmp.Canvas.Handle, p.X, p.Y, SRCCOPY);
    sp.FCommonData.FCacheBmp.Canvas.UnLock;
    DrawSkinGlyph(Bmp, Point(0, 0), 0, 1, sp.FCommonData.SkinManager.ma[i], MakeCacheInfo(Bmp));
    BitBlt(aDC, p.X, p.Y, Bmp.Width, Bmp.Height, Bmp.Canvas.Handle, 0, 0, SRCCOPY);

    FreeAndNil(Bmp);
  end;
end;

function CtrlIsReadyForHook(const Ctrl : TWinControl) : boolean;
begin
  Result := Ctrl.HandleAllocated{$IFDEF TNTUNICODE} and Ctrl.Visible and (Ctrl.Parent <> nil){$ENDIF} // Showing is False when Parent changed
end;

procedure MakeCaptForm(sp : TsSkinProvider; Full : boolean = False);
var
  p : TPoint;
  t, h, l, w : integer;
  Flags : Longint;
begin
  if not sp.FDrawNonClientArea or InAnimation(sp) or (sp.LockCount > 0) then Exit;
  if (sp.Form.FormStyle = fsMDIChild) and (TsSkinProvider(MDISkinProvider).LockCount > 0) then Exit;

  if sp.CaptForm = nil then begin
    sp.CaptForm := TForm.Create(Application);
    sp.CaptForm.Tag := ExceptTag;
    sp.CaptForm.OnPaint := sp.CaptFormPaint;
    sp.OldCaptFormProc := sp.CaptForm.WindowProc;
    sp.CaptForm.WindowProc := sp.NewCaptFormProc;
    sp.CaptForm.BorderStyle := bsNone;
  end;
  sp.CaptForm.Visible := False;

  if sp.BorderForm <> nil then begin
    h := sp.MenuHeight * sp.LinesCount;
    t := sp.Form.Top + sp.OffsetY - h - sp.ShadowSize.Top - DiffTitle(sp.BorderForm);
    l := sp.Form.Left + SysBorderWidth(sp.Form.Handle, sp.BorderForm, False);
    w := sp.Form.Width - 2 * SysBorderWidth(sp.Form.Handle, sp.BorderForm, False);
    if h <> 0 then inc(h);
  end
  else begin
    h := iffi(Full, sp.Form.Height, sp.HeaderHeight);
    t := sp.Form.Top;
    l := sp.Form.Left;
    w := sp.Form.Width;
  end;

  Flags := SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOREDRAW or SWP_NOSENDCHANGING or SWP_NOOWNERZORDER;

  if (sp.Form.FormStyle = fsMDIChild) then begin
    p := TsSkinProvider(MDISkinProvider).Form.ClientToScreen(Point(sp.Form.Left + GetAlignShift(TsSkinProvider(MDISkinProvider).Form, alLeft, True) + 2, sp.Form.Top + GetAlignShift(TsSkinProvider(MDISkinProvider).Form, alTop, True) + 2));
    SetWindowPos(sp.CaptForm.Handle, 0, p.x, p.y, sp.Form.Width, sp.HeaderHeight, Flags);
  end
  else begin
    if GetWindowLong(sp.Form.Handle, GWL_EXSTYLE) and WS_EX_TOPMOST = WS_EX_TOPMOST
      then SetWindowPos(sp.CaptForm.Handle, HWND_TOPMOST, l, t, w, h, Flags)
      else SetWindowPos(sp.CaptForm.Handle, GetNextWindow(sp.Form.Handle, GW_HWNDPREV), l, t, w, h, Flags);
  end;
end;

procedure KillCaptForm(sp : TsSkinProvider);
begin
  if sp.CaptForm <> nil then begin
    sp.CaptForm.WindowProc := sp.OldCaptFormProc;
    FreeAndNil(sp.CaptForm);
  end;
end;

procedure FillArOR(sp : TsSkinProvider);
var
  i : integer;
begin
  SetLength(sp.ArOR, 0);
  if sp.SkinData.SkinManager.IsValidImgIndex(sp.SkinData.BorderIndex) then begin
    // TopBorderRgn
    AddRgn(sp.ArOR, sp.CaptionWidth, sp.SkinData.SkinManager.ma[sp.SkinData.BorderIndex], 0, False);
    // BottomBorderRgn
    AddRgn(sp.ArOR, sp.CaptionWidth, sp.SkinData.SkinManager.ma[sp.SkinData.BorderIndex], sp.Form.Height - sp.SkinData.SkinManager.ma[sp.SkinData.BorderIndex].WB, True);
  end;

  // TitleRgn
  i := sp.SkinData.SkinManager.GetSkinIndex(sp.TitleSkinSection);
  if sp.SkinData.SkinManager.IsValidSkinIndex(i) then begin
    i := sp.SkinData.SkinManager.GetMaskIndex(i, sp.TitleSkinSection, s_BordersMask);
    if sp.SkinData.SkinManager.IsValidImgIndex(i) then AddRgn(sp.ArOR, sp.CaptionWidth, sp.SkinData.SkinManager.ma[i], 0, False);
  end;
end;

procedure UpdateRgn(sp : TsSkinProvider; Repaint : boolean = True);
const
  BE_ID = $41A2;
  CM_BEWAIT = CM_BASE + $0C4D;
var
  rgn : HRGN;
  R : TRect;
  sbw, i : integer;
begin
  if sp.DrawNonClientArea and not sp.InMenu and (HaveBorder(sp) or IsIconic(sp.Form.Handle)) then with sp do begin
    if not FirstInitialized then if SendMessage(Form.Handle, CM_BEWAIT, BE_ID, 0) = BE_ID then Exit; // BE compatibility
    if ((sp.Form.Parent = nil) or (TForm(sp.Form).DragKind <> dkDock)) {regions changing disabled when docking used} then begin
      RgnChanging := True;

      if (BorderForm <> nil) {or sp.SkinData.SkinManager.ExtendedBorders} then begin
        sbw := SysBorderWidth(sp.Form.Handle, sp.BorderForm, False);
//        Repaint := True; // ?? Remove later !!!
        if sp.FSysExHeight
          then i := CaptionHeight(False) - 4{SysBorderWidth(sp.Form.Handle, sp.BorderForm, False) }+ SysBorderWidth(sp.Form.Handle, sp.BorderForm, False)
          else i := SysBorderHeight(sp.Form.Handle, sp.BorderForm, False) + CaptionHeight(False) + SysBorderWidth(sp.Form.Handle, sp.BorderForm, False);
        rgn := CreateRectRgn(sbw,
                             i,
                             sp.Form.Width - sbw,
                             sp.Form.Height - sbw);
      end
      else
      if (sp.Form.WindowState = wsMaximized) and (sp.Form.Constraints.MaxWidth = 0) and (sp.Form.Constraints.MaxHeight = 0) and (Form.FormStyle <> fsMDIChild) then begin // v6.02
        R := Rect(0, 0, sp.Form.Width, sp.Form.Height);
        InflateRect(R, - SysBorderWidth(sp.Form.Handle, sp.BorderForm, False), - SysBorderHeight(sp.Form.Handle, sp.BorderForm, False));
        rgn := CreateRectRgn(R.Left, R.Top, R.Right, R.Bottom);
      end
      else rgn := GetRgnFromArOR(sp);
      sp.RgnChanged := True;

      SetWindowRgn(Form.Handle, rgn, Repaint); // True - repainting required

      RgnChanging := False;
    end
    else SetWindowRgn(Form.Handle, 0, False);
  end;
end;

function GetRgnFromArOR(sp : TsSkinProvider; X : integer = 0; Y : integer = 0) : hrgn;
var
  l, i : integer;
  subrgn : HRGN;
begin
  l := Length(sp.ArOR);
  Result := CreateRectRgn(X, Y, sp.CaptionWidth + X, sp.Form.Height + Y);
  if l > 0 then for i := 0 to l - 1 do begin
    subrgn := CreateRectRgn(sp.ArOR[i].Left + X, sp.ArOR[i].Top + Y, sp.ArOR[i].Right + X, sp.ArOR[i].Bottom + Y);
    CombineRgn(Result, Result, subrgn, RGN_DIFF);
    DeleteObject(subrgn);
  end;
end;

procedure RefreshFormScrolls(SkinProvider : TsSkinProvider; var ListSW : TacScrollWnd; Repaint : boolean);
begin
  if not (csDestroying in SkinProvider.ComponentState) and SkinProvider.Form.HandleAllocated and TForm(SkinProvider.Form).AutoScroll {v5.01} then begin
    if SkinProvider.SkinData.Skinned then begin
      UninitializeFlatSB(SkinProvider.Form.Handle);
      if (ListSW <> nil) and ListSW.Destroyed then FreeAndNil(ListSW);
      if ListSW = nil then begin
        ListSW := TacScrollWnd.Create(SkinProvider.Form.Handle, SkinProvider.SkinData, SkinProvider.SkinData.SkinManager, '', False);
      end;
    end
    else begin
      if ListSW <> nil then FreeAndNil(ListSW);
      InitializeFlatSB(SkinProvider.Form.Handle);
    end;
  end;
end;

procedure ForbidDrawing(sp : TsSkinProvider; MDIAlso : boolean = False);
begin
  sp.SkinData.BeginUpdate;
  sp.Form.Perform(WM_SETREDRAW, 0, 0);
  if MDIAlso and (TForm(sp.Form).FormStyle = fsMDIChild) and Assigned(MDISkinProvider) then begin
    TsSkinProvider(MDISkinProvider).SkinData.BeginUpdate;
    TsSkinProvider(MDISkinProvider).Form.Perform(WM_SETREDRAW, 0, 0);
  end;
end;

procedure PermitDrawing(sp : TsSkinProvider; MDIAlso : boolean = False);
begin
  sp.SkinData.EndUpdate;
  sp.Form.Perform(WM_SETREDRAW, 1, 0);
  if MDIAlso and (TForm(sp.Form).FormStyle = fsMDIChild) and Assigned(MDISkinProvider) then begin
    TsSkinProvider(MDISkinProvider).SkinData.EndUpdate;
    TsSkinProvider(MDISkinProvider).Form.Perform(WM_SETREDRAW, 1, 0);
  end;
end;

function HaveBorder(sp : TsSkinProvider) : boolean;
begin
  Result := (sp.Form.BorderStyle <> bsNone) or (TForm(sp.Form).FormStyle = fsMDIChild)
end;

procedure UpdateSkinCaption(SkinProvider : TsSkinProvider);
var
  DC, SavedDC : hdc;
begin
  if InAnimation(SkinProvider) or not SkinProvider.Form.visible then Exit;
  with SkinProvider do
  if (TForm(Form).FormStyle = fsMDIChild) and (Form.WindowState = wsMaximized) then begin
    TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
    DC := GetWindowDC(TsSkinProvider(MDISkinProvider).Form.Handle);
    SavedDC := SaveDC(DC);
    try
      TsSkinProvider(MDISkinProvider).PaintCaption(DC);
    finally
      RestoreDC(DC, SavedDC);
      ReleaseDC(TsSkinProvider(MDISkinProvider).Form.Handle, DC);
    end;
  end
  else if SkinProvider.BorderForm = nil then begin
    FCommonData.BGChanged := True;
    DC := GetWindowDC(Form.Handle);
    SavedDC := SaveDC(DC);
    try
{$IFDEF ACBETATEST}
     if SkinData.FCacheBmp = nil // Preventing of painting before ExBorders, usually when MainMenu exists
       then InitExBorders(SkinData.SkinManager.ExtendedBorders);
{$ENDIF}
      PaintCaption(DC);
    finally
      RestoreDC(DC, SavedDC);
      ReleaseDC(Form.Handle, DC);
    end;
  end
  else begin
    FCommonData.BGChanged := True;
    SkinProvider.BorderForm.UpdateExBordersPos;
  end
end;

function IsSizeBox(Handle : hWnd) : boolean;
var
  Style: LongInt;
begin
  Style := GetWindowLong(Handle, GWL_STYLE);
  Result := Style and WS_SIZEBOX = WS_SIZEBOX;
end;

function GetNearestSize(Max : integer) : integer;
begin
  case Max of
    -100..8 : Result := 1;
    9..16 : Result := 8;
    else Result := 16
{    17..32 : Result := 16
    else Result := 32}
  end;
end;

function GetSkinProvider(Cmp : TComponent) : TsSkinProvider;
var
  c : TComponent;
  sp : integer;
begin
  Result := nil;
  c := Cmp;
  while Assigned(c) and not (c is TCustomForm) do c := c.Owner;
  if (c is TCustomForm) then begin
    sp := SendMessage(TCustomForm(c).Handle, SM_ALPHACMD, MakeWParam(0, AC_GETPROVIDER), 0);
    if sp <> 0 then Result := TsSkinProvider(sp);
  end;
end;

function TitleIconWidth(SP : TsSkinProvider) : integer;
begin
  if SP.IconVisible then begin
    if SP.TitleIcon.Width <> 0 then Result := SP.TitleIcon.Width else Result := GetNearestSize(SP.CaptionHeight);
  end
  else Result := 0;
end;

function TitleIconHeight(SP : TsSkinProvider) : integer;
begin
  if SP.IconVisible then begin
    if SP.TitleIcon.Height <> 0 then Result := SP.TitleIcon.Height else Result := GetNearestSize(SP.CaptionHeight);
  end
  else Result := 0;
end;

procedure DrawAppIcon(SkinProvider : TsSkinProvider);
var
  iW, iH : integer;
  R : TRect;
  Ico : hicon;
begin
  with SkinProvider do if IconVisible then begin
    R := IconRect;
    if not TitleIcon.Glyph.Empty then begin
      TitleIcon.Glyph.Transparent := True;
      TitleIcon.Glyph.TransparentColor := clFuchsia;
      iW := iffi(TitleIcon.Width = 0, GetNearestSize(HeaderHeight - 2), TitleIcon.Width);
      iH := iffi(TitleIcon.Width = 0, GetNearestSize(HeaderHeight - 2), TitleIcon.Height);
      if TitleIcon.Glyph.PixelFormat = pf32bit then begin
        CopyByMask(Rect(R.Left, R.Top, R.Left + TitleIcon.Glyph.Width, R.Left + TitleIcon.Glyph.Height),
                   Rect(0, 0, TitleIcon.Glyph.Width, TitleIcon.Glyph.Height), FCommonData.FCacheBmp, TitleIcon.Glyph, EmptyCI, False);
      end
      else FCommonData.FCacheBmp.Canvas.StretchDraw(Rect(R.Left, R.Top, R.Left + iW, R.Top + iH), TitleIcon.Glyph);
    end
    else if TForm(Form).Icon.Handle <> 0 then begin
      DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, TForm(Form).Icon.Handle, TitleIconWidth(SkinProvider), TitleIconHeight(SkinProvider), 0, 0, DI_NORMAL);
    end
    else if Application.Icon.Handle <> 0 then begin
      Ico := SendMessage(Application.Handle, WM_GETICON, 2 {ICON_SMALL2}, 0);
      if Ico <> 0 then DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, Ico, TitleIconWidth(SkinProvider), TitleIconHeight(SkinProvider), 0, 0, DI_NORMAL);
    end
    else begin
      iW := iffi(TitleIcon.Width = 0, CaptionHeight - R.Top, TitleIcon.Width);
      iH := iffi(TitleIcon.Height = 0, CaptionHeight - R.Top, TitleIcon.Height);
      if (iH > 16) and (AppIconLarge <> nil)
        then DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, AppIconLarge.Handle, iW, iH, 0, 0, DI_NORMAL)
        else if (AppIcon <> nil)
          then DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, AppIcon.Handle, iW, iH, 0, 0, DI_NORMAL)
          else DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, LoadIcon(0, IDI_APPLICATION), TitleIconWidth(SkinProvider), TitleIconHeight(SkinProvider), 0, 0, DI_NORMAL);
    end;
  end;
end;

function GetWindowWidth(Handle : hwnd) : integer;
var
  R : TRect;
begin
  GetWindowRect(Handle, R);
  Result := WidthOf(R)
end;

function GetClientWidth(Handle : hwnd) : integer;
var
  R : TRect;
begin
  GetClientRect(Handle, R);
  Result := WidthOf(R)
end;

function GetWindowHeight(Handle : hwnd) : integer;
var
  R : TRect;
begin
  GetWindowRect(Handle, R);
  Result := HeightOf(R)
end;

function GetClientHeight(Handle : hwnd) : integer;
var
  R : TRect;
begin
  GetClientRect(Handle, R);
  Result := HeightOf(R)
end;

{ TsSkinProvider }

procedure TsSkinProvider.AfterConstruction;
begin
  inherited;
  if Assigned(FCommonData.SkinManager) and FCommonData.SkinManager.Active and not (csDesigning in ComponentState) then begin
    PrepareForm;
  end;
end;

function TsSkinProvider.BarWidth(i : integer): integer;
begin
  if Assigned(FCommonData.SkinManager.ma[i].Bmp) then begin
    Result := (FCommonData.SkinManager.ma[i].Bmp.Width div 9) * 2 + TitleBtnsWidth;
  end
  else begin
    Result := (WidthOf(FCommonData.SkinManager.ma[i].R) div (3 * FCommonData.SkinManager.ma[i].ImageCount)) * 2 + TitleBtnsWidth;
  end;
end;

function TsSkinProvider.BorderHeight(CheckSkin : boolean = True): integer;
begin
  Result := SysBorderHeight(Form.Handle, BorderForm, CheckSkin) + Form.BorderWidth
end;

function TsSkinProvider.BorderWidth(CheckSkin : boolean = True): integer;
begin
  Result := SysBorderWidth(Form.Handle, BorderForm, CheckSkin) + Form.BorderWidth;
end;

function TsSkinProvider.ButtonHeight: integer;
begin
  if FCommonData.SkinManager.IsValidImgIndex(ButtonClose.ImageIndex) then begin
    if FCommonData.SkinManager.ma[ButtonClose.ImageIndex].Bmp = nil
      then Result := HeightOf(FCommonData.SkinManager.ma[ButtonClose.ImageIndex].R) div (1 + FCommonData.SkinManager.ma[ButtonClose.ImageIndex].MaskType)
      else Result := FCommonData.SkinManager.ma[ButtonClose.ImageIndex].Bmp.Height div 2;
  end
  else Result := 21;
end;

function TsSkinProvider.SysButtonsCount: integer;
begin
  Result := 0;
  if Assigned(SystemMenu) and SystemMenu.VisibleClose{(biSystemMenu in Form.BorderIcons)} then begin
    inc(Result);
    if SystemMenu.VisibleMax then inc(Result);
    if SystemMenu.VisibleMin then inc(Result);
    if (biHelp in Form.BorderIcons) then inc(Result);
  end;
end;

function TsSkinProvider.SysButtonWidth(Btn : TsCaptionButton): integer;
begin
  if FCommonData.SkinManager.IsValidImgIndex(Btn.ImageIndex) then begin
    if FCommonData.SkinManager.ma[Btn.ImageIndex].Bmp = nil
     then Result := WidthOfImage(FCommonData.SkinManager.ma[Btn.ImageIndex])
     else Result := FCommonData.SkinManager.ma[Btn.ImageIndex].Bmp.Width div FCommonData.SkinManager.ma[Btn.ImageIndex].ImageCount;
  end
  else Result := 21;
end;

function TsSkinProvider.CaptionHeight(CheckSkin : boolean = True): integer;
begin
  Result := 0;
  if HaveBorder(Self) and (GetWindowLong(Form.Handle, GWL_STYLE) and WS_CAPTION = WS_CAPTION) or IsIconic(Form.Handle) then begin
    if CheckSkin then Result := SkinTitleHeight(Self.BorderForm);
    if FSysExHeight then begin//(BorderForm <> nil) and IsZoomed(Form.Handle) then begin // Used for GetMinMax message (Y can't be smaller then Zero there)
      if Form.BorderStyle in [bsToolWindow, bsSizeToolWin]
        then Result := max(Result, GetSystemMetrics(SM_CYSMCAPTION) + 4)//SysBorderWidth(Form.Handle, BorderForm, False))
        else Result := max(Result, GetSystemMetrics(SM_CYCAPTION) + 4)//SysBorderWidth(Form.Handle, BorderForm, False));
    end
    else if Result = 0 then begin
      if Form.BorderStyle in [bsToolWindow, bsSizeToolWin]
        then Result := GetSystemMetrics(SM_CYSMCAPTION)
        else Result := GetSystemMetrics(SM_CYCAPTION)
    end;
  end
  else Result := 0;
end;

constructor TsSkinProvider.Create(AOwner: TComponent);
var
  i : integer;
  sp : TsSkinProvider;
begin
  inherited Create(AOwner);
  FDrawNonClientArea := True;
  Form := TForm(GetOwnerForm(Self));
//  DwmInitialized := False;
  FInAnimation := False;
  FAllowExtBorders := True;
  OldWndProc := nil;

  if AOwner is TCustomFrame then ShowWarning('TsSkinProvider component must be used with forms only!');
  fAnimating := False;
  HaveSysMenu := False;
  InMenu := False;
  ShowAction := saIgnore;

  FCommonData := TsCommonData.Create(Self, False);
  FCommonData.SkinSection := s_Form;
  FCommonData.COC := COC_TsSkinProvider;
  if Form.ControlState <> [] then FCommonData.Updating := True;

  FResizeMode := rmStandard;
  FUseGlobalColor := True;
  MDIForm := nil;
  AeroInvalidate := False;

  MenuChanged := True;
  FMakeSkinMenu := DefMakeSkinMenu;
  MenusInitialized := False;
  RgnChanged := True;
  RgnChanging := False;
  FScreenSnap := False;
  FSnapBuffer := 10;
{$IFDEF CHECKXP}
//  StdBgIsUsed := True;
{$ENDIF}

  FShowAppIcon := True;
  FCaptionAlignment := taLeftJustify;
  FTitleIcon := TsTitleIcon.Create;
  FTitleButtons := TsTitleButtons.Create(Self);

  FGripMode := gmNone;
  ClearButtons := False;
  OldCaptFormProc := nil;

  // Search of other SkinProvider
  if (csDesigning in ComponentState) then begin
    for i := 0 to Form.ComponentCount - 1 do if (Form.Components[i] is TsSkinProvider) and (Form.Components[i] <> Self) then begin
      Form := nil;
      ShowWarning('Only one instance of the TsSkinProvider component is allowed!');
      break;
    end;
  end
  else begin
    sp := nil;
    for i := 0 to Form.ComponentCount - 1 do if (Form.Components[i] is TsSkinProvider) and (Form.Components[i] <> Self) then begin
      sp := TsSkinProvider(Form.Components[i]);
      break;
    end;
    if (sp <> nil) and (sp.Form <> nil) then begin
//      sp.Form.WindowProc := sp.OldWndProc;
//      OldWndProc := sp.OldWndProc;
      FreeAndNil(sp);
    end;
  end;

  if not (csDesigning in ComponentState) and (Form <> nil) then begin
    Form.DoubleBuffered := False;
    TempBmp := TBitmap.Create;
    MenuLineBmp := CreateBmp24(0, 0);

    ClearButtons := True;

    SetLength(ArOR, 0);

    FLinesCount := -1;

    OldWndProc := Form.WindowProc;
    Form.WindowProc := NewWndProc;
    IntSkinForm(Form);

    FormActive := True;
  end;
end;

destructor TsSkinProvider.Destroy;
begin
  if not (csDesigning in ComponentState) then begin
    KillAnimations;
    if Form <> nil then begin
      IntUnskinForm(Form);
      Form.WindowProc := OldWndProc;
      if (Form.FormStyle = fsMDIChild) and Assigned(Form.Menu) then begin
        if Assigned(MDISkinProvider) and
             not (csDestroying in TsSkinProvider(MDISkinProvider).ComponentState) and
             not (csDestroying in TsSkinProvider(MDISkinProvider).Form.ComponentState)
               then begin
          TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
          TsSkinProvider(MDISkinProvider).FLinesCount := -1;
          SendMessage(TsSkinProvider(MDISkinProvider).Form.Handle, WM_NCPAINT, 0, 0);
        end;
      end;
      if MDISkinProvider = Self then begin
        if MDIForm <> nil then HookMDI(False);
        MDISkinProvider := nil;
      end;
    end;
    if Assigned(SystemMenu) then FreeAndNil(SystemMenu);
    if Assigned(TempBmp) then FreeAndnil(TempBmp);
    if Assigned(MenuLineBmp) then FreeAndNil(MenuLineBmp);
    if TitleBG <> nil then FreeAndNil(TitleBG);
  end;

  if ChildProvider = Self then ChildProvider := nil;
  InitExBorders(False);

  if Assigned(FTitleIcon) then FreeAndNil(FTitleIcon);
  if Assigned(FTitleButtons) then FreeAndNil(FTitleButtons);

  if Assigned(Adapter) then FreeAndNil(Adapter);
  if ListSW <> nil then FreeAndNil(ListSW);
  if FCommonData <> nil then FreeAndNil(FCommonData);
  inherited Destroy;
end;

procedure TsSkinProvider.RepaintButton(i: integer);
var
  DC, SavedDC : hdc;
  CurButton : PsCaptionButton;
  cx, ind, x, y : integer;
  BtnDisabled : boolean;
  CI : TCacheInfo;
  R : TRect;
begin
  CurButton := nil;
  case i of
    HTCLOSE      : CurButton := @ButtonClose;
    HTMAXBUTTON  : CurButton := @ButtonMax;
    HTMINBUTTON  : CurButton := @ButtonMin;
    HTHELP       : CurButton := @ButtonHelp;
    HTCHILDCLOSE : CurButton := @MDIClose;
    HTCHILDMAX   : CurButton := @MDIMax;
    HTCHILDMIN   : CurButton := @MDIMin
    else if Between(i, HTUDBTN, (HTUDBTN + TitleButtons.Count - 1)) then CurButton := @TitleButtons.Items[i - HTUDBTN].BtnData;
  end;
  if (i in [HTCHILDCLOSE..HTCHILDMIN]) or (not FCommonData.SkinManager.AllowGlowing and (BorderForm = nil)) then begin 
    if (CurButton <> nil) and (CurButton^.State <> -1) then begin
      BtnDisabled := False;
      if CurButton^.Rect.Left <= IconRect.Right then Exit;
      cx := CaptionWidth - CurButton^.Rect.Left;
      BitBlt(FCommonData.FCacheBmp.Canvas.Handle, // Restore a button BG
             CurButton^.Rect.Left, CurButton^.Rect.Top, SysButtonwidth(CurButton^), ButtonHeight,
             TempBmp.Canvas.Handle, TempBmp.Width - cx, CurButton^.Rect.Top, SRCCOPY);
      // if Max btn and form is maximized then Norm btn
      if (i = HTMAXBUTTON) and (Form.WindowState = wsMaximized) then ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, s_GlobalInfo, s_BorderIconNormalize)
      else case i of
        HTCHILDMIN : begin
          ind := CurButton^.ImageIndex;
          if ChildProvider <> nil then BtnDisabled := not ChildProvider.SystemMenu.EnabledMin;
          if BtnDisabled then Exit;
        end;
        HTCHILDMAX : begin // Correction of the Maximize button (may be Normalize)
          if Assigned(Form.ActiveMDIChild) and (Form.ActiveMDIChild.WindowState = wsMaximized) then begin
            ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconNormalize);
            if ind < 0 then ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, s_GlobalInfo, s_BorderIconNormalize) // For compatibility
          end
          else ind := CurButton^.ImageIndex;
          if ChildProvider <> nil then BtnDisabled := not ChildProvider.SystemMenu.EnabledRestore;
        end
        else if IsIconic(Form.Handle) then begin
          case i of
            HTMINBUTTON : begin
              ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconNormalize);
              if ind < 0 then ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_BorderIconNormalize); // For compatibility
            end;
            HTMAXBUTTON : begin
              ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMaximize);
              if ind < 0 then ind := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_BorderIconMaximize); // For compatibility
              if not SystemMenu.EnabledMax then BtnDisabled := True;
            end
            else ind := CurButton^.ImageIndex;
          end
        end else ind := CurButton^.ImageIndex;
      end;
      if FCommonData.SkinManager.IsValidImgIndex(ind) then begin // Drawing of the button from skin
        if i < HTUDBTN // if not user defined
          then DrawSkinGlyph(FCommonData.FCacheBmp, Point(CurButton^.Rect.Left, CurButton^.Rect.Top),
                 CurButton^.State, 1 + integer(not FormActive or BtnDisabled) * integer((CurButton^.State = 0) or BtnDisabled), FCommonData.SkinManager.ma[ind], MakeCacheInfo(SkinData.FCacheBmp))
          else if (TitleButtons.Items[i - HTUDBTN].UseSkinData)
               then DrawSkinGlyph(FCommonData.FCacheBmp, Point(CurButton^.Rect.Left, CurButton^.Rect.Top),
                 CurButton^.State, 1 + integer(not FormActive) * integer(CurButton^.State = 0), FCommonData.SkinManager.ma[ind], MakeCacheInfo(SkinData.FCacheBmp));
      end;
      // If user Glyph is defined
      if (i >= HTUDBTN) and Assigned(TitleButtons.Items[i - HTUDBTN].Glyph) then begin
        if TitleButtons.Items[i - HTUDBTN].Glyph.PixelFormat = pf32bit then begin
          x := CurButton^.Rect.Left + integer(CurButton^.State = 2) + (WidthOf(CurButton^.Rect) - TitleButtons.Items[i - HTUDBTN].Glyph.Width) div 2;
          y := CurButton^.Rect.Top + integer(CurButton^.State = 2) + (HeightOf(CurButton^.Rect) - TitleButtons.Items[i - HTUDBTN].Glyph.Height) div 2;
          CI := MakeCacheInfo(FCommonData.FCacheBmp, x, y);
          CopyByMask(Rect(x, y, x + TitleButtons.Items[i - HTUDBTN].Glyph.Width, y + TitleButtons.Items[i - HTUDBTN].Glyph.Height),
                     Rect(0, 0, TitleButtons.Items[i - HTUDBTN].Glyph.Width, TitleButtons.Items[i - HTUDBTN].Glyph.Height),
                     FCommonData.FCacheBmp,
                     TitleButtons.Items[i - HTUDBTN].Glyph,
                     CI, True);
        end
        else begin
          TitleButtons.Items[i - HTUDBTN].Glyph.PixelFormat := pf24bit;
          CopyTransBitmaps(FCommonData.FCacheBmp, TitleButtons.Items[i - HTUDBTN].Glyph,
               CurButton^.Rect.Left + integer(CurButton^.State = 2) + (WidthOf(CurButton^.Rect) - TitleButtons.Items[i - HTUDBTN].Glyph.Width) div 2,
               CurButton^.Rect.Top + integer(CurButton^.State = 2) + (HeightOf(CurButton^.Rect) - TitleButtons.Items[i - HTUDBTN].Glyph.Height) div 2,
               ColorToSColor(TitleButtons.Items[i - HTUDBTN].Glyph.Canvas.Pixels[0, TitleButtons.Items[i - HTUDBTN].Glyph.Height - 1]));
        end;
      end;
      // Copying to form
      DC := GetWindowDC(Form.Handle);
      SavedDC := SaveDC(DC);
      try
        if BorderForm <> nil
          then BitBlt(DC, CurButton^.Rect.Left - DiffBorder(Self.BorderForm) - ShadowSize.Left, CurButton^.Rect.Top - DiffTitle(Self.BorderForm) - ShadowSize.Top, WidthOf(CurButton^.Rect), HeightOf(CurButton^.Rect),
                        FCommonData.FCacheBmp.Canvas.Handle, CurButton^.Rect.Left, CurButton^.Rect.Top, SRCCOPY)
          else BitBlt(DC, CurButton^.Rect.Left - ShadowSize.Left, CurButton^.Rect.Top - ShadowSize.Top, WidthOf(CurButton^.Rect), HeightOf(CurButton^.Rect),
                        FCommonData.FCacheBmp.Canvas.Handle, CurButton^.Rect.Left, CurButton^.Rect.Top, SRCCOPY);
        if (CurButton^.State = 1) and (i in [HTCLOSE, HTMAXBUTTON, HTMINBUTTON]) then begin
          case i of
            HTCLOSE      : x := FCommonData.SkinManager.SkinData.BICloseGlow;
            HTMAXBUTTON  : x := FCommonData.SkinManager.SkinData.BIMaxGlow;
            HTMINBUTTON  : x := FCommonData.SkinManager.SkinData.BIMinGlow;
          end;
          if x > 0 then begin
            case i of
              HTCLOSE      : y := FCommonData.SkinManager.SkinData.BICloseGlowMargin;
              HTMAXBUTTON  : y := FCommonData.SkinManager.SkinData.BIMaxGlowMargin;
              HTMINBUTTON  : y := FCommonData.SkinManager.SkinData.BIMinGlowMargin;
            end;
            if BorderForm <> nil
              then GetWindowRect(BorderForm.AForm.Handle, R)
              else GetWindowRect(Form.Handle, R);
            OffsetRect(R, CurButton^.Rect.Left, CurButton^.Rect.Top);
            R.Right := R.Left + WidthOf(CurButton^.Rect);
            R.Bottom := R.Top + HeightOf(CurButton^.Rect);

            if SkinData.SkinManager.AllowGlowing and (Form.Parent = nil) and (Form.FormStyle <> fsMDIChild) then begin
              if BorderForm <> nil
                then CurButton^.GlowID := ShowGlow(R, R, s_GlobalInfo, FCommonData.SkinManager.ma[CurButton.ImageIndex].PropertyName + s_Glow, y, 255, BorderForm.AForm.Handle, FCommonData.SkinManager)
                else CurButton^.GlowID := ShowGlow(R, R, s_GlobalInfo, FCommonData.SkinManager.ma[CurButton.ImageIndex].PropertyName + s_Glow, y, 255, Form.Handle, FCommonData.SkinManager);
            end  
          end;
        end
        else if CurButton^.GlowID <> -1 then begin
          HideGlow(CurButton^.GlowID);
          CurButton^.GlowID := -1;
        end;
      finally
        RestoreDC(DC, SavedDC);
        ReleaseDC(Form.Handle, DC);
      end;
    end
    else if (CurButton <> nil) and (CurButton^.GlowID <> -1) then begin
      HideGlow(CurButton^.GlowID);
      CurButton^.GlowID := -1;
    end;
  end
  else begin
    if (CurButton <> nil) and (CurButton^.State <> -1) then begin
      case CurButton^.State of
        1 : StartSBAnimation(CurButton, CurButton^.State, 10, CurButton^.State <> 0, Self);
        2 : StartSBAnimation(CurButton, CurButton^.State, 1, CurButton^.State <> 0, Self);
        else StartSBAnimation(CurButton, CurButton^.State, 10, False, Self);
      end;
    end
  end;
end;

function TsSkinProvider.HTProcess(var Message : TWMNCHitTest): integer;
const
  BtnSpacing = 1;
  DefRESULT = HTCLIENT;
var
  p : TPoint;
  ii, i, sbw, SysBtnCount, BtnIndex : integer;
  GripVisible : boolean;
  R, hrect, vrect : TRect;
  function GetBtnIndex : integer;
  var
    i, c : integer;
  begin
    Result := 0;
    if BorderForm <> nil then Exit;
    c := 0;
    if SystemMenu.VisibleClose and Assigned(SystemMenu) then begin
      inc(c);
      if PtInRect(ButtonClose.Rect, p) then Result := c else begin
        if SystemMenu.VisibleMax then begin
          inc(c);
          if PtInRect(ButtonMax.Rect, p) then begin
            Result := c;
            Exit;
          end;
        end;
        if SystemMenu.VisibleMin then begin
          inc(c);
          if PtInRect(ButtonMin.Rect, p)
            then Result := c
        end;
        if Result <> 0 then Exit;
        if (biHelp in Form.BorderIcons) then begin
          inc(c);
          if PtInRect(ButtonHelp.Rect, p) then begin
            Result := c;
            Exit;
          end;
        end;
      end;
    end;
    for i := 0 to TitleButtons.Count - 1 do begin
      inc(c);
      if PtInRect(TitleButtons[i].BtnData.Rect, p) then begin
        Result := c;
        Exit;
      end;
    end;
  end;
begin
  p := CursorToPoint(Message.XPos, Message.YPos);
  Result := DefRESULT;

  BtnIndex := GetBtnIndex;
  if (BtnIndex > 0) then begin
    SysBtnCount := 0;
    if SystemMenu.VisibleClose then begin
      inc(SysBtnCount);
      if SystemMenu.VisibleMax then inc(SysBtnCount);
      if SystemMenu.VisibleMin or IsIconic(Form.Handle) then inc(SysBtnCount);
      if biHelp in Form.BorderIcons then inc(SysBtnCount);
    end;
    if (BtnIndex <= SysBtnCount) then begin
      case BtnIndex of
        1 : if SystemMenu.VisibleClose then Result := HTCLOSE;
        2 : begin
          if SystemMenu.VisibleMax then begin
            if (SystemMenu.EnabledMax or (SystemMenu.EnabledRestore and not IsIconic(Form.Handle))) then Result := HTMAXBUTTON else Result := HTCAPTION;
          end
          else if (SystemMenu.VisibleMin) or IsIconic(Form.Handle) then begin
            if SystemMenu.EnabledMin then Result := HTMINBUTTON else Result := HTCAPTION;
          end
          else if (biHelp in Form.BorderIcons) then Result := HTHELP;
        end;
        3 : begin
          if (SystemMenu.VisibleMin) or IsIconic(Form.Handle) then begin
            if not IsIconic(Form.Handle) then begin
              if SystemMenu.EnabledMin then Result := HTMINBUTTON else Result := HTCAPTION;
            end
            else Result := HTMINBUTTON;
          end
          else if (biHelp in Form.BorderIcons) then Result := HTHELP;
        end;
        4 : if (biHelp in Form.BorderIcons) and SystemMenu.VisibleMax then Result := HTHELP;
      end;
    end
    else if (BtnIndex <= TitleButtons.Count + SysBtnCount) then begin // UDF button
      BtnIndex := BtnIndex - SysBtnCount - 1;
      if TitleButtons.Items[BtnIndex].Enabled then Result := HTUDBTN + BtnIndex;
    end;
    if Result <> DefRESULT then begin
      SetHotHT(Result);
      Exit;
    end;
  end;

  sbw := SysBorderWidth(Form.Handle, BorderForm);
  if (Form.WindowState <> wsMaximized) and (GetWindowLong(Form.Handle, GWL_STYLE) and WS_SIZEBOX = WS_SIZEBOX) and (BorderForm = nil) then begin
    if (p.Y < SysBorderHeight(Form.Handle, BorderForm, False)) then Result := HTTOP;
    if (p.Y > Form.Height - sbw) then Result := HTBOTTOM;
    if (p.X < sbw) then if Result = HTTOP then Result := HTTOPLEFT else if Result = HTBOTTOM then Result := HTBOTTOMLEFT else Result := HTLEFT;
    if (p.X > Form.Width - sbw) then if Result = HTTOP then Result := HTTOPRIGHT else if Result = HTBOTTOM then Result := HTBOTTOMRIGHT else Result := HTRIGHT;
    if Result <> DefRESULT then begin
      SetHotHT(HTTRANSPARENT);
      Exit;
    end;
  end;

  ii := CaptionHeight(False{v6.33});
  ii := ii + SysBorderHeight(Form.Handle, BorderForm);
  if Between(p.Y, 0, ii) then begin
//  if Between(p.Y, 0, CaptionHeight(False{v6.33}) + SysBorderHeight(Form.Handle, BorderForm)) then begin
    if Between(p.Y, CaptionHeight(False) + SysBorderHeight(Form.Handle, BorderForm, False), CaptionHeight(False) + SysBorderHeight(Form.Handle, BorderForm, False) + MenuHeight) then begin
      Result := HTMENU;//CAPTION;
      Exit;
    end;
    if PtInRect(IconRect, p)
      then Result := HTSYSMENU
      else Result := HTCAPTION;
  end
  else begin
    ii := ii + MenuHeight;
    if p.Y <= ii then begin
//    if p.Y <= CaptionHeight(False{v6.33}) + SysBorderHeight(Form.Handle, BorderForm) + MenuHeight then begin
      // MDI child buttons
      if MDIButtonsNeeded then begin
        if PtInRect(MDICLose.Rect, Point(p.X + ShadowSize.Left + DiffBorder(BorderForm), p.Y + ShadowSize.Top + DiffTitle(BorderForm)))
          then Result := HTCHILDCLOSE
          else if PtInRect(MDIMax.Rect, Point(p.X + ShadowSize.Left + DiffBorder(BorderForm), p.Y + ShadowSize.Top + DiffTitle(BorderForm)))
            then Result := HTCHILDMAX
            else if PtInRect(MDIMin.Rect, Point(p.X + ShadowSize.Left + DiffBorder(BorderForm), p.Y + ShadowSize.Top + DiffTitle(BorderForm))) then Result := HTCHILDMIN else Result := HTMENU;
        if Result <> DefRESULT
          then SetHotHT(Result)
          else SetHotHT(0);
      end
      else Result := HTMENU;
    end
    else begin
      if IsGripVisible(Self) then GripVisible := True else
        if Assigned(ListSW) and Assigned(ListSW.sbarVert) and ListSW.sbarVert.fScrollVisible and ListSW.sbarHorz.fScrollVisible then begin
          Ac_GetHScrollRect(ListSW, Form.Handle, hrect);
          Ac_GetVScrollRect(ListSW, Form.Handle, vrect);
          GetWindowRect(Form.Handle, R);
          GripVisible := PtInRect(Rect(hrect.Right - R.Left, hrect.Top - R.Top, vrect.Right - R.Left, hrect.Bottom - R.Top), p)
      end
      else GripVisible := False;
      if GripVisible then begin
        i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_GripImage);
        if FCommonData.SkinManager.IsValidImgIndex(i) then begin
          if (BorderForm <> nil) then begin
            if (p.y > RBGripPoint(i).y - DiffTitle(Self.BorderForm) - ShadowSize.Top) and (p.x > RBGripPoint(i).x - DiffBorder(Self.BorderForm) - ShadowSize.Left) then Result := HTBOTTOMRIGHT;
          end
          else begin
            if (p.y > RBGripPoint(i).y) and (p.x > RBGripPoint(i).x) then Result := HTBOTTOMRIGHT;
          end;
        end;
      end;
      if Result <> DefRESULT
        then SetHotHT(Result)
        else SetHotHT(0);
    end;
  end;
end;

procedure UpdateMainForm;
var
  Flags : Cardinal;
begin
  if Assigned(MDISkinProvider) then begin

    TsSkinProvider(MDISkinProvider).FCommonData.BeginUpdate;
    if Assigned(TsSkinProvider(MDISkinProvider).MDIForm) then TsMDIForm(TsSkinProvider(MDISkinProvider).MDIForm).UpdateMDIIconItem;
    TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
    TsSkinProvider(MDISkinProvider).MenuChanged := True;
    TsSkinProvider(MDISkinProvider).FLinesCount := -1;
    TsSkinProvider(MDISkinProvider).FCommonData.EndUpdate;

    Flags := RDW_ERASE or RDW_FRAME or RDW_INTERNALPAINT or RDW_INVALIDATE;
    if UpdateNow then Flags := Flags + RDW_UPDATENOW;

    RedrawWindow(TsSkinProvider(MDISkinProvider).Form.ClientHandle, nil, 0, Flags);
    RedrawWindow(TsSkinProvider(MDISkinProvider).Form.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE);

    if UpdateNow and (TsSkinProvider(MDISkinProvider).BorderForm <> nil) then TsSkinProvider(MDISkinProvider).BorderForm.UpdateExBordersPos;
  end
end;

procedure HandleEdge(var Edge: Integer; SnapToEdge: Integer; ASnapBuffer : integer; SnapDistance: Integer = 0);
begin
  if (Abs(Edge + SnapDistance - SnapToEdge) < ASnapBuffer) then Edge := SnapToEdge - SnapDistance;
end;

function DoLayered(Form : TForm; Layered : boolean) : boolean;
var
  DC : hdc;
  FBmpSize: TSize;
  FBmpTopLeft: TPoint;
  FBlend: TBlendFunction;
  Bmp : TBitmap;
begin
  Result := False;
  if Layered then begin
    if GetWindowLong(Form.Handle, GWL_EXSTYLE) and WS_EX_LAYERED <> WS_EX_LAYERED then begin
      DC := GetDC(0);
      FBlend.BlendOp := AC_SRC_OVER;
      FBlend.BlendFlags := 0;
      FBlend.AlphaFormat := AC_SRC_ALPHA;
      FBlend.SourceConstantAlpha := 10;
      FBmpSize.cx := 0;
      FBmpSize.cy := 0;
      FBmpTopLeft.X := 0;
      FBmpTopLeft.Y := 0;
      Bmp := TBitmap.Create;

      SetWindowLong(Form.Handle, GWL_EXSTYLE, GetWindowLong(Form.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
      UpdateLayeredWindow(Form.Handle, DC, nil, @FBmpSize, Bmp.Canvas.Handle, @FBmpTopLeft, clNone, @FBlend, ULW_ALPHA);

      Bmp.Free;
      ReleaseDC(0, DC);
      Result := True;
    end;
  end
  else begin
    SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) and not WS_VISIBLE); // Avoid a form showing
    SetWindowLong(Form.Handle, GWL_EXSTYLE, GetWindowLong(Form.Handle, GWL_EXSTYLE) and not WS_EX_LAYERED);
//    SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_VISIBLE);
  end;
end;

function acWorkRect(Form : TForm) : TRect;
begin
{$IFDEF DELPHI6UP}
  Result := Form.Monitor.WorkareaRect;
{$ELSE}
  Result := WorkRect;
{$ENDIF}
end;

type
  TAccessForm = class(TForm);

procedure TsSkinProvider.NewWndProc(var Message: TMessage);
var
  DC, SavedDC : hdc;
  mi :  TMenuItem;
  X, Y, i : integer;
  p : TPoint;
  UpdateClient, lInted : boolean;
  cR : TRect;
  PS : TPaintStruct;
  AFlags: Longint;
begin
{$IFDEF LOGGED}
  if Assigned(Form) and (Form.Name <> 'Form1') then begin
    AddToLog(Message);
  end;
{$ENDIF}
{$IFDEF LOGGED}
//  if Form.Tag = 1 then begin
//    if Form.Parent <> nil then AddToLog(Message, 'Docked  - ') else AddToLog(Message, 'Undocked  - ');
//  end;
//  AddToLog(Message);
{$ENDIF}
  if Message.Msg = SM_ALPHACMD then case Message.WParamHi of
    AC_REMOVESKIN : begin
      if (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) then begin
        if ListSW <> nil then FreeAndNil(ListSW);
//        UpdateClient := BorderForm <> nil;
        InitDwm(Form.Handle, False); // v6.43
        AdapterRemove;
        CommonMessage(Message, FCommonData);
        FLinesCount := -1;
        AlphaBroadCast(Form, Message);
        if Assigned(SkinData.SkinManager) then begin
          DeleteUnusedBmps(True);
        end;
        if (Form <> nil) and not (csDestroying in Form.ComponentState) then begin
          if Assigned(SkinData.SkinManager) then begin
            InitMenuItems(False);
            CheckSysMenu(False);
            if (Form.FormStyle = fsMDIForm) and (MDIForm <> nil) then HookMDI(False);
            if HaveBorder(Self) and not InMenu then SetWindowRgn(Form.Handle, 0, True); // Return standard kind
            UpdateMenu;
            RedrawWindow(Form.ClientHandle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE or RDW_ALLCHILDREN);
            InitExBorders(False);
          end;
          for i := 0 to Form.ControlCount - 1 do if Form.Controls[i] is TLabel then TLabel(Form.Controls[i]).Font.Color := clWindowText;
          if UseGlobalColor and not SkinData.CustomColor then Form.Color := clBtnFace;
          if FCommonData.FCacheBmp <> nil then FreeAndNil(FCommonData.FCacheBmp);
        end;
      end
      else AlphaBroadCast(Form, Message);
      Exit
    end;
    AC_SETNEWSKIN : if not (csDestroying in Form.ComponentState) and Assigned(SkinData) then begin
      if (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) and not Assigned(SystemMenu) then PrepareForm
    end;
    AC_GETAPPLICATION : begin Message.Result := longint(Application); Exit end;
    AC_PARENTCLOFFSET : begin Message.Result := MakeLong(OffsetX, OffsetY); Exit end;
    AC_CTRLHANDLED : begin Message.Result := 1; Exit end;
    AC_GETBG : if (FCommonData <> nil) then begin
      if FCommonData.BGChanged and not FCommonData.FUpdating and IsCached(SkinData) then begin
        PaintAll;
      end;
      if PacBGInfo(Message.LParam)^.PleaseDraw then begin
        inc(PacBGInfo(Message.LParam)^.Offset.X, OffsetX);
        inc(PacBGInfo(Message.LParam)^.Offset.Y, OffsetY);
      end;
      InitBGInfo(FCommonData, PacBGInfo(Message.LParam), integer(FormActive));
      if (PacBGInfo(Message.LParam)^.BgType = btCache) then begin
        if not PacBGInfo(Message.LParam)^.PleaseDraw then begin
          if PacBGInfo(Message.LParam)^.Bmp = nil then begin
            PaintAll;
            PacBGInfo(Message.LParam)^.Bmp := FCommonData.FCacheBmp;
          end;
          PacBGInfo(Message.LParam)^.Offset := Point(OffsetX, OffsetY);
        end;
      end;
      Exit;
    end;
    AC_GETSKINSTATE : begin
      Message.Result := FCommonData.CtrlSkinState;
      Exit;
    end;
  end;

  if (csDestroying in Form.ComponentState) or not FCommonData.Skinned(True) then begin
    if Message.Msg = SM_ALPHACMD then case Message.WParamHi of
      AC_GETPROVIDER : begin Message.Result := longint(Self); Exit end; // Used for menuline init
      AC_SETNEWSKIN : if not (csDestroying in Form.ComponentState) and Assigned(SkinData) then begin
        if (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) then begin
          DeleteUnusedBmps(True);
          FCommonData.UpdateIndexes;
//          if not IsCacheRequired(FCommonData) then FCommonData.CtrlSkinState := FCommonData.CtrlSkinState or ACS_FAST else FCommonData.CtrlSkinState := FCommonData.CtrlSkinState and not ACS_FAST;

          if (SkinData.SkinManager <> nil) then begin
            UpdateIconsIndexes;
            CheckSysMenu(True);
            if (Form.FormStyle = fsMDIForm) and (Screen.ActiveForm = Form.ActiveMDIChild) then FormActive := True;
            // Menus skinning
            if not (csLoading in SkinData.SkinManager.ComponentState) then
              InitMenuItems(True); // Update after skinning in run-time
            // Menu Line refresh
            FCommonData.BGChanged := True;
            FLinesCount := -1;
            if (TForm(Form).FormStyle = fsMDIForm) then begin
              if not Assigned(MDIForm) then HookMDI;
            end;
            if UseGlobalColor and not SkinData.CustomColor then Form.Color := SkinData.SkinManager.GetGlobalColor;
            InitDwm(Form.Handle, True); // v6.43
          end;
          if Adapter = nil then AdapterCreate else TacCtrlAdapter(Adapter).AddAllItems;
        end;
        Exit;
      end;
    end;
    OldWndProc(Message);
    if (Message.Msg = WM_NCDESTROY) and (Form.FormStyle = fsMDIChild) then begin
      if Assigned(MDISkinProvider) and Assigned(TsSkinProvider(MDISkinProvider).MDIForm) and not (csDestroying in TsSkinProvider(MDISkinProvider).ComponentState) and
          not (csDestroying in TsSkinProvider(MDISkinProvider).Form.ComponentState) and TsSkinProvider(MDISkinProvider).SkinData.Skinned(True) then begin
        TsSkinProvider(MDISkinProvider).RepaintMenu;
        if TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild = nil
          then RedrawWindow(TsSkinProvider(MDISkinProvider).Form.ClientHandle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INTERNALPAINT or RDW_INVALIDATE or RDW_UPDATENOW);
      end;
    end;
  end
  else begin
    if Message.Msg = SM_ALPHACMD then case Message.WParamHi of
      AC_CONTROLLOADED : if (Form <> nil) and not (csLoading in Form.ComponentState) then begin
        if (Adapter <> nil) then begin
          if (Message.LParam <> 0) then TacCtrlAdapter(Adapter).AddAllItems(TWinControl(Message.LParam)) else TacCtrlAdapter(Adapter).AddAllItems(Form);
        end;
      end;
      AC_PREPARING : if (FCommonData <> nil) then begin
        Message.Result := integer(not InAnimationProcess{LionDev} and IsCached(FCommonData) and (FCommonData.FUpdating{ or FormChanged}));
        Exit
      end;
      AC_UPDATING : begin
        FCommonData.Updating := Message.WParamLo = 1;
        if FCommonData.Updating then FCommonData.BGChanged := True;
      end;
      AC_EXTINVALIDATE : begin
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False);       
      end;
      AC_REFRESH : if (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) then begin
        if Adapter = nil then AdapterCreate else TacCtrlAdapter(Adapter).AddAllItems;
        if FDrawNonClientArea then RefreshFormScrolls(Self, ListSW, False);

        FLinesCount := -1;
        if Assigned(TitleBG) then FreeAndNil(TitleBG);
        if not (csLoading in SkinData.SkinManager.ComponentState) then begin
          UpdateMenu;
          InitMenuItems(SkinData.Skinned);
        end;
        if HaveBorder(Self) then RgnChanged := True;
        if not Form.Visible then Exit;

        FCommonData.BGChanged := True;
        InitExBorders(SkinData.SkinManager.ExtendedBorders);
        if not InAnimationProcess then begin
          if (Form.FormStyle = fsMDIForm) and Assigned(Form.ActiveMDIChild) and (Form.ActiveMDIChild.WindowState = wsMaximized) then begin
            SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
            InvalidateRect(Form.ActiveMDIChild.Handle, nil, True);
          end
          else begin
            RedrawWindow(Form.Handle, nil, 0, RDW_INVALIDATE or RDW_ERASE or RDW_UPDATENOW or RDW_FRAME or RDW_NOCHILDREN);
            if Form.FormStyle = fsMDIForm then RedrawWindow(Form.ClientHandle, nil, 0, RDW_INVALIDATE or RDW_ERASE or RDW_UPDATENOW or RDW_FRAME or RDW_NOCHILDREN);
          end;
        end;
        if UseGlobalColor and not SkinData.CustomColor then Form.Color := SkinData.SkinManager.GetGlobalColor;
        if MDIForm <> nil then TsMDIForm(MDIForm).ConnectToClient;
        FCommonData.Updating := False;                               // Form image is prepared now
        if SystemMenu <> nil then SystemMenu.UpdateGlyphs;
        SendToAdapter(Message);                                      // Sending message to all child adapted controls
        if BorderForm <> nil then BorderForm.UpdateExBordersPos;
      end;
      AC_CHILDCHANGED : begin
        Message.LParam := integer((FCommonData.SkinManager.gd[SkinData.SkinIndex].GradientPercent + FCommonData.SkinManager.gd[SkinData.SkinIndex].ImagePercent > 0));
        Message.Result := Message.LParam;
        Exit;
      end;
      AC_GETCONTROLCOLOR : begin
        Message.Result := FormColor;
        Exit;
      end;
      AC_INVALIDATE : begin
        if (BorderForm <> nil) and (fsModal in TAccessForm(Form).FormState) then BorderForm.UpdateExBordersPos(False); // Patch for ReportBuilder and similar windows
      end;
      AC_GETPROVIDER : begin
        Message.Result := longint(Self);
        Exit
      end; // Used for menuline init
      AC_SETNEWSKIN : if (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) then begin
        DeleteUnusedBmps(True);
        FCommonData.UpdateIndexes;
//        if not IsCacheRequired(FCommonData) then FCommonData.CtrlSkinState := FCommonData.CtrlSkinState or ACS_FAST else FCommonData.CtrlSkinState := FCommonData.CtrlSkinState and not ACS_FAST;
        if (SkinData.SkinManager <> nil) then begin
          UpdateIconsIndexes;

          DeleteUnusedBmps(True);
          CheckSysMenu(FDrawNonClientArea);
          SkinData.SkinManager.SkinableMenus.UpdateMenus;

          // Menu Line refresh
          FCommonData.BGChanged := True;
          FLinesCount := -1;
          SendMessage(Form.Handle, WM_NCPaint, 0, 0);
          if (TForm(Form).FormStyle = fsMDIForm) and not Assigned(MDIForm) then HookMDI;
        end;
      end;
      AC_BEFORESCROLL : if FCommonData.RepaintIfMoved then SendMessage(Form.Handle, WM_SETREDRAW, 0, 0);
      AC_AFTERSCROLL : if FCommonData.RepaintIfMoved then begin
        SendMessage(Form.Handle, WM_SETREDRAW, 1, 0);
        RedrawWindow(Form.Handle, nil, 0, {RDW_NOERASE or }RDW_UPDATENOW or RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_FRAME or RDW_ERASE);
        if MDISkinProvider = Self then RedrawWindow(Form.ClientHandle, nil, 0, RDW_UPDATENOW or RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_FRAME);
      end;
      AC_URGENTPAINT : begin
        CommonWndProc(Message, FCommonData);
        if FCommonData.UrgentPainting then PaintAll;
        Exit;
      end;
    end
    else case Message.Msg of
      WM_CONTEXTMENU : begin
        if (Form.PopupMenu <> nil) then SkinData.SkinManager.SkinableMenus.HookPopupMenu(Form.PopupMenu, True);
        OldWndProc(Message);
      end;
      WM_SETREDRAW : begin
        if (Message.WParam = 1) then LockCount := max(0, LockCount - 1) else inc(LockCount);
        OldWndProc(Message);
      end;
      WM_EXITSIZEMOVE : begin
        OldWndProc(Message);
        if (BorderForm <> nil) and (acSupportedList <> nil) then for i := 0 to acSupportedList.Count - 1 do begin
          if acSupportedList[i] <> nil then SendAMessage(TacProvider(acSupportedList[i]).CtrlHandle, AC_INVALIDATE); // Update of some popup Dlgs
        end;
        if (BorderForm <> nil) and (fsModal in TAccessForm(Form).FormState) then BorderForm.UpdateExBordersPos(False); // Patch for ReportBuilder and similar windows
      end;
      WM_GETMINMAXINFO : AC_WMGetMinMaxInfo(TWMGetMinMaxInfo(Message));
      WM_SETICON : begin
        OldWndProc(Message);
        UpdateSkinCaption(Self);
      end;
//      WM_NCCALCSIZE : AC_WMNCCalcSize(TWMNCCalcSize(Message));
      WM_INITMENUPOPUP : AC_WMInitMenuPopup(TWMInitMenuPopup(Message));
      787 : DropSysMenu(Mouse.CursorPos.X, Mouse.CursorPos.Y);
      CM_SHOWINGCHANGED : begin
        if FCommonData.BGChanged and {not AeroIsEnabled and }Form.Showing and FDrawNonClientArea then begin // If first showing
          InitMenuItems(SkinData.Skinned);
          if Adapter <> nil then TacCtrlAdapter(Adapter).AddAllItems(Form);
          fAnimating := (Form.FormStyle <> fsMDIChild) and (Form.Parent = nil) and
                        (not (Form.BorderStyle in [bsSizeable, bsSingle]) and SkinData.SkinManager.AnimEffects.DialogShow.Active or
                        (Form.BorderStyle in [bsSizeable, bsSingle]) and SkinData.SkinManager.AnimEffects.FormShow.Active);

          lInted := False;
          if fAnimating then begin
            FCommonData.Updating := True; // Don't draw child controls
            FInAnimation := True;
            lInted := DoLayered(Form, True);
            if lInted then begin
              UpdateRgn(Self, False);
              RgnChanging := False;
            end;
            for i := 0 to Form.ControlCount - 1 do if Form.Controls[i].Visible and not (Form.Controls[i] is TCoolBar) {TCoolBar must have Painting processed for buttons aligning} then Form.Controls[i].Perform(WM_SETREDRAW, 0, 0);
          end
          else SkinData.Updating := False;
          InitExBorders(SkinData.SkinManager.ExtendedBorders);

          OldWndProc(Message);
          RefreshFormScrolls(Self, ListSW, False);
          if fAnimating then begin
            for i := 0 to Form.ControlCount - 1 do if Form.Controls[i].Visible then Form.Controls[i].Perform(WM_SETREDRAW, 1, 0);
            if lInted then DoLayered(Form, False);
          end;
          if fAnimating then begin
            fAnimating := False;
            if not (Form.BorderStyle in [bsSizeable, bsSingle])
              then i := SkinData.SkinManager.AnimEffects.DialogShow.Time
              else i := SkinData.SkinManager.AnimEffects.FormShow.Time;
            AnimShowControl(Form, i);
            UpdateRgn(Self, False);
            FInAnimation := False;
            if IsCached(FCommonData) //or UseAero
              then RedrawWindow(Form.Handle, nil, 0, RDW_NOERASE or RDW_UPDATENOW or RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_FRAME)
              else RedrawWindow(Form.Handle, nil, 0, RDW_ERASE or RDW_UPDATENOW or RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_FRAME);
            RgnChanging := False;
          end;
          if (Form.FormStyle = fsMDIChild) and (Form.WindowState = wsMaximized) then TsSkinProvider(MDISkinProvider).RepaintMenu;
        end
        else begin // Backgrounds must be drawn by all controls for a blinking prevent
          OldWndProc(Message);
        end;
      end;
      WM_SHOWWINDOW : begin
        if (Form.FormStyle <> fsMDIChild) then begin

          if (Message.WParam = 1) and AeroIsEnabled then begin
            if not InAnimationProcess and (GetWindowLong(Form.Handle, GWL_EXSTYLE) and WS_EX_LAYERED <> WS_EX_LAYERED) then begin
//              SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_VISIBLE); // v6.30
              RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_ALLCHILDREN or RDW_INVALIDATE);
            end;
          end;

          if TWMShowWindow(Message).Status = SW_PARENTCLOSING then begin
            if IsIconic(Form.Handle) then ShowAction := saMinimize else if IsZoomed(Form.Handle) then ShowAction := saMaximize else ShowAction := saRestore;
          end;
        end;
        OldWndProc(Message);
        if (Form.FormStyle = fsMDIChild) and (Form.WindowState = wsMaximized) then TsSkinProvider(MDISkinProvider).RepaintMenu;
        if (Form.FormStyle = fsMDIForm) then begin
          for i := 0 to Form.MDIChildCount - 1 do
            if not GetBoolMsg(Form.MDIChildren[i].Handle, AC_CTRLHANDLED)
              then AddSupportedForm(Form.MDIChildren[i].Handle);
        end;
      end;
      WM_SETTEXT : if Form.Showing and not (csCreating in Form.ControlState) and FDrawNonClientArea {and not ((Form.FormStyle = fsMdiChild) and (Form.WindowState = wsMaximized))} then begin
        if (Form.FormStyle = fsMdiChild) and (Form.WindowState = wsMaximized) then begin
          TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
          MakeCaptForm(TsSkinProvider(MDISkinProvider));
          OldWndProc(Message);
          KillCaptForm(TsSkinProvider(MDISkinProvider));
        end
        else if not AeroIsEnabled then begin
          FCommonData.BGChanged := True;
          MakeCaptForm(Self);
          OldWndProc(Message);
          KillCaptForm(Self);
{$IFDEF DELPHI6UP}          
          if Form.AlphaBlend then SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
{$ENDIF}
        end
        else begin
//          Form.Perform(WM_SETREDRAW, 0, 0);
          OldWndProc(Message);
//          Form.Perform(WM_SETREDRAW, 1, 0); // Don't work correctly under Aero
          UpdateSkinCaption(Self);
        end;
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(True);
      end else OldWndProc(Message);
      CM_ENABLEDCHANGED : begin
        OldWndProc(Message);
        if FDrawNonClientArea then begin
          SkinData.BGChanged := True;
          SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
        end;
      end;
      WM_SYSCOLORCHANGE : begin
        OldWndProc(Message);
        UpdateMenu;
      end;
      WM_CHILDACTIVATE : begin
        OldWndProc(Message);
        UpdateMenu;
        if (MDISkinProvider <> nil) and (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild <> nil)
          then if TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState = wsMaximized
            then TsMDIForm(TsSkinProvider(MDISkinProvider).MDIForm).UpdateMDIIconItem;
      end;
      WM_SIZE : begin
        if IsGripVisible(Self) then begin
          i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_GripImage);
          if FCommonData.SkinManager.IsValidImgIndex(i) then begin // If grip image is defined in skin
            X := WidthOf(FCommonData.SkinManager.ma[i].R) div FCommonData.SkinManager.ma[i].ImageCount;
            Y := HeightOf(FCommonData.SkinManager.ma[i].R) div (FCommonData.SkinManager.ma[i].MaskType + 1);

            if ((Form.ClientWidth > WidthOf(LastClientRect)) or (Form.ClientHeight > HeightOf(LastClientRect))) then begin
              if not IsCached(SkinData) then begin // Refresh rect where Grip was drawn
                if (WidthOf(LastClientRect) <> 0) then begin

                  cR.Left := LastClientRect.Right - X;
                  cR.Top := LastClientRect.Bottom - Y;
                  cR.Bottom := LastClientRect.Bottom;
                  cR.Right := LastClientRect.Right;

                  InvalidateRect(Form.Handle, @cR, not IsCached(FCommonData));
                end;
              end;
            end;
            if ((Form.ClientWidth < WidthOf(LastClientRect)) or (Form.ClientHeight < HeightOf(LastClientRect))) then begin
              cR.Left := Form.ClientWidth - X;
              cR.Top := Form.ClientHeight - Y;
              cR.Bottom := Form.ClientHeight;
              cR.Right := Form.ClientWidth;
              InvalidateRect(Form.Handle, @cR, not IsCached(FCommonData));
            end;
          end;
        end;
        if ((Form.ClientWidth < WidthOf(LastClientRect)) or (Form.ClientHeight < HeightOf(LastClientRect)) or (WidthOf(LastClientRect) = 0)) then begin
          i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_ImgTopRight);
          if i > -1 then begin
            X := WidthOf(FCommonData.SkinManager.ma[i].R) div FCommonData.SkinManager.ma[i].ImageCount;
            Y := HeightOf(FCommonData.SkinManager.ma[i].R) div (FCommonData.SkinManager.ma[i].MaskType + 1);
            cR.Left := LastClientRect.Right - X;
            cR.Top := LastClientRect.Bottom - Y;
            cR.Bottom := LastClientRect.Bottom;
            cR.Right := LastClientRect.Right;
            InvalidateRect(Form.Handle, @cR, not IsCached(FCommonData));
          end;
          i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_ImgBottomRight);
          if i > -1 then begin
            X := WidthOf(FCommonData.SkinManager.ma[i].R) div FCommonData.SkinManager.ma[i].ImageCount;
            Y := HeightOf(FCommonData.SkinManager.ma[i].R) div (FCommonData.SkinManager.ma[i].MaskType + 1);
            cR.Left := LastClientRect.Right - X;
            cR.Top := LastClientRect.Bottom - Y;
            cR.Bottom := LastClientRect.Bottom;
            cR.Right := LastClientRect.Right;
            InvalidateRect(Form.Handle, @cR, not IsCached(FCommonData));
          end;

          if FCommonData.SkinManager.gd[FCommonData.SkinIndex].GradientPercent > 0 then InvalidateRect(Form.Handle, nil, True);
        end;
        LastClientRect := Rect(0, 0, Form.ClientWidth, Form.ClientHeight);

        OldWndProc(Message);
        if not InAnimationProcess then begin
          if Form.Showing then begin
            if FormChanged and (not (IsIconic(Form.Handle) and AeroIsEnabled)) then begin
              RgnChanged := True;
              FCommonData.BGChanged := True;
              FLinesCount := -1;
              if FCommonData.FCacheBmp <> nil
                then UpdateClient := IsCached(FCommonData) and ((FCommonData.FCacheBmp.Width > Form.Width) or (FCommonData.FCacheBmp.Height > Form.Height))
                else UpdateClient := True;
              if FDrawNonClientArea then SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
              if UpdateClient and not AeroIsEnabled then InvalidateRect(Form.Handle, nil, False);
            end
            else if (Form.FormStyle = fsMDIForm) and IsCached(SkinData) then begin
              SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
            end
            else begin
              case Message.WParam of
                SIZE_MAXIMIZED : if (Form.FormStyle = fsMDIChild) and (Form.WindowState = wsMaximized) then begin // Repaint MDI child buttons
                  TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
                  TsSkinProvider(MDISkinProvider).MenuChanged := True;
                  RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
                end;
              end;
            end;
          end
          else FCommonData.BGChanged := True;
          if BorderForm <> nil then BorderForm.UpdateExBordersPos;
        end;
      end;
      WM_MOVE : begin
        KillAnimations;
        OldWndProc(Message);
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False);
      end;
      WM_ENTERMENULOOP : begin
        if (Form.FormStyle = fsMDIForm) and not InMenu and (Form.ActiveMDIChild <> nil) and (Form.ActiveMDIChild.WindowState = wsMaximized) then begin
          InMenu := True;
          if MDIIconsForm = nil then MDIIconsForm := TForm.Create(Application);
          MDIIconsForm.Tag := ExceptTag;
          MDIIconsForm.Visible := False;
          MDIIconsForm.Name := 'acMDIIcons';
          MDIIconsForm.OnPaint := MdiIcoFormPaint;

          MDIIconsForm.BorderStyle := bsNone;
          SetWindowPos(MDIIconsForm.Handle, 0, Form.BoundsRect.Right - 60 - SysBorderWidth(Form.Handle, BorderForm, False),
                                               Form.Top + CaptionHeight(False) + SysBorderWidth(Form.Handle, BorderForm, False),
                                               60,
                                               GetSystemMetrics(SM_CYMENU) - 1 + 4, SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOREDRAW);
        end;
        OldWndProc(Message);
      end;
      WM_EXITMENULOOP : begin
        InMenu := False;
        if Assigned(MDIIconsForm) then FreeAndNil(MDIIconsForm);
        OldWndProc(Message);
      end;
//      WM_DRAWITEM : if not FDrawNonClientArea then OldWndProc(Message) else AC_WMDrawItem(TWMDrawItem(Message));
      WM_NCHITTEST : begin
//        OldWndProc(Message);
//        if (CaptionHeight <> 0) and FDrawNonClientArea and (Message.Result = 0) then begin
        if (CaptionHeight = 0) or not FDrawNonClientArea then OldWndProc(Message) else begin
          Message.Result := HTProcess(TWMNCHitTest(Message));
          case Message.Result of
            Windows.HTCAPTION, Windows.HTNOWHERE, HTMENU, HTCLIENT : begin
              OldWndProc(Message);
              SetHotHT(0);
              Exit;
            end;
          end;
          if (ResizeMode = rmBorder) and (nDirection = 0) and (Message.Result in [HTCAPTION, HTLEFT..HTBOTTOMRIGHT]) then nDirection := Message.Result;
        end;
      end;
      WM_SIZING : begin
        OldWndProc(Message);
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False);
      end;
      WM_MOUSELEAVE, CM_MOUSELEAVE : begin
        SetHotHT(0);
        OldWndProc(Message);
      end;
      CM_MOUSEENTER : begin
        OldWndProc(Message);
        for i := 0 to Form.ControlCount - 1 do begin
          if (Form.Controls[i] is TsSpeedButton) and (Form.Controls[i] <> Pointer(Message.LParam)) and TsSpeedButton(Form.Controls[i]).SkinData.FMouseAbove
            then Form.Controls[i].Perform(CM_MOUSELEAVE, 0, 0)
        end;
      end;
      WM_NCCREATE : begin
        OldWndProc(Message);
        if Form.FormStyle <> fsMDIChild { v6.37 Solving of problem with menu } then PrepareForm;
      end;
      WM_NCLBUTTONDOWN : begin
        if FDrawNonClientArea then begin
          if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTOBJECT) then begin
            OldWndProc(Message);
            Exit;
          end;
          if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTTRANSPARENT)
            then TWMNCLButtonDown(Message).HitTest := BorderForm.Ex_WMNCHitTest(TWMNCHitTest(Message));
//            else if (TWMNCLButtonDown(Message).HitTest <> HTBOTTOMRIGHT) { If statusbar with grip exists }
//              then TWMNCLButtonDown(Message).HitTest := HTProcess(TWMNCHitTest(Message)); // Commented because is not required already, solved problem with overriding of HITTEST message
          case TWMNCLButtonDown(Message).HitTest of
            HTCLOSE, HTMAXBUTTON, HTMINBUTTON, HTHELP, HTCHILDCLOSE..HTCHILDMIN : begin
              if Assigned(ChildProvider) then begin
                if ((TWMNCLButtonDown(Message).HitTest = HTCHILDMIN) and not ChildProvider.SystemMenu.EnabledMin) or
                     ((TWMNCLButtonDown(Message).HitTest = HTCHILDMAX) and not ChildProvider.SystemMenu.EnabledRestore)
                        then Exit;
              end;
              SetPressedHT(TWMNCLButtonDown(Message).HitTest);
            end;
            HTMENU : begin
              OldWndProc(Message);
            end;
            HTSYSMENU : begin
              SetHotHT(0);
              if not SkinData.SkinManager.SkinnedPopups then begin // Check and Exit when DblClick and not SkinnedPopups
                Delay(200);
                Application.ProcessMessages;
                if SkinData.FUpdating then Exit;
              end;
              if Form.FormStyle = fsMDIChild then begin
                if Assigned(MDISkinProvider) then begin
                  p := FormLeftTop;
                  DropSysMenu(p.x, p.y + CaptionHeight(False) + 4);
                end;
              end
              else begin
                DropSysMenu(FormLeftTop.x + SysBorderWidth(Form.Handle, BorderForm, False), FormLeftTop.y + BorderHeight + HeightOf(IconRect) + SysBorderHeight(Form.Handle, BorderForm, False));
              end;
            end
            else if BetWeen(TWMNCLButtonDown(Message).HitTest, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin
              SetPressedHT(TWMNCLButtonDown(Message).HitTest);
              TitleButtons.Items[TWMNCHitMessage(Message).HitTest - HTUDBTN].MouseDown(TWMNCHitMessage(Message).HitTest - HTUDBTN, mbLeft, [], TWMNCHitMessage(Message).XCursor, TWMNCHitMessage(Message).YCursor);
            end
            else begin
              if IsIconic(Form.Handle) then Form.Perform(WM_SYSCOMMAND, $F012, 0) else begin
                SetHotHT(0);
                if (Form.WindowState <> wsMaximized) or (CursorToPoint(0, TWMNCLButtonDown(Message).YCursor).y > SysBorderHeight(Form.Handle, BorderForm) + CaptionHeight) then begin
                  if (ResizeMode = rmBorder) and not (TWMNCLButtonDown(Message).HitTest in [HTMENU]) then begin // MarkB
                    // If caption pressed then activate form (standard procedure)
                    if (TWMNCLButtonDown(Message).HitTest in [HTMENU, HTCAPTION]) then OldWndProc(Message);
                    bMode := not (TWMNCLButtonDown(Message).HitTest in [HTRIGHT, HTLEFT, HTBOTTOM, HTTOP, HTTOPLEFT, HTTOPRIGHT, HTBOTTOMLEFT, HTBOTTOMRIGHT]);
                    p := Point(TWMNCLButtonDown(Message).XCursor, TWMNCLButtonDown(Message).YCursor);
                    if bMode then SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MOVE, 0) else SendMessage(Form.Handle, WM_SYSCOMMAND, SC_SIZE, 0);
                    StartMove(p.X, p.Y);
                  end
                  else begin
                    OldWndProc(Message);
                    if (BorderForm <> nil) and (Form.Owner = nil) then BorderForm.UpdateExBordersPos(False); // Patch for ReportBuilder and similar windows
                  end;
                end
                else if not Form.Active then Form.SetFocus; // Focusing if maximized
              end;
            end
          end
        end
        else begin
          // Skinned sysmenu
          case TWMNCLButtonDown(Message).HitTest of
            HTSYSMENU : begin
              SetHotHT(0);
              if Form.FormStyle = fsMDIChild then begin
                if Assigned(MDISkinProvider) then begin
                  p := FormLeftTop;
                  DropSysMenu(p.x, p.y + CaptionHeight + 4);
                end;
              end
              else DropSysMenu(FormLeftTop.x + SysBorderWidth(Form.Handle, BorderForm), FormLeftTop.y + BorderHeight + HeightOf(IconRect) + SysBorderHeight(Form.Handle, BorderForm, False));
            end
            else OldWndProc(Message);
          end
        end;
      end;
      CM_ACTIVATE : begin
        OldWndProc(Message);
        if (BorderForm <> nil) then BorderForm.UpdateExBordersPos(False); // Patch for ReportBuilder dialogs and similar windows
      end;
      WM_SETTINGCHANGE : begin
        FCommonData.BGChanged := True;
        if TitleBG <> nil then FreeAndNil(TitleBG);
        OldWndProc(Message);
      end;
      WM_MOUSEMOVE : begin // MarkB
        OldWndProc(Message);
        if (DefaultManager <> nil) and not (csDesigning in DefaultManager.ComponentState) then DefaultManager.ActiveControl := 0;
        if ResizeMode = rmBorder then begin
          p := Form.ClientToScreen(Point(TWMMouseMove(Message).XPos, TWMMouseMove(Message).YPos));
          X := p.X;
          Y := p.Y;
          if bMode then begin //Move section
            if bCapture then bCapture := False;
            if bInProcess then begin
              DrawFormBorder(nleft, ntop);
              nleft := nleft + (X - nX);
              ntop := ntop + (Y - nY);
              nY := Y;
              nX := X;
              DrawFormBorder(nleft, ntop);
            end;
          end
          else begin
            //Size section
            if bCapture then begin
              nX := X;
              nY := Y;
              bCapture := False;
            end;
            if bInProcess then begin
              DrawFormBorder(0, 0);
              case nDirection of
                HTLEFT : begin
                  nleft := Form.left + X - nX;
                  if nright - nleft < nMinWidth then nleft := nright - nMinWidth;
                end;
                HTRIGHT : begin
                  nright := Form.left + Form.width + X - nX;
                  if nright - nleft < nMinWidth then nright := Form.left + nMinWidth;
                end;
                HTBOTTOM : begin
                  nbottom := Form.top + Form.height + Y - nY;
                  if nbottom - ntop < nMinHeight then nbottom := Form.top + nMinHeight;
                end;
                HTTOP : begin
                  ntop := Form.top + Y - nY;
                  if nbottom - ntop < nMinHeight then ntop := nbottom - nMinHeight;
                end;
                HTBOTTOMLEFT : begin
                  nbottom := Form.top + Form.height + Y - nY;
                  if nbottom - ntop < nMinHeight then nbottom := Form.top + nMinHeight;
                  nleft := Form.left + X - nX;
                  if nright - nleft < nMinWidth then nleft := nright - nMinWidth;
                end;
                HTTOPRIGHT : begin
                  ntop := Form.top + Y - nY;
                  if nbottom - ntop < nMinHeight then ntop := nbottom - nMinHeight;
                  nright := Form.left + Form.width + X - nX;
                  if nright - nleft < nMinWidth then nright := Form.left + nMinWidth;
                end;
                HTTOPLEFT : begin
                  ntop := Form.top + Y - nY;
                  if nbottom - ntop < nMinHeight then ntop := nbottom - nMinHeight;
                  nleft := Form.left + X - nX;
                  if nright - nleft < nMinWidth then nleft := nright - nMinWidth;
                end
                else begin
                  nbottom := Form.top + Form.height + Y - nY;
                  if nbottom - ntop < nMinHeight then nbottom := Form.top + nMinHeight;
                  nright := Form.left + Form.width + X - nX;
                  if nright - nleft < nMinWidth then nright := Form.left + nMinWidth;
                end;
              end;
              DrawFormBorder(0, 0);
            end;
          end;
        end;
      end;
      WM_NCRBUTTONDOWN : if not (TWMNCLButtonUp(Message).HitTest in [HTCAPTION, HTSYSMENU]) then OldWndProc(Message);
      WM_NCRBUTTONUP : begin
        if {FDrawNonClientArea Skinned sysmenu and} HaveBorder(Self){SkinData.SkinManager.SkinnedPopups} then begin
          if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTTRANSPARENT)
            then TWMNCLButtonDown(Message).HitTest := BorderForm.Ex_WMNCHitTest(TWMNCHitTest(Message))
            else TWMNCLButtonDown(Message).HitTest := HTProcess(TWMNCHitTest(Message));
          case TWMNCLButtonUp(Message).HitTest of
            HTCAPTION, HTSYSMENU : begin
              SetHotHT(0);
              DropSysMenu(TWMNCLButtonUp(Message).XCursor, TWMNCLButtonUp(Message).YCursor);
            end
          end;
          Exit;
        end
        else OldWndProc(Message);
      end;
      WM_NCLBUTTONUP, WM_LBUTTONUP: if FDrawNonClientArea then begin
        if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTTRANSPARENT)
          then TWMNCLButtonDown(Message).HitTest := BorderForm.Ex_WMNCHitTest(TWMNCHitTest(Message));
//            else TWMNCLButtonDown(Message).HitTest := HTProcess(TWMNCHitTest(Message));

        case TWMNCHitMessage(Message).HitTest of
          HTCLOSE : if biClicked then begin
            ButtonClose.State := 0;
            SendMessage(Form.Handle, WM_SYSCOMMAND, SC_CLOSE, 0);
          end;
          HTMAXBUTTON : if (SystemMenu.EnabledMax or (Form.WindowState = wsMaximized) and SystemMenu.EnabledRestore) then begin
            if biClicked then begin
              if Form.FormStyle = fsMDIChild then TsSkinProvider(MDISkinProvider).FCommonData.BeginUpdate;
              SetHotHT(0);
              if Form.WindowState = wsMaximized then begin
                if Form.FormStyle <> fsMDIChild then Form.WindowState := wsNormal else ChildProvider := nil;
                SendMessage(Form.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
                Form.Repaint
              end
              else begin
                if Form.FormStyle = fsMDIChild
                  then ChildProvider := nil;
                SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
              end;
              SystemMenu.UpdateItems;
            end
            else begin
              SetHotHT(0);
              OldWndProc(Message);
            end;
          end;
          HTMINBUTTON : if biClicked then begin
            if BorderForm <> nil
              then p := Point(TWMMouse(Message).XPos - BorderForm.AForm.Left, TWMMouse(Message).YPos - BorderForm.AForm.Top)
              else p := CursorToPoint(TWMMouse(Message).XPos, TWMMouse(Message).YPos);
            if PtInRect(ButtonMin.Rect, p) then begin
              SetHotHT(0);
              if (Application.MainForm = Form) then begin
//                Application.Minimize; !!!
                SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0); 
              end
              else if IsIconic(Form.Handle) then begin
                SendMessage(Form.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
              end
              else SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
              FCommonData.BGChanged := True;
              RegionChanged := True;
            end
            else OldWndProc(Message);
          end
          else begin
            SetHotHT(0);
            OldWndProc(Message);
          end;
          HTHELP : if biClicked then begin
            SendMessage(Form.Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
            SetHotHT(0);
            SystemMenu.UpdateItems;
            Form.Perform(WM_NCPAINT, 0, 0);
          end else SetHotHT(0);
          // MDI child buttons
          HTCHILDCLOSE : if biClicked then begin
            SendMessage(Form.ActiveMDIChild.Handle, WM_SYSCOMMAND, SC_CLOSE, 0);
            SetHotHT(0, False);
          end;
          HTCHILDMAX : begin
            if biClicked then SendMessage(Form.ActiveMDIChild.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
            SetHotHT(0, False);
          end;
          HTCHILDMIN : begin
            if biClicked then begin
              TsSkinProvider(MDISkinProvider).FCommonData.BeginUpdate;
              SendMessage(Form.ActiveMDIChild.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
            end;
            SetHotHT(0);
          end
          else if BetWeen(TWMNCHitMessage(Message).HitTest, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin
            if biClicked then TitleButtons.Items[TWMNCHitMessage(Message).HitTest - HTUDBTN].MouseUp(TWMNCHitMessage(Message).HitTest - HTUDBTN, mbLeft, [], TWMNCHitMessage(Message).XCursor, TWMNCHitMessage(Message).YCursor);
            SetHotHT(0);
          end
          else begin
            if IsIconic(Form.Handle) then begin
              if Assigned(MDISkinProvider) then DropSysMenu(acMousePos.x + FormLeftTop.X, acMousePos.y) else OldWndProc(Message);
            end
            else begin
              if (ResizeMode = rmBorder) and (Form.WindowState <> wsMaximized) and bInProcess then begin // MarkB
                //Common section
                p := Form.ClientToScreen(Point(TWMNCLButtonDown(Message).XCursor, TWMNCLButtonDown(Message).YCursor));
                StopMove(p.x, p.y);
                ReleaseCapture;
              end else OldWndProc(Message);
            end;
          end
        end;
      end
      else OldWndProc(Message);
      WM_ENTERIDLE : begin
        Message.Result := 0;
        Exit;
      end;
      CM_FLOAT : begin
        OldWndProc(Message);
        if ListSW <> nil then FreeAndNil(ListSW);
        SendAMessage(Form.Handle, AC_REFRESH, Cardinal(SkinData.SkinManager));
      end;
      CM_MENUCHANGED : begin
        if not (fsCreating in Form.FormState) and Form.Visible then MenuChanged := True; // Menu may be invisible after form opening ????
        OldWndProc(Message);
      end;
      WM_PRINT : begin
        if not Form.Visible or (csLoading in ComponentState) or (fsCreating in Form.FormState) or (csDestroying in Form.ComponentState) then Exit;
        if {FCommonData.Updating or} ((Form.FormStyle = fsMDIChild) and (MDISkinProvider <> nil) and
                Assigned(TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) and
                  (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState = wsMaximized)
                    and (Form <> TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild)) then Exit;
        if not MenusInitialized then begin
          if UpdateMenu then MenusInitialized := True;
        end;
        DC := TWMPaint(Message).DC;
        FCommonData.Updating := False;
        if BorderForm <> nil then begin
          if FCommonData.BGChanged then PaintAll;
          BitBlt(DC, 0, 0, FCommonData.FCacheBmp.Width, FCommonData.FCacheBmp.Height, FCommonData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);
          MoveWindowOrg(DC, OffsetX, OffsetY + integer(MenuHeight <> 0));// + 1);
          GetClientRect(Form.Handle, cR);
          IntersectClipRect(DC, 0, 0, WidthOf(cR), HeightOf(cR));
          if (Form.FormStyle <> fsMDIForm) then PaintControls(DC, Form, True, Point(0, 0));
//          PaintForm(DC);
        end
        else begin
          if FDrawNonClientArea then begin
            if not HaveBorder(Self) and IsSizeBox(Form.Handle) then begin
              if FCommonData.BGChanged then PaintAll;
              i := Form.BorderWidth + 3;
              BitBlt(DC, 0, 0, Form.Width, i, FCommonData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY); // Title and menu line update
              BitBlt(DC, 0, i, i, FCommonData.FCacheBmp.Height, FCommonData.FCacheBmp.Canvas.Handle, 0, i, SRCCOPY); // Left border update
              BitBlt(DC, i, Form.Height - i, Form.Width - i, i, FCommonData.FCacheBmp.Canvas.Handle, i, Form.Height - i, SRCCOPY); // Bottom border update
              BitBlt(DC, FCommonData.FCacheBmp.Width - i, i, i, FCommonData.FCacheBmp.Height, FCommonData.FCacheBmp.Canvas.Handle, FCommonData.FCacheBmp.Width - i, i, SRCCOPY); // Right border update
            end
            else PaintCaption(DC);
          end;
          MoveWindowOrg(DC, OffsetX, OffsetY);
          GetClientRect(Form.Handle, cR);
          IntersectClipRect(DC, 0, 0, WidthOf(cR), HeightOf(cR));

          if SkinData.CtrlSkinState and ACS_FAST <> ACS_FAST then PaintForm(DC) else begin
            SavedDC := SaveDC(DC);
            ExcludeControls(DC, Form, actGraphic, 0, 0);
            PaintForm(DC);
            RestoreDC(DC, SavedDC);
            if (Form.FormStyle <> fsMDIForm) then PaintControls(DC, Form, True, Point(0, 0));
          end;
        end;

        if Form.FormStyle = fsMDIForm then SendMessage(Form.ClientHandle, WM_PRINT, longint(DC), 0);

        if Assigned(Form.OnPaint) then begin
          Form.Canvas.Handle := DC;
          Form.OnPaint(Form);
          Form.Canvas.Handle := 0;
        end;
      end;
      WM_PRINTCLIENT : ;
      CM_INVALIDATE, 147, 45132, 48205 : Message.Result := 0;
      WM_NCPAINT : if DrawNonClientArea and not (InAnimationProcess and (Form.FormStyle = fsMDIChild){liondev}) then begin
        if IsIconic(Form.Handle) then FCommonData.BGChanged := True;
        if fAnimating or not Form.Showing or (csLoading in ComponentState) or (SystemMenu = nil{not initialized}) then Exit;

        if not Assigned(Adapter) then AdapterCreate; // Preventing of std controls BG erasing before hooking

{        if AeroIsEnabled and (Tag = -97) then begin // If WM_PAINT was not performed (when TsSkinProvider wasn't placed before form showing)
          Tag := 0;
          if Assigned(Adapter) then Adapter.AddAllItems else AdapterCreate;
          InvalidateRect(Form.Handle, nil, True);
          RedrawWindow(Form.Handle, nil, 0, RDW_ALLCHILDREN or RDW_ERASE or RDW_INVALIDATE or RDW_UPDATENOW);
        end;}

        if SkinData.FCacheBmp = nil // Preventing of painting before ExBorders, usually when MainMenu exists
          then InitExBorders(SkinData.SkinManager.ExtendedBorders);

        AC_WMNCPaint;
        Message.Result := 0;
      end
      else OldWndProc(Message);
      WM_ERASEBKGND : if Form.Showing then begin
        if not (csPaintCopy in Form.ControlState) and (Message.WParam <> Message.LParam {PerformEraseBackground, TntSpeedButtons}) then begin
          if not IsCached(FCommonData) or ((Form.FormStyle = fsMDIForm) and (Form.ActiveMDIChild <> nil) and (Form.ActiveMDIChild.WindowState = wsMaximized)) then begin
            if (Form.FormStyle = fsMDIChild) and (FCommonData.FCacheBmp <> nil) then begin
              GetClientRect(TsSkinProvider(MDISkinProvider).Form.Handle, cR);
              if (PtInRect(cR, Form.BoundsRect.TopLeft) and PtInRect(cR, Form.BoundsRect.BottomRight)) then begin
                FCommonData.FCacheBmp.Height := min(FCommonData.FCacheBmp.Height, CaptionHeight + SysBorderHeight(Form.Handle, BorderForm) + LinesCount * MenuHeight + 1);
                FCommonData.BGChanged := True;
              end
            end;
            if not AeroIsEnabled then AC_WMEraseBkGnd(TWMPaint(Message).DC) else begin
              if (GetClipBox(TWMPaint(Message).DC, cR) = NULLREGION) or (WidthOf(cR) = 0) or (HeightOf(cR) = 0) then begin
                DC := GetDC(Form.Handle);
              end
              else DC := TWMPaint(Message).DC;
              AC_WMEraseBkGnd(DC);
            end;
            if MDICreating then begin
              MDICreating := False;
              if Form.FormStyle = fsMDIChild then begin
                ChildProvider := Self;
              end;
            end;
{            if not FCommonData.FUpdating then begin
              // If have child control with Align = clClient // If client area is not visible // v6.12
              if (GetClipBox(TWMPaint(Message).DC, cR) = NULLREGION) or (WidthOf(cR) = 0) or (HeightOf(cR) = 0) then begin
                SetParentUpdated(Form);
                Exit;
              end;
            end}
          end
          else begin
            if not FCommonData.FUpdating then begin
              // If have child control with Align = clClient // If client area is not visible // v6.12
              if (GetClipBox(TWMPaint(Message).DC, cR) = NULLREGION) or (WidthOf(cR) = 0) or (HeightOf(cR) = 0) then begin
                SetParentUpdated(Form);
                Exit;
              end;
            end
          end;
        end
        else if (Message.WParam <> 0) then begin // From PaintTo 
          if FCommonData.BGChanged then PaintAll;
          if not FCommonData.BGChanged then begin
            if IsCached(FCommonData)
              then BitBlt(TWMPaint(Message).DC, 0, 0, Form.Width, Form.Height, FCommonData.FCacheBmp.Canvas.Handle, OffsetX, OffsetY, SRCCOPY)
              else FillDC(TWMPaint(Message).DC, Rect(0, 0, Form.Width, Form.Height), GetControlColor(Form.Handle));
          end;
        end;
        Message.Result := 1;
        {$IFDEF CHECKXP}
//        if UseThemes and ThemeServices.ThemesEnabled {and StdBgIsUsed} and not InAnimationProcess then OldWndProc(Message) // Draw BG for controls with ParentBackground if exists
        {$ENDIF}
      end
      else OldWndProc(Message);
      WM_PAINT : begin
        if (csPaintCopy in Form.ControlState) then Exit; // Implemented in WM_ERASEBKGND
        if IsCached(FCommonData) {!!!and not AeroIsEnabled} then begin
          if Form.Showing then begin
            OurPaintHandler(TWMPaint(Message));
            if MDICreating then begin
              MDICreating := False;
              if Form.FormStyle = fsMDIChild then begin
                SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
//                Form.WindowState := wsMaximized;
              end;
            end;
            if (Form.FormStyle = fsMDIForm) then begin
              if TWMPaint(Message).DC = 0 then TWMPaint(Message).DC := GetDC(Form.Handle);
              PaintControls(TWMPaint(Message).DC, Form, True, Point(0, 0));
            end;
            Message.Result := 0;
          end
          else if (BorderForm <> nil) {$IFDEF DELPHI7UP} or Form.AlphaBlend {$ENDIF} then OldWndProc(Message);
        end
        else begin
          if Form.Showing then begin
            if not (csDestroying in ComponentState) and SkinData.BGChanged {v6.41} {and AeroInvalidate} then begin // Background update in desight-time
//              AeroInvalidate := False;
              InvalidateRect(Form.Handle, nil, True); // Background update (for repaint of graphic controls)
            end;
            BeginPaint(Form.Handle, PS);
            EndPaint(Form.Handle, PS);
            Message.Result := 0;
          end
          else OldWndProc(Message);
        end;
        if not InAnimation(Self) and Assigned(Form.OnPaint) then Form.OnPaint(Form);
      end;
{$IFNDEF ALITE}
{$IFDEF D2005}
      CM_RECREATEWND : if acTaskBarChanging then Exit;
{$ENDIF}
{$ENDIF}
      WM_NCACTIVATE : if not (csDestroying in ComponentState) then begin
        FormActive := TWMNCActivate(Message).Active;
        if not FormActive and (ShowAction = saMaximize) then begin // <<<<< Caption blinking removing
          ShowAction := saIgnore;
        end
        else if not (ShowAction = saMaximize) then begin
          FCommonData.BGChanged := True;
          FCommonData.Updating := False;
        end
        else FCommonData.Updating := True;                         // >>>>> Caption blinking removing

        if Form.Showing then begin
          if FormActive <> (TWMActivate(Message).Active <> WA_INACTIVE) then FCommonData.BGChanged := True;
          if AeroIsEnabled then begin
            AFlags := GetWindowLong(Form.Handle, GWL_STYLE);
            SetWindowLong(Form.Handle, GWL_STYLE, AFlags and not WS_VISIBLE);
            if fAnimating
              then SendMessage(Form.Handle, WM_SETREDRAW, 0, 0)
          end
          else begin
{            if SkinData.SkinManager.ExtendedBorders then begin
              AFlags := GetWindowLong(Form.Handle, GWL_STYLE);
              SetWindowLong(Form.Handle, GWL_STYLE, AFlags and not WS_VISIBLE);
            end;}
            if fAnimating
              then SendMessage(Form.Handle, WM_SETREDRAW, 0, 0)
              else MakeCaptForm(Self);
          end;

          if (BorderForm <> nil) and not SkinData.SkinManager.AnimEffects.FormShow.Active and not AeroIsEnabled then begin // Forbid a borders painting by system
            UpdateRgn(Self, False);
          end;

          OldWndProc(Message);

          if AeroIsEnabled then begin
            if fAnimating
              then SendMessage(Form.Handle, WM_SETREDRAW, 1, 0);
            SetWindowLong(Form.Handle, GWL_STYLE, AFlags);
          end
          else begin
{            if SkinData.SkinManager.ExtendedBorders then begin
              SetWindowLong(Form.Handle, GWL_STYLE, AFlags);
            end;}
            if fAnimating
              then SendMessage(Form.Handle, WM_SETREDRAW, 1, 0)
              else KillCaptForm(Self);
          end;
        end
        else OldWndProc(Message);
        if Assigned(Form) and (Form.Visible) and (Form.FormStyle = fsMDIChild) and (fsCreatedMDIChild in Form.FormState) and
                   (fsshowing in Form.FormState) and Assigned(MDISkinProvider) and Assigned(TsSkinProvider(MDISkinProvider).MDIForm) then begin

          if SystemMenu = nil then PrepareForm; // If not intitialized (occurs when Scaled = False)
          TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
          TsSkinProvider(MDISkinProvider).FLinesCount := -1;
          TsMDIForm(TsSkinProvider(MDISkinProvider).MDIForm).UpdateMDIIconItem;

          SendMessage(TsSkinProvider(MDISkinProvider).Form.Handle, WM_NCPAINT, 0, 0);
          SendMessage(TsSkinProvider(MDISkinProvider).Form.ClientHandle, WM_NCPAINT, 0, 0);
        end;
        if GetWindowLong(Form.Handle, GWL_EXSTYLE) and WS_EX_LAYERED = WS_EX_LAYERED then SendMessage(Form.Handle, WM_NCPAINT, 0, 0);

        if (csCreating in Form.ControlState) then Exit;

        if HaveBorder(Self) then begin
          if MDIButtonsNeeded then begin
            if (TWMActivate(Message).Active <> WA_INACTIVE) or (Form.ActiveMDIChild.Active) then begin
              FormActive := (TWMActivate(Message).Active <> WA_INACTIVE) or (Form.ActiveMDIChild.Active);
              FLinesCount := -1;
            end;
          end
          else if FormActive <> (TWMActivate(Message).Active <> WA_INACTIVE) then begin
            FormActive := (TWMActivate(Message).Active <> WA_INACTIVE);
            FLinesCount := -1;
          end;
        end;

//        if Form.FormStyle = fsMDIChild then begin// System default proc calling enables blinking
        SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
        if BorderForm <> nil then BorderForm.UpdateExBordersPos;
//        end;

        if not (csDesigning in SkinData.SkinManager.ComponentState) then InitMenuItems(SkinData.Skinned); // Update after skinning in run-time
        if not MenusInitialized then begin
          if UpdateMenu then MenusInitialized := True;
        end;
        if FCommonData.Skinned and (Adapter = nil) then AdapterCreate;
{        if IsIconic(Form.Handle) and not AeroIsEnabled then begin // Aero
//        if IsIconic(Form.Handle) then begin
          FCommonData.BGChanged := True;
          SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
        end;}
//        if IsCached(FCommonData) and not FCommonData.BGChanged then SetParentUpdated(Form); // Updating of frames which are not refreshed
//        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False); // Update z-order ( BDS )
      end
      else OldWndProc(Message);
{      WM_ACTIVATEAPP : begin
        OldWndProc(Message);
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False); // Update z-order ( BDS )
      end;                       }
      WM_MDIACTIVATE, WM_MDIDESTROY : begin
        OldWndProc(Message);
        if (Form.FormStyle = fsMDIChild) and (Form.WindowState <> wsMaximized) and Assigned(MDISkinProvider)
              and not (csDestroying in TsSkinProvider(MDISkinProvider).ComponentState) then begin
          MenusInitialized := False;
          TsSkinProvider(MDISkinProvider).Menuchanged := True;
          TsSkinProvider(MDISkinProvider).SkinData.BGChanged := True;
          TsSkinProvider(MDISkinProvider).FLinesCount := -1;
          SendMessage(TsSkinProvider(MDISkinProvider).Form.Handle, WM_NCPAINT, 0, 0);
        end;
        ChildProvider := Self;
      end;
      WM_ACTIVATE : if Form.Showing then begin
{
        if AeroIsEnabled then begin
          AFlags := GetWindowLong(Form.Handle, GWL_STYLE);
          SetWindowLong(Form.Handle, GWL_STYLE, AFlags and not WS_VISIBLE);
        end;
v6.30}
        OldWndProc(Message);
        if (ListSW = nil) and FDrawNonClientArea then RefreshFormScrolls(Self, ListSW, False);
//        if AeroIsEnabled then SetWindowLong(Form.Handle, GWL_STYLE, AFlags or WS_VISIBLE);
        if not (csCreating in Form.ControlState) then begin
          FLinesCount := -1;
          if Form.FormStyle = fsMDIChild then begin// !! System calling enables blinking
            for i := 0 to TsSkinProvider(MDISkinProvider).Form.MDIChildCount - 1 do begin
              if (TsSkinProvider(MDISkinProvider).Form.MDIChildren[i] <> Form) and (TsSkinProvider(MDISkinProvider).Form.MDIChildren[i].Visible)
                then SendMessage(TsSkinProvider(MDISkinProvider).Form.MDIChildren[i].Handle, WM_NCPAINT, 0, 0);
            end;
            TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
          end;
          if not (csDesigning in SkinData.SkinManager.ComponentState) then InitMenuItems(SkinData.Skinned); // Update after skinning in run-time
          if Assigned(SystemMenu) then SystemMenu.UpdateItems;
          if (Form.BorderStyle = bsNone) then SetParentUpdated(Form);
        end;
      end else OldWndProc(Message);
      CM_VISIBLECHANGED : begin
        OldWndProc(Message);
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False); // v6.33
        if (Message.WParam = 0) then begin

          if Assigned(SkinData) and Assigned(SkinData.FCacheBmp) and not (csDestroying in Form.ComponentState) then begin
            SkinData.FCacheBmp.Width := 0;
            SkinData.FCacheBmp.Height := 0;
          end;
          KillAnimations;
        end
        else begin
          if Form.Parent <> nil then SetParentUpdated(Form); // Updating of controls which are not refreshed
        end;
      end;
      WM_NCLBUTTONDBLCLK : begin
        if (ResizeMode = rmBorder) and bInProcess then begin
          p := Form.ClientToScreen(Point(TWMMouse(Message).XPos, TWMMouse(Message).YPos));
          StopMove(p.x, p.y);
          ReleaseCapture;
          bInProcess := False;
        end;
        DoStartMove := False;
        case TWMNCHitMessage(Message).HitTest of
          HTSYSMENU : begin
            if not SkinData.SkinManager.SkinnedPopups then // Check and Exit when DblClick and not SkinnedPopups
              SkinData.FUpdating := True;
            Form.Close;
          end;
          HTCAPTION : begin
            if SystemMenu.VisibleClose and (SystemMenu.EnabledMax or SystemMenu.EnabledRestore) or not HaveBorder(Self) and IsIconic(Form.Handle) then begin
              if (Form.WindowState = wsMaximized) or IsIconic(Form.Handle)
                then SendMessage(Form.Handle, WM_SYSCOMMAND, SC_RESTORE, 0)
                else SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
              SystemMenu.UpdateItems;
            end;
            TWMNCHitMessage(Message).HitTest := 0;
          end;
        end;
      end;
      WM_MEASUREITEM : begin
        if (Form.FormStyle = fsMDIForm) and (MDISkinProvider = Self) then MDISkinProvider := Self;
        if not (Form.FormStyle = fsMDIChild) and Assigned(Form.Menu) and Assigned(SkinData.SkinManager) and (PMeasureItemStruct(Message.LParam)^.CtlType = ODT_MENU) then begin
          mi := Form.Menu.FindItem(PMeasureItemStruct(Message.LParam)^.itemID, fkCommand);
          if mi <> nil then SkinData.SkinManager.SkinableMenus.InitItem(mi, True);
        end;
        OldWndProc(Message);
      end;
      WM_SYSCOMMAND : begin
        if Message.WParamLo = $F012 then Form.Repaint;               // Faster switching between a forms (avoid of system delay)
        if (ResizeMode = rmBorder) and not bInProcess then begin     // MarkB
          if ($FFF0 and Message.WParam = SC_MOVE) then begin         // Move section
            SetCapture(Form.handle);
            bCapture := True; bMode := True;
          end
          else if ($FFF0 and Message.WParam = SC_SIZE) then begin    // Size section
            SetCapture(Form.handle);
            nDirection := 0;
            bCapture := True; bMode := False;
          end;
        end;

        case Form.FormStyle of
          fsMDIChild : begin
            UpdateClient := (Form.WindowState = wsMaximized) and (Message.WParam <> SC_MAXIMIZE) and (Form.WindowState <> wsNormal);
            if UpdateClient then TsSkinProvider(MDISkinProvider).FCommonData.BeginUpdate; // Speed rising
            case $FFF0 and Message.WParam of
              SC_CLOSE : begin

                if (MDISkinProvider <> nil) and Assigned(TsSkinProvider(MDISkinProvider).MDIForm) then begin
                  if UpdateClient then UpdateMainForm;
                end; // If CloseQuery used then must be repainted before

                TsSkinProvider(MDISkinProvider).InMenu := True;
                OldWndProc(Message);
                SetHotHT(0, False);
                TsSkinProvider(MDISkinProvider).InMenu := False;

                if (MDISkinProvider <> nil) and Assigned(TsSkinProvider(MDISkinProvider).MDIForm) then if UpdateClient then UpdateMainForm;
                Exit;
              end;
              SC_KEYMENU : ;
              SC_RESTORE : begin
                if Form.WindowState = wsMinimized then UpdateClient := True;
                if MDICreating then Exit;
                ForbidDrawing(Self, True);
                OldWndProc(Message);
                SkinData.BGChanged := True;

                SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) and not WS_SYSMENU); 
                PermitDrawing(Self, True);
                RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_ERASE or RDW_INVALIDATE or RDW_UPDATENOW);

                // Updating of childs
                for i := 0 to TsSkinProvider(MDISkinProvider).Form.MDIChildCount - 1 do if TsSkinProvider(MDISkinProvider).Form.MDIChildren[i] <> Form then begin
                  if TsSkinProvider(MDISkinProvider).Form.MDIChildren[i].WindowState = wsMaximized then TsSkinProvider(MDISkinProvider).Form.MDIChildren[i].WindowState := wsNormal;
                  RedrawWindow(TsSkinProvider(MDISkinProvider).Form.MDIChildren[i].Handle, nil, 0, RDW_FRAME or RDW_INTERNALPAINT or RDW_ERASE or RDW_UPDATENOW);
                end;
                if UpdateClient then UpdateMainForm;
                SystemMenu.UpdateItems(True);
                Exit;
              end;
              SC_MINIMIZE : begin
                OldWndProc(Message);
                if UpdateClient then UpdateMainForm;
                SystemMenu.UpdateItems(True);
                FreeAndNil(TitleBG);
                FCommonData.BGChanged := True;
                UpdateMainForm;
                Exit;
              end;
              SC_MAXIMIZE : begin
                ChildProvider := Self;
                SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) and not WS_VISIBLE); // v6.37
//                ForbidDrawing(Self, True);
                OldWndProc(Message);
                SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_VISIBLE);
//                PermitDrawing(Self, True);
                RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_INTERNALPAINT or RDW_ERASE or RDW_UPDATENOW);

                if Assigned(TsSkinProvider(MDISkinProvider).MDIForm) then UpdateMainForm;
                SystemMenu.UpdateItems(True);
                Exit;
              end
              else OldWndProc(Message);
            end;
            if MDISkinProvider <> nil then TsSkinProvider(MDISkinProvider).FCommonData.EndUpdate;
          end;
          fsMDIForm : begin
            OldWndProc(Message);
            case Message.WParam of
              SC_MAXIMIZE, SC_RESTORE, SC_MINIMIZE : begin
                TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
                TsSkinProvider(MDISkinProvider).FLinesCount := -1;
                SendMessage(TsSkinProvider(MDISkinProvider).Form.Handle, WM_NCPAINT, 0, 0);
              end;
            end;
          end
          else begin
            OldWndProc(Message);
            case Message.WParam of
              SC_KEYMENU : if (TWMSysCommand(Message).Key = VK_SPACE) and SystemMenu.VisibleClose{(bisystemMenu in Form.BorderIcons)} and HaveBorder(Self)
                then DropSysMenu(FormLeftTop.x + SysBorderWidth(Form.Handle, BorderForm), FormLeftTop.y + BorderHeight + HeightOf(IconRect));
              SC_MAXIMIZE, SC_RESTORE : begin
                if SystemMenu.VisibleMax then CurrentHT := HTMAXBUTTON;
                SetHotHT(0);
                if (Message.WParam = SC_RESTORE) then begin
                  if not HaveBorder(Self) then begin
                    FCommonData.BGChanged := True;
                    RegionChanged := True;
                    SetWindowRgn(Form.Handle, 0, True);
                  end
                  else begin
                    FCommonData.BGChanged := True;
                    RegionChanged := True;
                    RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE);
                  end
                end;
              end;
              SC_MINIMIZE : if Assigned(FCommonData.FCacheBmp) then begin
                FCommonData.FCacheBmp.Width := 0;
                FCommonData.FCacheBmp.Height := 0;
//                if (Application.MainForm = Form) then Application.Minimize; v6.10
              end;
            end;
          end;
        end;
      end;
      WM_WINDOWPOSCHANGING : begin
        if not RgnChanging then begin
          if not IsZoomed(Form.Handle) and FScreenSnap and ((TWMWindowPosChanging(Message).WindowPos^.X <> 0) or (TWMWindowPosChanging(Message).WindowPos^.Y <> 0)) then begin
            with TWMWindowPosChanging(Message).WindowPos^ do begin
              cR := acWorkRect(Form);
              i := DiffBorder(BorderForm);
              HandleEdge(x, cR.Right, FSnapBuffer, Form.Width + i);
              HandleEdge(y, cR.Bottom, FSnapBuffer, Form.Height + i);
              HandleEdge(x, cR.Left, FSnapBuffer, -i);
              HandleEdge(y, cR.Top, FSnapBuffer, -DiffTitle(BorderForm));
            end;
          end;
          OldWndProc(Message);
        end;
      end;
      WM_WINDOWPOSCHANGED : begin
        OldWndProc(Message);
        FSysExHeight := IsZoomed(Form.Handle) and (BorderForm <> nil) and (CaptionHeight < CaptionHeight(False) + 4);//SysBorderWidth(Form.Handle, BorderForm, False));
        if BorderForm <> nil then BorderForm.UpdateExBordersPos(False); // Update z-order ( BDS )
      end;
      CM_COLORCHANGED : if SkinData.CustomColor then begin
        if not (csCreating in Form.ControlState) then FCommonData.BGChanged := True;
        OldWndProc(Message);
      end;
      WM_CREATE : begin
        if Assigned(TitleBG) then FreeAndNil(TitleBG);

        if (Form.FormStyle = fsMDIChild) and (MDISkinProvider = nil)
          then AddSupportedForm(Application.MainForm.Handle);

        if (Form.FormStyle = fsMDIChild) and
             ((TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) <> nil) and
               (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState = wsMaximized) then begin
          MDICreating := True;
        end else MDICreating := False;
        OldWndProc(Message);
        if (Form.FormStyle <> fsMDIChild) then PrepareForm; // Problem with MDI menu solving
      end;
      WM_PARENTNOTIFY : if not (csLoading in ComponentState) and not (csLoading in Form.ComponentState) and ((Message.WParam and $FFFF = WM_CREATE) or (Message.WParam and $FFFF = WM_DESTROY)) then begin
        OldWndProc(Message);
        if Assigned(Adapter) and (Message.WParamLo = WM_CREATE) then TacCtrlAdapter(Adapter).AddAllItems;
        acM := MakeMessage(SM_ALPHACMD, MakeWParam(0, AC_GETSKINSTATE), 1, 0);
        AlphaBroadCast(Form, acM);
        if FDrawNonClientArea
          then UpdateScrolls(ListSW, True);
      end
      else OldWndProc(Message);
      WM_NOTIFY : begin
        OldWndProc(Message);
        case TWMNotify(Message).NMHdr^.code of
          TCN_SELCHANGE : if Adapter <> nil then TacCtrlAdapter(Adapter).AddAllItems;
        end;
      end;
      CM_CONTROLLISTCHANGE : begin
        if (TCMControlListChange(Message).Control <> nil) then begin
          OldWndProc(Message);
          if (TCMControlListChange(Message).Control is TWinControl) then begin
            if Adapter <> nil then TacCtrlAdapter(Adapter).AddNewItem(TWinControl(TCMControlListChange(Message).Control));
            acM := MakeMessage(SM_ALPHACMD, MakeWParam(0, AC_GETSKINSTATE), 1, 0);
            AlphaBroadCast(TWinControl(TCMControlListChange(Message).Control), acM);
          end;
          TCMControlListChange(Message).Control.Perform(SM_ALPHACMD, MakeWParam(0, AC_GETSKINSTATE), 1);
        end
        else OldWndProc(Message);
      end
      else OldWndProc(Message);
    end;
  end;
end;

procedure TsSkinProvider.PaintBorderIcons;
var
  i, b, index, mi, Offset, x, y : integer;
  CI : TCacheInfo;
  procedure PaintButton(var Btn : TsCaptionButton; var Index : integer; SkinIndex : integer; BtnEnabled : boolean; UserBtn : TsTitleButton = nil);
  var
    w : integer;
  begin
    if UserBtn = nil then w := SysButtonWidth(Btn) else w := UserButtonWidth(UserBtn);
    Btn.Rect.Left := Btn.Rect.Right - w;
    if Btn.HaveAlignment { If not user button and not small } and (FCommonData.SkinManager.SkinData.BIVAlign = 1) { Top aligning } then begin
      Btn.Rect.Top := ShadowSize.Top;
      if (Form.WindowState = wsMaximized) then begin
        inc(Btn.Rect.Top, SysBorderWidth(Form.Handle, BorderForm, False) - 1{!!!} {4 - 1});

        if (BorderForm <> nil) then begin
          if (FCommonData.SkinManager.SkinData.ExTitleHeight <> FCommonData.SkinManager.SkinData.ExMaxHeight)
            then Btn.Rect.Top := Btn.Rect.Top + FCommonData.SkinManager.SkinData.ExTitleHeight - FCommonData.SkinManager.SkinData.ExMaxHeight;

          if (SkinData.SkinManager.SkinData.ExDrawMode = 1)
            then inc(Btn.Rect.Top, FCommonData.SkinManager.SkinData.ExCenterOffs);

        end;
      end;
      Btn.Rect.Bottom := Btn.Rect.Top + ButtonHeight;
    end
    else begin // va_center
      Btn.Rect.Top := (CaptionHeight - ButtonHeight + SysBorderHeight(Form.Handle, BorderForm)) div 2 + ShadowSize.Top;
      if (BorderForm <> nil) and (SkinData.SkinManager.SkinData.ExDrawMode = 1)
        then inc(Btn.Rect.Top, FCommonData.SkinManager.SkinData.ExCenterOffs);

      if IsZoomed(Form.Handle) then begin
        dec(Btn.Rect.Top, 2{4 div 2} - integer(BorderForm = nil) * 2);

        if (BorderForm <> nil) and (FCommonData.SkinManager.SkinData.ExTitleHeight <> FCommonData.SkinManager.SkinData.ExMaxHeight) then begin
          Btn.Rect.Top := Btn.Rect.Top + (FCommonData.SkinManager.SkinData.ExTitleHeight - FCommonData.SkinManager.SkinData.ExMaxHeight - FCommonData.SkinManager.SkinData.ExCenterOffs) div 2 - 2;
        end;
      end;

      if (BorderForm <> nil) and (Form.WindowState = wsMaximized) then inc(Btn.Rect.Top, SysBorderWidth(Form.Handle, BorderForm, False) div 2);
      if BigButtons(Self) and (ButtonHeight < 16) then inc(Btn.Rect.Top, 2);
      Btn.Rect.Bottom := Btn.Rect.Top + ButtonHeight;
    end;

    if SkinIndex > -1 then DrawSkinGlyph(FCommonData.FCacheBmp, Point(Btn.Rect.Left, Btn.Rect.Top),
      Btn.State * integer(Btn.Timer = nil), 1 + integer(not FormActive or not BtnEnabled) * integer((Btn.State = 0) or (Btn.Timer <> nil)), FCommonData.SkinManager.ma[SkinIndex], MakeCacheInfo(SkinData.FCacheBmp));

    inc(Index);
  end;
begin
  if not HaveBorder(Self) then Exit;
  b := 1;
  Offset := CaptionWidth{ - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing v6.41 }- FCommonData.SkinManager.SkinData.BIRightMargin - ShadowSize.Right;
  dec(Offset, SysBorderWidth(Form.Handle, BorderForm));
  RestoreBtnsBG;
  if Assigned(SystemMenu) and SystemMenu.VisibleClose then begin // Accommodation of a buttons in a special order...
    if FCommonData.SkinManager.IsValidImgIndex(ButtonClose.ImageIndex) then begin
      ButtonClose.Rect.Right := Offset;
      PaintButton(ButtonClose, b, ButtonClose.ImageIndex, True);
      Offset := ButtonClose.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
    end;
    if SystemMenu.VisibleMax then begin

      if Form.WindowState <> wsMaximized then begin
        ButtonMax.ImageIndex := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_BorderIconMaximize);
        if FCommonData.SkinManager.IsValidImgIndex(ButtonMax.ImageIndex) then begin
          ButtonMax.Rect.Right := Offset;
          PaintButton(ButtonMax, b, ButtonMax.ImageIndex, SystemMenu.EnabledMax);
          Offset := ButtonMax.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
        end;
      end
      else begin
        ButtonMax.ImageIndex := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_BorderIconNormalize);
        i := ButtonMax.ImageIndex;
        if i < 0 then i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_BorderIconNormalize); // For compatibility
        if i > -1 then begin
          ButtonMax.Rect.Right := Offset;
          PaintButton(ButtonMax, b, i, SystemMenu.EnabledRestore);
          Offset := ButtonMax.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
        end;
      end;

    end;
    if SystemMenu.VisibleMin then begin
      if Form.WindowState = wsMinimized then begin // If form is minimized then changing to Normalize
        i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_BorderIconNormalize);
        if i < 0 then i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_BorderIconNormalize);
        if FCommonData.SkinManager.IsValidImgIndex(i) then begin
          ButtonMin.Rect.Right := Offset;
          PaintButton(ButtonMin, b, i, SystemMenu.EnabledRestore); // For compatibility
          Offset := ButtonMin.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
        end;
      end
      else begin
        if FCommonData.SkinManager.IsValidImgIndex(ButtonMin.ImageIndex) then begin
          ButtonMin.Rect.Right := Offset;
          PaintButton(ButtonMin, b, ButtonMin.ImageIndex, SystemMenu.EnabledMin);
          Offset := ButtonMin.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
        end;
      end;
    end;
    if biHelp in Form.BorderIcons then begin
      if FCommonData.SkinManager.IsValidImgIndex(ButtonHelp.ImageIndex) then begin
        ButtonHelp.Rect.Right := Offset;
        PaintButton(ButtonHelp, b, ButtonHelp.Imageindex, True);
        Offset := ButtonHelp.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
      end;
    end;
  end; 

  if TitleButtons.Count > 0 then begin
    mi := UserBtnIndex;
    Offset := Offset - UserButtonsOffset;
    for index := 0 to TitleButtons.Count - 1 do begin
      if TitleButtons.Items[index].UseSkinData and FCommonData.SkinManager.IsValidImgIndex(mi) then begin
        TitleButtons.Items[index].BtnData.ImageIndex := mi;
        TitleButtons.Items[index].BtnData.Rect.Right := Offset;
        PaintButton(TitleButtons.Items[index].BtnData, b, mi, TitleButtons.Items[index].Enabled, TitleButtons.Items[index]);
        Offset := TitleButtons.Items[index].BtnData.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
      end
      else begin
        TitleButtons.Items[index].BtnData.ImageIndex := -1;
        TitleButtons.Items[index].BtnData.Rect.Right := Offset;
        PaintButton(TitleButtons.Items[index].BtnData, b, -1, TitleButtons.Items[index].Enabled, TitleButtons.Items[index]);
        Offset := TitleButtons.Items[index].BtnData.Rect.Left - integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing;
      end;
      TitleButtons.Items[index].BtnData.HitCode := HTUDBTN + index;
      if Assigned(TitleButtons.Items[index].Glyph) and not TitleButtons.Items[index].Glyph.Empty then begin
        if TitleButtons.Items[index].Glyph.PixelFormat = pf32bit then begin
          x := TitleButtons.Items[index].BtnData.Rect.Left + (UserButtonWidth(TitleButtons.Items[index]) - TitleButtons.Items[index].Glyph.Width) div 2;
          y := TitleButtons.Items[index].BtnData.Rect.Top + (ButtonHeight - TitleButtons.Items[index].Glyph.Height) div 2;
          CI := MakeCacheInfo(FCommonData.FCacheBmp, x, y);
          CopyByMask(Rect(x, y, x + TitleButtons.Items[index].Glyph.Width, y + TitleButtons.Items[index].Glyph.Height),
                     Rect(0, 0, TitleButtons.Items[index].Glyph.Width, TitleButtons.Items[index].Glyph.Height),
                     FCommonData.FCacheBmp,
                     TitleButtons.Items[index].Glyph,
                     CI, True);
        end
        else begin
          TitleButtons.Items[index].Glyph.PixelFormat := pf24bit;
          CopyTransBitmaps(FCommonData.FCacheBmp, TitleButtons.Items[index].Glyph,
                 TitleButtons.Items[index].BtnData.Rect.Left + (UserButtonWidth(TitleButtons.Items[index]) - TitleButtons.Items[index].Glyph.Width) div 2,
                 TitleButtons.Items[index].BtnData.Rect.Top + (ButtonHeight - TitleButtons.Items[index].Glyph.Height) div 2,
                 ColorToSColor(TitleButtons.Items[index].Glyph.Canvas.Pixels[0, TitleButtons.Items[index].Glyph.Height - 1]));
        end;
      end;
    end;
  end;

  // Drawing of MDI child buttons if maximized
  if MDIButtonsNeeded then begin
    b := CaptionHeight + SysBorderHeight(Form.Handle, BorderForm) + ShadowSize.Top + (MenuHeight - SmallButtonHeight) div 2; // Buttons top
    if FCommonData.SkinManager.IsValidImgIndex(MDIMin.ImageIndex) then begin
      MDIMin.Rect := Bounds(
                          CaptionWidth - SysBorderWidth(Form.Handle, BorderForm) - 3 * (SmallButtonWidth + 1) - ShadowSize.Right,
                          b,
                          SmallButtonWidth, SmallButtonHeight
                         );

      DrawSkinGlyph(FCommonData.FCacheBmp, Point(MDIMin.Rect.Left, MDIMin.Rect.Top),
                MDIMin.State, 1 + integer(not FormActive or not ChildProvider.SystemMenu.EnabledMin), FCommonData.SkinManager.ma[MDIMin.ImageIndex], MakeCacheInfo(SkinData.FCacheBmp));
    end;
    if Assigned(TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) and // Drawing of norm. button when maximized
          (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState <> wsMaximized) then begin
      i := MDIMax.ImageIndex
    end
    else begin
      i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconNormalize);
      if i < 0 then i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, s_GlobalInfo, s_BorderIconNormalize);
    end;
    MDIMax.Rect := Bounds(
                          CaptionWidth - SysBorderWidth(Form.Handle, BorderForm) - 2 * (SmallButtonWidth + 1) - ShadowSize.Right,
                          b,
                          SmallButtonWidth, SmallButtonHeight
                         );
    if FCommonData.SkinManager.IsValidImgIndex(i) then begin
      DrawSkinGlyph(FCommonData.FCacheBmp, Point(MDIMax.Rect.Left, MDIMax.Rect.Top),
              MDIMax.State, 1 + integer(not FormActive or not ChildProvider.SystemMenu.EnabledRestore), FCommonData.SkinManager.ma[i], MakeCacheInfo(SkinData.FCacheBmp));
    end;
    if FCommonData.SkinManager.IsValidImgIndex(MDIClose.ImageIndex) then begin
      MDIClose.Rect := Bounds(CaptionWidth - SysBorderWidth(Form.Handle, BorderForm) - SmallButtonWidth - 1 - ShadowSize.Right,
                              b,
                              SmallButtonWidth, SmallButtonHeight);

      DrawSkinGlyph(FCommonData.FCacheBmp, Point(MDIClose.Rect.Left, MDIClose.Rect.Top),
                MDIClose.State, 1 + integer(not FormActive), FCommonData.SkinManager.ma[MDIClose.ImageIndex], MakeCacheInfo(SkinData.FCacheBmp));
    end;
  end;
end;

procedure TsSkinProvider.PaintCaption(DC : hdc);
var
  h, hmnu : integer;
begin
  h := SysBorderHeight(Form.Handle, BorderForm) + CaptionHeight;
  if IsIconic(Form.Handle) then inc(h);
  if FCommonData.BGChanged or not IsCached(FCommonData) then begin
    if MenuChanged or IsBorderUnchanged(FCommonData.BorderIndex, FCommonData.SkinManager) or (TitleBG = nil) or (TitleBG.Width <> CaptionWidth) or (FCommonData.FCacheBmp.Height <> Form.Height) or not HaveBorder(Self) then begin// if ready caption BG
      ControlsChanged := not FirstInitialized;
    end;
    PaintAll;
    FCommonData.BGChanged := False;
    FCommonData.Updating := False;
  end;
  hmnu := integer(MenuPresent) * (LinesCount * MenuHeight + 1);
  // Title and menu line update
  BitBlt(DC, 0, 0, Form.Width, HeaderHeight, FCommonData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);
  // Left border update
  BitBlt(DC, 0, HeaderHeight, BorderWidth, FCommonData.FCacheBmp.Height - HeaderHeight, FCommonData.FCacheBmp.Canvas.Handle, 0, h + hmnu + TForm(Form).BorderWidth, SRCCOPY);
  // Bottom border update
  BitBlt(DC, BorderWidth, Form.Height - BorderHeight, Form.Width - BorderWidth, BorderHeight, FCommonData.FCacheBmp.Canvas.Handle,
          SysBorderwidth(Form.Handle, BorderForm) + TForm(Form).BorderWidth, Form.Height - SysBorderHeight(Form.Handle, BorderForm) - TForm(Form).BorderWidth, SRCCOPY);
  // Right border update
  BitBlt(DC, FCommonData.FCacheBmp.Width - SysBorderWidth(Form.Handle, BorderForm) - TForm(Form).BorderWidth, HeaderHeight, SysBorderHeight(Form.Handle, BorderForm) + TForm(Form).BorderWidth, FCommonData.FCacheBmp.Height - HeaderHeight, FCommonData.FCacheBmp.Canvas.Handle, FCommonData.FCacheBmp.Width - SysBorderwidth(Form.Handle, BorderForm) - TForm(Form).BorderWidth, h + hmnu + TForm(Form).BorderWidth, SRCCOPY);
end;

procedure TsSkinProvider.PaintForm(DC : hdc; SendUpdated : boolean = True);
var
  Changed : boolean;
  R : TRect;
begin
  R := Form.ClientRect;
  if SkinData.CtrlSkinState and ACS_FAST = ACS_FAST then begin
    FillDC(DC, R, FormColor);
  end
  else begin
    Changed := FCommonData.BGChanged;
    if not FCommonData.UrgentPainting then PaintAll;
    if (Form.FormStyle <> fsMDIForm) then begin
      CopyWinControlCache(Form, FCommonData, Rect(OffsetX, OffsetY, 0, 0), Rect(0, 0, Form.ClientWidth, Form.ClientHeight), DC, False);
      PaintControls(DC, Form, ControlsChanged or Changed, Point(0, 0));
    end;
    if SendUpdated then begin
      SetParentUpdated(Form);
      SendToAdapter(MakeMessage(SM_ALPHACMD, MakeWParam(0, AC_ENDPARENTUPDATE), 0, 0));
    end;
  end;
  ControlsChanged := False;
end;

procedure ShowHint(Btn : TsTitleButton);
var
  R : TRect;
{$IFNDEF DELPHI5}
  Animate: BOOL;
{$ENDIF}    
begin
  if Btn.HintWnd <> nil then FreeAndNil(Btn.HintWnd);
  if Btn.Hint <> '' then begin
    Btn.HintWnd := THintWindow.Create(Application);
    Btn.HintWnd.Visible := False;
    Btn.HintWnd.Color := clInfoBk;
    R := Btn.HintWnd.CalcHintRect(200, Btn.Hint, 0);
    OffsetRect(R, acMousePos.X + 8, acMousePos.Y + 16);

    // < Solving of the "Owner Z-ordering" problem when BorderForm is used
    Btn.HintWnd.Caption := Btn.Hint;
    Inc(R.Bottom, 4);

    Btn.HintWnd.ParentWindow := Application.Handle;
    Btn.HintWnd.SetBounds(R.Left, R.Top, WidthOf(R, True), HeightOf(R, True));
    SetWindowPos(Btn.HintWnd.Handle, HWND_TOPMOST, R.Left, R.Top, Btn.HintWnd.Width, Btn.HintWnd.Height,
      SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE or SWP_NOOWNERZORDER);
{$IFNDEF DELPHI5}
    if (Length(Btn.Hint) < 100) and Assigned(AnimateWindowProc) then begin
      SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, {$IFNDEF CLR}@{$ENDIF}Animate, 0);
      if Animate then
      begin
        SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, {$IFNDEF CLR}@{$ENDIF}Animate, 0);
        if Animate then AnimateWindowProc(Btn.HintWnd.Handle, 200, AW_BLEND);
      end;
    end;
{$ENDIF}    
    ShowWindow(Btn.HintWnd.Handle, SW_SHOWNOACTIVATE);
    Btn.HintWnd.Invalidate;
    // >
  end;
end;

procedure HideHint(Btn : TsTitleButton);
begin
  if Btn.HintWnd <> nil then FreeAndNil(Btn.HintWnd);
end;

procedure TsSkinProvider.SetHotHT(i: integer; Repaint : boolean = True);
  procedure ShowCaptionHint(Code: integer); // Must be implemented !!!
  var
    Btn : PsCaptionButton;
  begin
    case Code of
      HTCLOSE : Btn := @ButtonClose;
      HTMAXBUTTON : Btn := @ButtonMax;
      HTMINBUTTON : Btn := @ButtonMin;
      HTHELP : Btn := @ButtonHelp;
      HTCHILDCLOSE : Btn := @MDIClose;
      HTCHILDMAX : Btn := @MDIMax;
      HTCHILDMIN : Btn := @MDIMin;
      else Btn := nil;
    end;
    if Btn <> nil then begin
    end;
  end;
begin
  if not FDrawNonClientArea then Exit;
  if HotItem.Item <> nil then begin
    RepaintMenuItem(HotItem.Item, HotItem.R, []);
    HotItem.Item := nil;
  end;
  if (CurrentHT = i) or (CurrentHT = -1) and (i = 0) then Exit;
  if (CurrentHT > 0) then begin
    case CurrentHT of
      HTCLOSE : ButtonClose.State := 0;
      HTMAXBUTTON : ButtonMax.State := 0;
      HTMINBUTTON : ButtonMin.State := 0;
      HTHELP : ButtonHelp.State := 0;
      HTCHILDCLOSE : MDIClose.State := 0;
      HTCHILDMAX : MDIMax.State := 0;
      HTCHILDMIN : MDIMin.State := 0
      else if BetWeen(CurrentHT, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin
        TitleButtons.Items[CurrentHT - HTUDBTN].BtnData.State := 0;
        HideHint(TitleButtons.Items[CurrentHT - HTUDBTN]);
      end;
    end;
    if Repaint then RepaintButton(CurrentHT);
  end;
  CurrentHT := i;
  case CurrentHT of
    HTCLOSE : ButtonClose.State := 1;
    HTMAXBUTTON : ButtonMax.State := 1;
    HTMINBUTTON : ButtonMin.State := 1;
    HTHELP : ButtonHelp.State := 1;
    HTCHILDCLOSE : MDIClose.State := 1;
    HTCHILDMAX : MDIMax.State := 1;
    HTCHILDMIN : MDIMin.State := 1
    else if BetWeen(CurrentHT, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin
      TitleButtons.Items[CurrentHT - HTUDBTN].BtnData.State := 1;
      ShowHint(TitleButtons.Items[CurrentHT - HTUDBTN]);         
    end;

    if (CurrentHT < HTUDBTN) and (BorderForm <> nil) then ShowCaptionHint(CurrentHT);
  end;
  biClicked := False;
  if Repaint then RepaintButton(CurrentHT);
end;

procedure TsSkinProvider.SetPressedHT(i: integer);
begin
  if (CurrentHT <> i) and (CurrentHT <> 0) then begin
    case CurrentHT of
      HTCLOSE : ButtonClose.State := 0;
      HTMAXBUTTON : ButtonMax.State := 0;
      HTMINBUTTON : ButtonMin.State := 0;
      HTHELP : ButtonHelp.State := 0;
      HTCHILDCLOSE : MDIClose.State := 0;
      HTCHILDMAX : MDIMax.State := 0;
      HTCHILDMIN : MDIMin.State := 0
      else if BetWeen(CurrentHT, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin
        TitleButtons.Items[CurrentHT - HTUDBTN].BtnData.State := 0;
        HideHint(TitleButtons.Items[CurrentHT - HTUDBTN]);
      end;
    end;
    RepaintButton(CurrentHT);
  end;
  CurrentHT := i;
  case CurrentHT of
    HTCLOSE : ButtonClose.State := 2;
    HTMAXBUTTON : if SystemMenu.EnabledMax or ((Form.WindowState = wsMaximized) and SystemMenu.EnabledRestore) then ButtonMax.State := 2 else begin
      CurrentHT := 0;
      Exit;
    end;
    HTMINBUTTON : ButtonMin.State := 2;
    HTHELP : ButtonHelp.State := 2;
    HTCHILDCLOSE : MDIClose.State := 2;
    HTCHILDMAX : if SystemMenu.EnabledMax then MDIMax.State := 2;
    HTCHILDMIN : MDIMin.State := 2
    else if BetWeen(CurrentHT, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin
      TitleButtons.Items[CurrentHT - HTUDBTN].BtnData.State := 2;
      HideHint(TitleButtons.Items[CurrentHT - HTUDBTN]);
    end;
  end;
  biClicked := True;
  RepaintButton(CurrentHT);
end;

procedure TsSkinProvider.PaintAll;
var
  VisIndex, Index, i, sbw, {sbwf, }TitleIndex, CY : integer;
  x, w, h, y, fHeight, fWidth, fCaptHeight : integer;
  s : acString;
  r, rForm, rC : TRect;
  ci : TCacheInfo;
  CurrentItem : TMenuItem;
  ItemProcessed : integer;
  ChangedIndex : integer;
  Iconic, exBorders : boolean;
  SavedCanvas, SavedDC : hdc;
  ts : TSize;
  P, Src : PRGBAArray;
  SavedTitle : TBitmap;
  function ProcessMerged(CurrentIndex : integer) : boolean;
  var
    i, j, VisJ, w : integer;
    LocalItem : TMenuItem;
  begin
    Result := False;
    if Assigned(Form.ActiveMDIChild) and Assigned(Form.ActiveMDIChild.Menu) then begin
      for i := ItemProcessed to Form.ActiveMDIChild.Menu.Items.Count - 1 do if Form.ActiveMDIChild.Menu.Items[i].Visible then begin
        LocalItem := Form.ActiveMDIChild.Menu.Items[i];
        // If MDI form and included other
        if (LocalItem.GroupIndex > ChangedIndex) and (LocalItem.GroupIndex <= CurrentIndex) then begin

          if not Assigned(LocalItem.OnMeasureItem) or not Assigned(LocalItem.OnAdvancedDrawItem) then Continue;

          Result := (LocalItem.GroupIndex >= CurrentIndex);
          ChangedIndex := LocalItem.GroupIndex;

          j := i;
          VisJ := j;
          while (j < Form.ActiveMDIChild.Menu.Items.Count) do begin
            LocalItem := Form.ActiveMDIChild.Menu.Items[j];
            if (LocalItem.GroupIndex > CurrentIndex) and (Index <= Form.Menu.Items.Count - 1) then Exit;
            GetMenuItemRect(Form.ActiveMDIChild.Handle, Form.ActiveMDIChild.Menu.Handle, VisJ, R);

            w := WidthOf(R);
            ChangedIndex := LocalItem.GroupIndex;

            if x + w > Form.Width - 2 * sbw - 2 * TForm(Form).BorderWidth then begin
              x := sbw + ShadowSize.Left;
              inc(y, MenuHeight);
            end;

            r := Rect(x, y, x + w, y + MenuHeight);
            LocalItem.OnAdvancedDrawItem(LocalItem, FCommonData.FCacheBmp.Canvas, R, []);
            x := r.Right;
            ItemProcessed := i + 1;
            inc(j);
            inc(VisIndex);
            inc(VisJ);
          end;
        end;
      end;
    end;
  end;
  procedure PaintTitle;
  begin
    if (CaptionHeight <> 0) and FDrawNonClientArea then begin // Paint title
      TitleIndex := FCommonData.SkinManager.GetSkinIndex(TitleSkinSection);

      if FCommonData.SkinManager.IsValidSkinIndex(TitleIndex) and not exBorders then begin
        if Iconic
          then PaintItem(TitleIndex, TitleSkinSection, ci, True, integer(FormActive), Rect(rForm.Left, rForm.Top, rForm.Right, rForm.Bottom), Point(0, 0), FCommonData.FCacheBmp, FCommonData.SkinManager)
          else PaintItem(TitleIndex, TitleSkinSection, ci, True, integer(FormActive), Rect(rForm.Left, rForm.Top, rForm.Right, fCaptHeight), Point(0, 0), FCommonData.FCacheBmp, FCommonData.SkinManager);
      end;

      DrawAppIcon(Self); // Draw app icon
      if (SysButtonsCount > 0) then begin // Paint title toolbar if defined in skin
        i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_NormalTitleBar);
        if FCommonData.SkinManager.IsValidImgIndex(i)
          then DrawSkinRect(FCommonData.FCacheBmp, Rect(CaptionWidth - BarWidth(i), 0, FCommonData.FCacheBmp.Width, h - CY),
                             True, EmptyCI, FCommonData.SkinManager.ma[i], integer(FormActive), True);
      end;
    end;
  end;
  procedure PaintText;
  begin
    if (CaptionHeight <> 0) and FDrawNonClientArea then begin
      // Out the title text
      FCommonData.FCacheBmp.Canvas.Font.Handle := acGetTitleFont;

      FCommonData.FCacheBmp.Canvas.Font.Style := FCommonData.FCacheBmp.Canvas.Font.Style + [fsBold];
      FCommonData.FCacheBmp.Canvas.Font.Height := GetCaptionFontSize;

      if IsZoomed(Form.Handle)
        then R := Rect(SysBorderWidth(Form.Handle, BorderForm) + integer(IconVisible) * WidthOf(IconRect) + 4 + SkinData.SkinManager.SkinData.BILeftMargin + ShadowSize.Left,
                ShadowSize.Top + SysBorderWidth(Form.Handle, BorderForm, False) div 2 + 1,
                rForm.Right - TitleBtnsWidth - 6 - ShadowSize.Right,
                fCaptHeight)
        else R := Rect(SysBorderWidth(Form.Handle, BorderForm) + integer(IconVisible) * WidthOf(IconRect) + 4 + SkinData.SkinManager.SkinData.BILeftMargin + ShadowSize.Left,
                ShadowSize.Top + 2,
                rForm.Right - TitleBtnsWidth - 6 - ShadowSize.Right,
                fCaptHeight);
      if ExBorders then begin
        OffsetRect(R, 0, FCommonData.SkinManager.SkinData.ExCenterOffs);
        if (Form.WindowState = wsMaximized) and (FCommonData.SkinManager.SkinData.ExTitleHeight <> FCommonData.SkinManager.SkinData.ExMaxHeight)
          then OffsetRect(R, 0, (FCommonData.SkinManager.SkinData.ExTitleHeight - FCommonData.SkinManager.SkinData.ExMaxHeight) div 2 - 2)
      end;
      if not IsRectEmpty(R) then begin
{$IFDEF TNTUNICODE}
        s := WideString(GetWndText(Form.Handle));
        GetTextExtentPoint32W(FCommonData.FCacheBmp.Canvas.Handle, PWideChar(s), Length(s), ts);
{$ELSE}
{$IFDEF TESTBGCHANGED}
        s := IntToStr(iTestCount);
{$ELSE}
        s := Form.Caption;
{$ENDIF}
        GetTextExtentPoint32(FCommonData.FCacheBmp.Canvas.Handle, PChar(s), Length(s), ts);
{$ENDIF}
        R.Top := R.Top + (HeightOf(R) - ts.cy) div 2;
        R.Bottom := R.Top + ts.cy;
        acWriteTextEx(FCommonData.FCacheBmp.Canvas, PacChar(s), Form.Enabled, R,
          GetStringFlags(Form, FCaptionAlignment) or DT_END_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX,
          FCommonData.SkinManager.GetSkinIndex(TitleSkinSection), FormActive, FCommonData.SkinManager)
      end;
    end;
  end;
begin
  if (csCreating in Form.ControlState) then Exit;
  fHeight := Form.Height;
  if BorderForm <> nil then fHeight := fHeight + DiffBorder(Self.BorderForm) + DiffTitle(Self.BorderForm) + ShadowSize.Top + ShadowSize.Bottom + integer(MenuHeight <> 0);
  fWidth := CaptionWidth;
  exBorders := (BorderForm <> nil) and (SkinData.SkinManager.SkinData.ExDrawMode = 1);

  with FCommonData do if FCacheBmp = nil then begin // If first loading
    if BorderForm <> nil then FCacheBmp := CreateBmp32(fWidth, fHeight) else FCacheBmp := CreateBmp24(fWidth, fHeight);
    UpdateSkinState(FCommonData, False);
    acM := MakeMessage(SM_ALPHACMD, MakeWParam(0, AC_GETSKINSTATE), 1, 0); // Initialization of all child states
    if not (csLoading in Form.ComponentState) then AlphaBroadCast(Form, acM);
  end;
  if (Form.FormStyle = fsMDIForm) and (Form.ActiveMDIChild <> nil) and (Form.ActiveMDIChild.WindowState = wsMaximized) then begin
    if (fsShowing in Form.ActiveMDIChild.FormState) and MenuChanged then Exit;
  end;
  ItemProcessed := 0;

  sbw := SysBorderWidth(Form.Handle, BorderForm);
//  sbwf := SysBorderWidth(Form.Handle, BorderForm, False);
  Iconic := IsIconic(Form.Handle);
  CY := SysBorderHeight(Form.Handle, BorderForm, False);
  h := 2 * CY + CaptionHeight;
  fCaptHeight := CaptionHeight + SysBorderHeight(Form.Handle, BorderForm, False) + ShadowSize.Top; //
  if Iconic
    then rForm := Rect(ShadowSize.Left, ShadowSize.Top, fWidth - ShadowSize.Right, fCaptHeight + 1 - ShadowSize.Bottom)
    else rForm := Rect(ShadowSize.Left, ShadowSize.Top, fWidth - ShadowSize.Right, fHeight - ShadowSize.Bottom);
//  if not IsCached(FCommonData) and (Form.Height <> FCommonData.FCacheBmp.Height) then FCommonData.BGChanged := True;
  if FCommonData.BGChanged then begin
    if not MenuChanged and IsBorderUnchanged(FCommonData.BorderIndex, FCommonData.SkinManager) and (TitleBG <> nil) and (TitleBG.Width = CaptionWidth) and (FCommonData.FCacheBmp.Height = Form.Height) and (CaptionHeight <> 0) and (BorderForm = nil) then begin // if ready caption BG
      // Drawn caption only if form is not changed
      if FDrawNonClientArea then begin
        ci := MakeCacheInfo(FCommonData.FCacheBmp);
        BitBlt(FCommonData.FCacheBmp.Canvas.Handle, 0, 0, TitleBG.Width, TitleBG.Height, TitleBG.Canvas.Handle, 0, 0, SRCCOPY);
        PrepareCaption(CI, Rect(0, 0, TitleBG.Width, TitleBG.Height));
      end;
    end
    else begin
{$IFDEF TESTBGCHANGED}  
      inc(iTestCount);
{$ENDIF}  
      RgnChanged := True;
      ci.Ready := False;
      FCommonData.FCacheBmp.Width := fWidth;
      FCommonData.FCacheBmp.Height := fHeight;

      if FCommonData.SkinManager.IsValidSkinIndex(FCommonData.SkinIndex) then begin
        // Paint body
        if SkinData.CtrlSkinState and ACS_FAST <> ACS_FAST then begin // If cache is required
          if HaveBorder(Self) and not exBorders
            then PaintItem(FCommonData, EmptyCI, False, integer(FormActive), rForm, Point(0, 0), FCommonData.FCacheBmp, False)
            else PaintItemBG(FCommonData.SkinIndex, FCommonData.SkinSection, EmptyCI, integer(FormActive), rForm, Point(0, 0), FCommonData.FCacheBmp, FCommonData.SkinManager);
        end
        else begin
          if (BorderForm = nil) {or exBorders }then begin // If not extended borders
            FillDC(FCommonData.FCacheBmp.Canvas.Handle, Rect(0, 0, FCommonData.FCacheBmp.Width, CaptionHeight + BorderWidth + LinesCount * MenuHeight + 1), FormColor);
            if not exBorders then PaintBorderFast(FCommonData.FCacheBmp.Canvas.Handle, rForm, BorderWidth, FCommonData, integer(FormActive));
          end
          else begin
            FillDC(FCommonData.FCacheBmp.Canvas.Handle,
              Rect(ShadowSize.Left, ShadowSize.Top,
                   FCommonData.FCacheBmp.Width - ShadowSize.Right,
                   FCommonData.FCacheBmp.Height - ShadowSize.Bottom), FormColor);
            if not exBorders then PaintBorderFast(FCommonData.FCacheBmp.Canvas.Handle, rForm, BorderWidth, FCommonData, integer(FormActive));
          end;
        end;

        if IsGripVisible(Self) and IsCached(FCommonData)then begin
          FCommonData.BGChanged := False;
          PaintGrip(FCommonData.FCacheBmp.Canvas.Handle, Self);
        end;

        ci := MakeCacheInfo(FCommonData.FCacheBmp, OffsetX, OffsetY); // Prepare cache info

        if not exBorders then PaintTitle;

        if (Form.Menu <> nil) and MenuPresent and (MenuHeight > 0) then begin // Menu line drawing
          i := -1;
          if FMenuLineSkin <> '' then i := FCommonData.SkinManager.GetSkinIndex(FMenuLineSkin);
          if i < 0 then i := FCommonData.SkinManager.GetSkinIndex(s_MenuLine); // Paint menu bar
          if FCommonData.SkinManager.IsValidSkinIndex(i)
            then PaintItem(i, FMenuLineSkin, ci, True, integer(FormActive),
                   Rect(ShadowSize.Left, fCaptHeight, FCommonData.FCacheBmp.Width - ShadowSize.Right, fCaptHeight + LinesCount * MenuHeight),
                   Point(ShadowSize.Left, fCaptHeight), FCommonData.FCacheBmp, FCommonData.SkinManager);

          MenuLineBmp.Width := fWidth - ShadowSize.Left - ShadowSize.Right; // Store bg for Menu line
          MenuLineBmp.Height := LinesCount * MenuHeight;
          y := OffsetY - LinesCount * MenuHeight - Form.BorderWidth;
          if BorderForm = nil then dec(y, 1);
          BitBlt(MenuLineBmp.Canvas.Handle, 0, 0, MenuLineBmp.Width, MenuLineBmp.Height,
                 FCommonData.FCacheBmp.Canvas.Handle, OffsetX - Form.BorderWidth, y, SRCCOPY);

          // Draw maximized child form system icon on menuline
          if ChildIconPresent and (MDISkinProvider = Self) then begin
            if Form.ActiveMDIChild.Icon.Handle <> 0
              then DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, sbw + 1, fCaptHeight + 1, Form.ActiveMDIChild.Icon.Handle, MenuHeight - 2, MenuHeight - 2, 0, 0, di_Normal)
              else if AppIcon <> nil
                then DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, sbw + 1 + ShadowSize.Left, fCaptHeight + 1, AppIcon.Handle, MenuHeight - 2, MenuHeight - 2, 0, 0, di_Normal)
                else DrawIconEx(FCommonData.FCacheBmp.Canvas.Handle, sbw + 1 + ShadowSize.Left, fCaptHeight + 1, LoadIcon(0, IDI_APPLICATION), MenuHeight - 2, MenuHeight - 2, 0, 0, di_Normal);
          end;
          /////// Painting of menu items ///////
          x := sbw + ShadowSize.Left;
          y := fCaptHeight;
          ChangedIndex := -1;
          Index := 0;
          VisIndex := 0;

          if AeroIsEnabled and (Form.Menu <> nil) then FCommonData.SkinManager.SkinableMenus.InitMenuLine(Form.Menu, FDrawNonCLientArea);

          while Index < Form.Menu.Items.Count do begin
            if (x = sbw + ShadowSize.Left) and (MDISkinProvider = Self) and ChildIconPresent then begin // Skip Item with child icon
              GetMenuItemRect(Form.Handle, Form.Menu.Handle, 0, R);
              inc(x, WidthOf(R));
              inc(VisIndex);
              Continue;
            end;
            CurrentItem := Form.Menu.Items[Index];
            if ((CurrentItem.GroupIndex = ChangedIndex) or ProcessMerged(CurrentItem.GroupIndex)) then begin
              inc(Index); continue;
            end
            else begin
              if not Assigned(CurrentItem.OnMeasureItem) or not Assigned(CurrentItem.OnAdvancedDrawItem) or not CurrentItem.Visible then begin
                inc(Index); Continue;
              end;
              GetMenuItemRect(Form.Handle, Form.Menu.Handle, VisIndex, R);
              w := WidthOf(R);
              if FSysExHeight
                then OffsetRect(R, -Form.Left + DiffBorder(Self.BorderForm) + ShadowSize.Left, -Form.Top + DiffTitle(Self.BorderForm) + ShadowSize.Top + 4)
                else OffsetRect(R, -Form.Left + DiffBorder(Self.BorderForm) + ShadowSize.Left, -Form.Top + DiffTitle(Self.BorderForm) + ShadowSize.Top);
              CurrentItem.OnAdvancedDrawItem(CurrentItem, FCommonData.FCacheBmp.Canvas, R, [odNoAccel, odReserved1]);
              inc(x, w);
              inc(Index);
              inc(VisIndex);
            end;
          end;
          ProcessMerged(MaxInt);
        end;

        if not exBorders and (BorderForm <> nil) then PaintText;
        // Paint MDIArea
        if (Form.FormStyle = fsMDIForm) and Assigned(MDIForm) then begin
          rC.Left := BorderWidth + GetAlignShift(Form, alLeft) + ShadowSize.Left;
          if BorderForm = nil
            then rC.Top := fCaptHeight + LinesCount * MenuHeight * integer(MenuPresent) + Form.BorderWidth + GetAlignShift(Form, alTop)
            else rC.Top := fCaptHeight + LinesCount * MenuHeight * integer(MenuPresent) + Form.BorderWidth + GetAlignShift(Form, alTop);

          if Menuheight <> 0 then inc(rC.Top);
          rC.Right := FCommonData.FCacheBmp.Width - BorderWidth - GetAlignShift(Form, alRight) - ShadowSize.Right;
          rC.Bottom := FCommonData.FCacheBmp.Height - BorderWidth - GetAlignShift(Form, alBottom) - ShadowSize.Bottom;
          CI := MakeCacheInfo(FCommonData.FCacheBmp);
          i := FCommonData.SkinManager.GetSkinIndex(s_MDIArea);
          PaintItem(i, s_MDIArea, CI, False, 0, Rect(rC.Left, rC.Top, rC.Right, rC.Bottom), rC.TopLeft, FCommonData.FCacheBmp.Canvas.Handle, FCommonData.SkinManager);
        end;

        if BorderForm <> nil then begin // Painting of form shadow if required
          // Fill alphachannel
          h := FCommonData.FCacheBmp.Height - ShadowSize.Bottom - 1;
          w := FCommonData.FCacheBmp.Width - ShadowSize.Right - 1;
          for y := ShadowSize.Top to h do begin
            p := FCommonData.FCacheBmp.ScanLine[y];
            for x := ShadowSize.Left to w do p[x].A := MaxByte;
          end;

          if FormActive then BorderForm.ShadowTemplate := SkinData.SkinManager.ShdaTemplate else BorderForm.ShadowTemplate := SkinData.SkinManager.ShdiTemplate;
          if BorderForm.ShadowTemplate <> nil then begin
            if exBorders then with SkinData.SkinManager do begin
              ChangedIndex := ConstData.ExBorder; // Index of extended border in skin
              PaintControlByTemplate(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, Rect(0, 0, fWidth, fHeight),
                  Rect(0, 0, BorderForm.ShadowTemplate.Width, BorderForm.ShadowTemplate.Height),
                  Rect(min(ma[ChangedIndex].WL, BorderWidth + ShadowSize.Left), ma[ChangedIndex].WT, min(ma[ChangedIndex].WR, BorderWidth + ShadowSize.Right), ma[ChangedIndex].WB),
                  Rect(MaxByte, MaxByte, MaxByte, MaxByte), Rect(1, 1, 1, 1), False, False);

              SavedTitle := CreateBmp32(fWidth, fCaptHeight);
              BitBlt(SavedTitle.Canvas.Handle, 0, 0, fWidth, fCaptHeight, FCommonData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);

              PaintTitle;
              PaintText;

              h := min(FCommonData.FCacheBmp.Height, SavedTitle.Height) - 1;
              w := SavedTitle.Width - 1;
              for y := 0 to h do begin // Must be optimized
                Src := SavedTitle.ScanLine[y];
                P := FCommonData.FCacheBmp.ScanLine[y];
//                if Form.WindowState <> wsMaximized then begin
                for x := 0 to w do if (Src[x].C <> P[x].C) then P[X].A := MaxByte
//                end
//                else for x := 0 to w do P[X].A := (P[X].A + MaxByte) div 2 // Title is not transparent when window is maximized
              end;
              SavedTitle.Free;
            end
            else begin
              PaintControlByTemplate(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, Rect(0, 0, fWidth, fHeight),
                Rect(0, 0, BorderForm.ShadowTemplate.Width, BorderForm.ShadowTemplate.Height),
                Rect(ShadowSize.Left + SkinData.SkinManager.SkinData.ExContentOffs, ShadowSize.Top + SkinData.SkinManager.SkinData.ExContentOffs, ShadowSize.Right + SkinData.SkinManager.SkinData.ExContentOffs, ShadowSize.Bottom + SkinData.SkinManager.SkinData.ExContentOffs),
                ShadowSize, Rect(1, 1, 1, 1), False, False);

              // Draw shadows in corners
              if SkinData.SkinManager.IsValidImgIndex(TitleIndex) then TitleIndex := FCommonData.SkinManager.gd[TitleIndex].BorderIndex;
              if SkinData.SkinManager.IsValidImgIndex(TitleIndex) then begin // If title mask exists
                x := FCommonData.SkinManager.MaskWidthRight(TitleIndex);
                // LeftTop
                R := Rect(ShadowSize.Left, ShadowSize.Top, ShadowSize.Left + FCommonData.SkinManager.MaskWidthLeft(TitleIndex),
                          ShadowSize.Top + FCommonData.SkinManager.MaskWidthTop(TitleIndex));
                FillTransPixels32(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, R, ShadowSize.TopLeft, TitleIndex, FCommonData.SkinManager, HTTOPLEFT);
                // RightTop
                R := Rect(FCommonData.FCacheBmp.Width - ShadowSize.Right - x, ShadowSize.Top, FCommonData.FCacheBmp.Width - ShadowSize.Right,
                          ShadowSize.Top + FCommonData.SkinManager.MaskWidthTop(TitleIndex));
                FillTransPixels32(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, R,
                  Point(BorderForm.ShadowTemplate.Width - ShadowSize.Right - x, ShadowSize.Top), TitleIndex, FCommonData.SkinManager, HTTOPRIGHT);
              end
              else if FCommonData.BorderIndex > -1 then begin
                x := FCommonData.SkinManager.MaskWidthRight(FCommonData.BorderIndex);
                // LeftTop
                R := Rect(ShadowSize.Left, ShadowSize.Top, ShadowSize.Left + min(FCommonData.SkinManager.MaskWidthLeft(FCommonData.BorderIndex), 8), ShadowSize.Top + min(FCommonData.SkinManager.MaskWidthTop(FCommonData.BorderIndex), 8));
                FillTransPixels32(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, R, ShadowSize.TopLeft, FCommonData.BorderIndex, FCommonData.SkinManager, HTTOPLEFT);
                // RightTop
                R := Rect(FCommonData.FCacheBmp.Width - ShadowSize.Right - x,  ShadowSize.Top, FCommonData.FCacheBmp.Width - ShadowSize.Right,
                          ShadowSize.Top + FCommonData.SkinManager.MaskWidthTop(FCommonData.BorderIndex));
                FillTransPixels32(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, R, Point(BorderForm.ShadowTemplate.Width - ShadowSize.Right - x, ShadowSize.Top), FCommonData.BorderIndex, FCommonData.SkinManager, HTTOPRIGHT);
              end;
              if FCommonData.BorderIndex > -1 then begin
                y := FCommonData.SkinManager.MaskWidthBottom(FCommonData.BorderIndex);
                x := FCommonData.SkinManager.MaskWidthRight(FCommonData.BorderIndex);

                // LeftBottom
                R := Rect(ShadowSize.Left, FCommonData.FCacheBmp.Height - ShadowSize.Bottom - y, ShadowSize.Left + FCommonData.SkinManager.MaskWidthLeft(FCommonData.BorderIndex),
                          FCommonData.FCacheBmp.Height - ShadowSize.Bottom);
                FillTransPixels32(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, R, Point(ShadowSize.Left, BorderForm.ShadowTemplate.Height - ShadowSize.Bottom - y), FCommonData.BorderIndex, FCommonData.SkinManager, HTBOTTOMLEFT);
                // RightBottom
                R := Rect(FCommonData.FCacheBmp.Width - ShadowSize.Right - x, FCommonData.FCacheBmp.Height - ShadowSize.Bottom - y,
                          FCommonData.FCacheBmp.Width - ShadowSize.Right, FCommonData.FCacheBmp.Height - ShadowSize.Bottom);
                FillTransPixels32(FCommonData.FCacheBmp, BorderForm.ShadowTemplate, R,
                  Point(BorderForm.ShadowTemplate.Width - ShadowSize.Right - x, BorderForm.ShadowTemplate.Height - ShadowSize.Bottom - y), FCommonData.BorderIndex, FCommonData.SkinManager, HTBOTTOMRIGHT);
              end;
            end;
          end;
        end;

        // Save caption
        if IsBorderUnchanged(FCommonData.BorderIndex, FCommonData.SkinManager) and ((TitleBG = nil) or (TitleBG.Width <> CaptionWidth)) then MakeTitleBG;

        if not exBorders and (BorderForm = nil) then PaintText;

        if (CaptionHeight <> 0) and FDrawNonClientArea then begin
          SaveBGForBtns(True);
          // Paint buttons
          PaintBorderIcons;
        end;

      end;
      MenuChanged := False;
      FCommonData.BGChanged := False;
      if Assigned(Form.OnPaint) and IsCached(SkinData) then begin
        SavedCanvas := Form.Canvas.Handle;
        Form.Canvas.Handle := SkinData.FCacheBmp.Canvas.Handle;
        SavedDC := SaveDC(Form.Canvas.Handle);
        MoveWindowOrg(Form.Canvas.Handle, OffsetX, OffsetY);
        Form.Canvas.Lock;
        Form.OnPaint(Form);
        Form.Canvas.Unlock;
        RestoreDC(Form.Canvas.Handle, SavedDC);
        Form.Canvas.Handle := SavedCanvas;
      end;
    end;
    FirstInitialized := True;
    FCommonData.BGChanged := False;
  end;
  FCommonData.Updating := False;
end;

function TsSkinProvider.FormLeftTop: TPoint;
var
  p : TPoint;
  R : TRect;
begin
  if TForm(Form).FormStyle = fsMDIChild then begin
    p := Point(0, 0);
    p := Form.ClientToScreen(p);
    Result.x := p.x - SysBorderWidth(Form.Handle, BorderForm);
    Result.y := p.y - SysBorderHeight(Form.Handle, BorderForm) - integer(not IsIconic(Form.Handle)) * CaptionHeight;
  end
  else begin
    GetWindowRect(Form.Handle, R);
    Result.x := R.Left;
    Result.y := R.Top;
  end;
end;

function TsSkinProvider.IconRect: TRect;
var
  fCaptHeight : integer;
begin
  Result.Left := SysBorderWidth(Form.Handle, BorderForm) + SkinData.SkinManager.SkinData.BILeftMargin + ShadowSize.Left;
  Result.Right := Result.Left + TitleIconWidth(Self);
  Result.Top := ShadowSize.Top + SysBorderWidth(Form.Handle, BorderForm, False) div 2 - 1;
  fCaptHeight := CaptionHeight + SysBorderHeight(Form.Handle, BorderForm, False) + ShadowSize.Top;

  Result.Top := Result.Top + (fCaptHeight - Result.Top - TitleIconHeight(Self)) div 2;


  Result.Bottom := Result.Top + TitleIconHeight(Self);
  if (BorderForm <> nil) {and (SkinData.SkinManager.SkinData.ExDrawMode = 1)} then begin
    OffsetRect(Result, 0, FCommonData.SkinManager.SkinData.ExCenterOffs);
    if (Form.WindowState = wsMaximized) and (FCommonData.SkinManager.SkinData.ExTitleHeight <> FCommonData.SkinManager.SkinData.ExMaxHeight)
      then OffsetRect(Result, 0, (FCommonData.SkinManager.SkinData.ExTitleHeight - FCommonData.SkinManager.SkinData.ExMaxHeight) div 2 - 2)
  end;
end;

procedure TsSkinProvider.DropSysMenu(x, y : integer);
var
  mi : TMenuitem;
  SysMenu: HMENU;
  SelItem: DWORD;
  procedure EnableCommandItem(uIDEnableItem : UINT; Enable : Boolean);
  begin
    if Enable
      then EnableMenuItem(SysMenu, uIDEnableItem, MF_BYCOMMAND or MF_ENABLED)
      else EnableMenuItem(SysMenu, uIDEnableItem, MF_BYCOMMAND or MF_GRAYED or MF_DISABLED);
  end;
begin
  if SkinData.SkinManager.SkinnedPopups then begin
    SystemMenu.UpdateItems(SystemMenu.ExtItemsCount > 0);
    if FMakeSkinMenu and (SystemMenu.Items.Count > 0) then begin
      if SystemMenu.Items[0].Name = s_SkinSelectItemName then begin
        while SystemMenu.Items[0].Count > 0 do begin
          mi := SystemMenu.Items[0].Items[0];
          SystemMenu.Items[0].Delete(0);
          FreeAndNil(mi);
        end;
        mi := SystemMenu.Items[0];
        SystemMenu.Items.Delete(0);
        FreeAndNil(mi);
      end;
      SystemMenu.MakeSkinItems;
    end;
    SkinData.SkinManager.SkinableMenus.HookPopupMenu(SystemMenu, True);

    SkinData.SkinManager.SkinableMenus.HookPopupMenu(SystemMenu, True);
    SystemMenu.WindowHandle := Form.Handle;
    SystemMenu.Popup(x, y);
  end
  else begin
    // Prevent of painting by system (white line)
    SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) and not WS_VISIBLE);
    //get a modifiable copy of the original sysmenu
    SysMenu := GetSystemMenu(Form.Handle, False);
    //read and emulate states from skin SystemMenu
    with SystemMenu do begin
      EnableCommandItem(SC_RESTORE , VisibleRestore And EnabledRestore);
      EnableCommandItem(SC_MOVE    , EnabledMove and not IsIconic(Form.Handle));
      EnableCommandItem(SC_SIZE    , VisibleSize And EnabledSize And (Form.WindowState = wsNormal));
      EnableCommandItem(SC_MINIMIZE, VisibleMin And EnabledMin);
      EnableCommandItem(SC_MAXIMIZE, VisibleMax And EnabledMax);
      EnableCommandItem(SC_CLOSE   , VisibleClose);
    end;
    SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_VISIBLE);
    //Get menuselection from menu, do not send it on automatically
    SelItem := LongWord(TrackPopupMenu(SysMenu, TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_RETURNCMD, x, y, 0, Form.Handle, nil));
    //If the sysmenu tracking resulted in a selection, post it as a WM_SYSCOMMAND
    if SelItem > 0 then PostMessage(Form.Handle, WM_SYSCOMMAND, SelItem, 0);
  end;
end;

function TsSkinProvider.CursorToPoint(x, y: integer): TPoint;
begin
  Result := FormLeftTop;
  Result.x := x - Result.x;
  Result.y := y - Result.y;
end;

function TsSkinProvider.MenuPresent: boolean;
var
 i, VisibleItems : integer;
begin
  Result := False;
  if (Form.BorderStyle <> bsDialog) and (Form.FormStyle <> fsMDIChild) then begin
    if Form.Menu <> nil then begin
      VisibleItems := 0;
      for i := 0 to Form.Menu.Items.Count - 1 do if Form.Menu.Items[i].Visible then begin
        inc(VisibleItems);
        Break;
      end;
      if (Form.FormStyle = fsMDIForm) and Assigned(Form.ActiveMDIChild) and Assigned(Form.ActiveMDIChild.Menu) then begin
        for i := 0 to Form.ActiveMDIChild.Menu.Items.Count - 1 do if Form.ActiveMDIChild.Menu.Items[i].Visible then begin
          inc(VisibleItems);
          Break;
        end;
      end;
      Result := VisibleItems > 0;
    end;
  end;
end;

function TsSkinProvider.OffsetX: integer;
var
  i : integer;
begin
  if (BorderForm <> nil) then Result := BorderWidth + ShadowSize.Left else begin
    if Assigned(ListSW) and Assigned(ListSW.sBarVert) and ListSW.sBarVert.fScrollVisible then i := GetScrollMetric(ListSW.sBarVert, SM_CXVERTSB) else i := 0;
    Result := (GetWindowWidth(Form.Handle) - GetClientWidth(Form.Handle) - i) div 2
  end;
end;

function TsSkinProvider.OffsetY: integer;
var
  i : integer;
begin
  if (BorderForm <> nil) then begin
    Result := CaptionHeight + LinesCount * MenuHeight + Form.BorderWidth + ShadowSize.Top
  end
  else begin
    if Assigned(ListSW) and Assigned(ListSW.sBarHorz) and ListSW.sBarHorz.fScrollVisible then i := GetScrollMetric(ListSW.sBarHorz, SM_CYHORZSB) else i := 0;
    Result := GetWindowHeight(Form.Handle) - GetClientHeight(Form.Handle) - BorderWidth * integer(CaptionHeight <> 0) - i;
  end;
end;

function TsSkinProvider.GetLinesCount: integer;
var
  VisIndex, Index, x, w, GlobalResult : integer;
  CurrentItem : TMenuItem;
  ItemProcessed : integer;
  ChangedIndex : integer;
  R : TRect;
  function ProcessMerged(CurrentIndex : integer) : boolean;
  var
    i, j, VisJ, w : integer;
    LocalItem : TMenuItem;
  begin
    Result := False;
    if Assigned(Form.ActiveMDIChild) and Assigned(Form.ActiveMDIChild.Menu) then begin
      for i := ItemProcessed to Form.ActiveMDIChild.Menu.Items.Count - 1 do begin
        LocalItem := Form.ActiveMDIChild.Menu.Items[i];
        // If MDI form and included other
        if (LocalItem.GroupIndex > ChangedIndex) and (LocalItem.GroupIndex <= CurrentIndex) then begin

          if not Assigned(LocalItem.OnMeasureItem) or not Assigned(LocalItem.OnAdvancedDrawItem) or not LocalItem.Visible then Continue;

          Result := (LocalItem.GroupIndex >= CurrentIndex);
          ChangedIndex := LocalItem.GroupIndex;

          j := i;
          VisJ := j;
          while (j <= Form.ActiveMDIChild.Menu.Items.Count - 1) do begin
            LocalItem := Form.ActiveMDIChild.Menu.Items[j];
            if (LocalItem.GroupIndex > ChangedIndex) and (Index <= Form.Menu.Items.Count - 1) then Exit;
            GetMenuItemRect(Form.ActiveMDIChild.Handle, Form.ActiveMDIChild.Menu.Handle, VisJ, R);
            w := WidthOf(R);
            ChangedIndex := LocalItem.GroupIndex;

            if x + w > Form.Width - 2 * SysBorderWidth(Form.Handle, BorderForm) - 2 * TForm(Form).BorderWidth then begin
              x := SysBorderWidth(Form.Handle, BorderForm);
              inc(GlobalResult);
            end;

            inc(x, w);
            ItemProcessed := i + 1;
            inc(j);
            inc(VisJ);
          end;
        end;
      end;
    end;
  end;
begin
  if FLinesCount <> -1 then Result := FLinesCount else begin
    GlobalResult := 1;
    x := SysBorderWidth(Form.Handle, BorderForm);
    ItemProcessed := 0;
    if Form.Menu <> nil then begin
      ChangedIndex := -1;
      Index := 0;
      VisIndex := 0;
      while Index <= Form.Menu.Items.Count - 1 do begin
        if (x = SysBorderWidth(Form.Handle, BorderForm)) and (MDISkinProvider = Self) and ChildIconPresent then begin
          GetMenuItemRect(Form.Handle, Form.Menu.Handle, 0, R);
          inc(x, WidthOf(R));
          inc(VisIndex);
          Continue;
        end;
        CurrentItem := Form.Menu.Items[Index];
        if (CurrentItem.GroupIndex = ChangedIndex) or ProcessMerged(CurrentItem.GroupIndex) then begin
          inc(Index);
          continue;
        end
        else begin
          if not Assigned(CurrentItem.OnMeasureItem) or not Assigned(CurrentItem.OnAdvancedDrawItem) or not CurrentItem.Visible then begin
            inc(Index);
            Continue;
          end;

          GetMenuItemRect(Form.Handle, Form.Menu.Handle, VisIndex, R);
          w := WidthOf(R);

          if x + w > Form.Width - 2 * SysBorderWidth(Form.Handle, BorderForm) - 2 * TForm(Form).BorderWidth then begin
            inc(GlobalResult);
            x := SysBorderWidth(Form.Handle, BorderForm);
          end;

          inc(x, w);
          inc(Index);
          inc(VisIndex);
        end;
      end;
      ProcessMerged(MaxInt);
    end;
    Result := GlobalResult;
    FLinesCount := Result;
  end;
end;

procedure TsSkinProvider.Loaded;
var
  mi, i : integer;
begin
  inherited;
  if Assigned(FCommonData.SkinManager) and not (csDesigning in ComponentState) and FCommonData.Skinned(True) then begin
    if Form.HandleAllocated then InitDwm(Form.Handle, True); // v6.43
{    if (Form <> nil) then begin
      OldWndProc := Form.WindowProc;
      Form.WindowProc := NewWndProc;
      IntSkinForm(Form);

      FormActive := True;
    end;}
    if Adapter = nil then AdapterCreate;
    PrepareForm;
    if Assigned(SystemMenu) then SystemMenu.UpdateItems;

    mi := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_TitleButtonMask);
    for i := 0 to TitleButtons.Count - 1 do
      if TitleButtons.Items[i].UseSkinData
        then TitleButtons.Items[i].BtnData.ImageIndex := mi
        else TitleButtons.Items[i].BtnData.ImageIndex := -1;

    if Assigned(MDIForm) then begin
      TsMDIForm(MDIForm).ConnectToClient;
    end;
  end
end;

procedure TsSkinProvider.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (AComponent is TsSkinManager) then case Operation of
    opInsert : if not Assigned(SkinData.SkinManager) then SkinData.SkinManager := TsSkinManager(AComponent);
    opRemove : if AComponent = SkinData.SkinManager then SkinData.SkinManager := nil;
  end
  else if (AComponent is TWinControl) then case Operation of
    opInsert : if Assigned(Adapter) then begin
      if TacCtrlAdapter(Adapter).IsControlSupported(TWincontrol(AComponent)) then TacCtrlAdapter(Adapter).AddNewItem(TWincontrol(AComponent));
    end;
  end;
end;

function TsSkinProvider.FormChanged: boolean;
begin
  Result := (FCommonData.FCacheBmp = nil) or (CaptionWidth <> FCommonData.FCacheBmp.Width) or (Form.Height <> FCommonData.FCacheBmp.Height)
end;

procedure TsSkinProvider.RepaintMenuItem(mi: TMenuItem; R: TRect; State : TOwnerDrawState);
var
  DC, SavedDC : hdc;
begin
  SavedDC := 0;
  if MenuPresent and (Form.Menu.FindItem(mi.Handle, fkHandle) <> nil) then begin
    mi.OnAdvancedDrawItem(mi, FCommonData.FCacheBmp.Canvas, R, State);
    DC := GetWindowDC(Form.Handle);
    try
      SavedDC := SaveDC(DC);
      BitBlt(DC, R.Left, R.Top, WidthOf(R), HeightOf(R), FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, SRCCOPY);
    finally
      RestoreDC(DC, SavedDC);
      ReleaseDC(Form.Handle, DC);
    end;
  end;
end;

function TsSkinProvider.SmallButtonWidth: integer;
begin
  if FCommonData.SkinManager.IsValidImgIndex(MDIClose.ImageIndex) then begin
    if Assigned(FCommonData.SkinManager.ma[MDIClose.ImageIndex].Bmp)
      then Result := FCommonData.SkinManager.ma[MDIClose.ImageIndex].Bmp.Width div 3
      else Result := WidthOf(FCommonData.SkinManager.ma[MDIClose.ImageIndex].R) div FCommonData.SkinManager.ma[MDIClose.ImageIndex].ImageCount;
  end
  else Result := 16;
end;

function TsSkinProvider.SmallButtonHeight: integer;
begin
  if FCommonData.SkinManager.IsValidImgIndex(MDIClose.ImageIndex) then begin
    if Assigned(FCommonData.SkinManager.ma[MDIClose.ImageIndex].Bmp)
      then Result := FCommonData.SkinManager.ma[MDIClose.ImageIndex].Bmp.Height div 2
      else Result := HeightOf(FCommonData.SkinManager.ma[MDIClose.ImageIndex].R) div (FCommonData.SkinManager.ma[MDIClose.ImageIndex].MaskType + 1);
  end
  else Result := 16;
end;

function TsSkinProvider.HeaderHeight: integer;
begin
  if (BorderForm <> nil) then begin
    Result := CaptionHeight + SysBorderHeight(Form.Handle, BorderForm, False);
  end
  else
    if CaptionHeight(BorderForm = nil) = 0
      then Result := GetWindowHeight(Form.Handle) - GetClientHeight(Form.Handle)
      else Result := GetWindowHeight(Form.Handle) - GetClientHeight(Form.Handle) - BorderHeight;

  if Result < 0 then Result := 0;
  if IsIconic(Form.Handle) then inc(Result, SysBorderHeight(Form.Handle, BorderForm, False));
  if SkinData.Skinned and Assigned(ListSW) and Assigned(ListSW.sBarHorz) and ListSW.sBarHorz.fScrollVisible then begin
    dec(Result, GetScrollMetric(ListSW.sBarHorz, SM_CYHORZSB));
  end;
end;

function TsSkinProvider.MDIButtonsNeeded: boolean;
begin
  Result := (ChildProvider <> nil) and (Form.FormStyle = fsMDIForm) and Assigned(Form.ActiveMDIChild) and
              (Form.ActiveMDIChild.WindowState = wsMaximized) and (Form.Menu <> nil) and (biSystemMenu in Form.ActiveMDIChild.BorderIcons);
end;

function TsSkinProvider.MenuHeight: integer;
begin
  if Form.Menu <> nil then Result := GetSystemMetrics(SM_CYMENU) - 1 else Result := 0;
end;

type
  TAccessMenuItem = class(TMenuItem);

function TsSkinProvider.UpdateMenu : boolean;
begin
  Result := False;
  if not fGlobalFlag then begin
    fGlobalFlag := True;
    if (Form.Menu <> nil) and (Form.Menu.Items.Count > 0) and (Form.Menu.Items[0] <> nil) then begin
      TAccessMenuItem(Form.Menu.Items[0]).MenuChanged(True);
      Result := True;
    end;
    fGlobalFlag := False;
  end;
end;

function TsSkinProvider.IconVisible: boolean;
begin
  Result := ((Form.BorderStyle = bsSizeable) or (Form.BorderStyle = bsSingle)) and FShowAppIcon and (GetSystemMenu(Form.Handle, False) <> 0);
end;

procedure TsSkinProvider.MakeTitleBG;
begin
  if TitleBG <> nil then FreeAndNil(TitleBG);
  TitleBG := CreateBmp32(FCommonData.FCacheBmp.Width, CaptionHeight + SysBorderHeight(Form.Handle, BorderForm) + ShadowSize.Top);
  BitBlt(TitleBG.Canvas.Handle, 0, 0, TitleBG.Width, TitleBG.Height, FCommonData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

procedure TsSkinProvider.PrepareCaption(CI: TCacheInfo; R : TRect);
var
  i : integer;
  s : acString;
  sRect : TRect;
  ts : TSize;
begin
  i := FCommonData.SkinManager.GetSkinIndex(TitleSkinSection); // Paint title
  PaintItem(i, TitleSkinSection, ci, True, integer(FormActive), Rect(0, 0, R.Right, R.Bottom), Point(0, 0), FCommonData.FCacheBmp, FCommonData.SkinManager);

  DrawAppIcon(Self);
  if (SysButtonsCount > 0) then begin
    // Paint title toolbar if exists
    i := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinIndex, FCommonData.SkinSection, s_NormalTitleBar);
    if FCommonData.SkinManager.IsValidImgIndex(i)
      then DrawSkinRect(FCommonData.FCacheBmp, Rect(R.Right - BarWidth(i), 0, R.Right, R.Bottom), True, EmptyCI, FCommonData.SkinManager.ma[i], integer(FormActive), True);
  end;
  SaveBGForBtns; 
  // Paint buttons
  PaintBorderIcons;

  // Out title text
  FCommonData.FCacheBmp.Canvas.Font.Handle := acGetTitleFont;
  FCommonData.FCacheBmp.Canvas.Font.Height := GetCaptionFontSize;
  FCommonData.FCacheBmp.Canvas.Font.Style := FCommonData.FCacheBmp.Canvas.Font.Style + [fsBold];

  sRect := Rect(SysBorderWidth(Form.Handle, BorderForm) + integer(IconVisible) * WidthOf(IconRect) + 4 + SkinData.SkinManager.SkinData.BILeftMargin + ShadowSize.Left,
                2 + ShadowSize.Top, SkinData.FCacheBmp.Width - ShadowSize.Right - TitleBtnsWidth - 6, CaptionHeight + SysBorderHeight(Form.Handle, BorderForm, False) + ShadowSize.Top);

  if not IsRectEmpty(sRect) then begin
{$IFDEF TNTUNICODE}
    s := WideString(GetWndText(Form.Handle));
    GetTextExtentPoint32W(FCommonData.FCacheBmp.Canvas.Handle, PWideChar(s), Length(s), ts);
    sRect.Top := sRect.Top + (HeightOf(sRect) - ts.cy) div 2;
    sRect.Bottom := sRect.Top + ts.cy;
    WriteTextExW(FCommonData.FCacheBmp.Canvas, PWideChar(s), Form.Enabled, sRect,
      GetStringFlags(Form, FCaptionAlignment) or DT_END_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX, FCommonData.SkinManager.GetSkinIndex(TitleSkinSection),
      FormActive, FCommonData.SkinManager)
{$ELSE}
    s := Form.Caption;
    GetTextExtentPoint32(FCommonData.FCacheBmp.Canvas.Handle, PacChar(s), Length(s), ts);
    sRect.Top := sRect.Top + (HeightOf(sRect) - ts.cy) div 2;
    sRect.Bottom := sRect.Top + ts.cy;
    acWriteTextEx(FCommonData.FCacheBmp.Canvas, PChar(s), Form.Enabled, sRect,
      GetStringFlags(Form, FCaptionAlignment) or DT_END_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX, FCommonData.SkinManager.GetSkinIndex(TitleSkinSection),
      FormActive, FCommonData.SkinManager);
{$ENDIF}
  end;
end;

procedure TsSkinProvider.SetCaptionAlignment(const Value: TAlignment);
begin
  if FCaptionAlignment <> Value then begin
    FCaptionAlignment := Value;
    FCommonData.BGChanged := True;
    if Form.Visible then SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
  end;
end;

procedure TsSkinProvider.SetShowAppIcon(const Value: boolean);
begin
  if FShowAppIcon <> Value then begin
    FShowAppIcon := Value;
    FCommonData.BGChanged := True;
    if Form.Visible then SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
  end;
end;

procedure TsSkinProvider.SetTitleButtons(const Value: TsTitleButtons);
begin
  FTitleButtons.Assign(Value);
end;

function TsSkinProvider.RBGripPoint(ImgIndex : integer): TPoint;
begin
  Result := Point(FCommonData.FCacheBmp.Width - WidthOfImage(FCommonData.SkinManager.ma[ImgIndex]) - SysBorderWidth(Form.Handle, BorderForm) - ShadowSize.Right - 1,
                  FCommonData.FCacheBmp.Height - HeightOfImage(FCommonData.SkinManager.ma[ImgIndex]) - SysBorderWidth(Form.Handle, BorderForm) - ShadowSize.Bottom - 1);
end;

procedure TsSkinProvider.InitMenuItems(A: boolean);
var
  i : integer;
  procedure ProcessComponent(c: TComponent);
  var
    i: integer;
  begin
    if (c <> nil) then begin
      if (c is TMainMenu) then begin
        FCommonData.SkinManager.SkinableMenus.InitMenuLine(TMainMenu(c), A and FDrawNonCLientArea);
        for i := 0 to TMainMenu(c).Items.Count - 1 do
          FCommonData.SkinManager.SkinableMenus.HookItem(TMainMenu(c).Items[i], A and FCommonData.SkinManager.SkinnedPopups);
      end
      else if (c is TPopupMenu) then FCommonData.SkinManager.SkinableMenus.HookPopupMenu(TPopupMenu(c), A and FCommonData.SkinManager.SkinnedPopups)
        else if (c is TMenuItem) then if not (TMenuItem(c).GetParentMenu is TMainMenu)
          then FCommonData.SkinManager.SkinableMenus.HookItem(TMenuItem(c), A and FCommonData.SkinManager.SkinnedPopups)
          else for i := 0 to c.ComponentCount - 1 do ProcessComponent(c.Components[i]);
    end;
  end;
begin
  if (csDesigning in Form.ComponentState) or (FCommonData.SkinManager.SkinableMenus = nil) or not FCommonData.SkinManager.IsDefault then Exit;
  for i := 0 to Form.ComponentCount - 1 do ProcessComponent(Form.Components[i]);
end;

procedure TsSkinProvider.StartMove(X, Y: Integer);
begin
  if ResizeMode = rmBorder then begin
    //Common section
    bInProcess := TRUE;
    deskwnd    := GetDesktopWindow();
    formDC     := GetWindowDC(deskwnd);
    nDC        := SaveDC(formDC);
    ntop       := Form.Top;
    nleft      := Form.Left;
    SetROP2(formDC, R2_NOT);

    if bMode then begin //Move section
      nX := X;
      nY := Y;
      DrawFormBorder(nleft, ntop);
    end
    else begin //Size section
      nMinHeight := Form.Constraints.MinHeight;
      nMinWidth  := Form.Constraints.MinWidth;
      nbottom    := Form.top + Form.height;
      nright     := Form.left + Form.width;
      DrawFormBorder(0, 0);
    end;
  end;
end;

procedure TsSkinProvider.StopMove(X, Y: Integer);
begin
  if ResizeMode = rmBorder then begin
    //Common section
    ReleaseCapture;
    bInProcess := FALSE;

    if bMode then begin //Move section
      DrawFormBorder(nleft, ntop);
      RestoreDC(formDC, nDC);
      ReleaseDC(deskwnd, formDC);
      MoveWindow(Form.handle, nleft, ntop, Form.width, Form.height, TRUE)
    end
    else begin //Size section
      DrawFormBorder(0,0);
      RestoreDC(formDC, nDC);
      ReleaseDC(deskwnd, formDC);
      if not bCapture then MoveWindow(Form.handle, nleft, ntop, nright - nleft, nbottom - ntop, TRUE);
      bCapture := FALSE;
    end;
  end;
end;

procedure TsSkinProvider.DrawFormBorder(X, Y: Integer);
var
  pts : array [1..5] of TPoint;
  incX, incY : integer;
begin
  if ResizeMode = rmBorder then begin
    if Form.FormStyle = fsMDIChild then with TsSkinProvider(MDISkinProvider) do begin
      incX := Form.Left + SysBorderWidth(Form.Handle, BorderForm) + Form.BorderWidth + 1;
      incY := Form.Top + SysBorderHeight(Form.Handle, BorderForm) * 2 + CaptionHeight + LinesCount * MenuHeight * integer(MenuPresent) + Form.BorderWidth - 2;
      X := X + incX;
      Y := Y + incY;
    end
    else begin
      incX := 0;
      incY := 0;
    end;
    if bMode then begin //Move section
      pts[1] := point(X, Y);
      pts[2] := point(X, Y + Form.Height);
      pts[3] := point(X + Form.Width, Y + Form.Height);
      pts[4] := point(X + Form.Width, Y);
      pts[5] := point(X, Y);
      PolyLine(formDC, pts, 5);
    end
    else begin //Size section
      pts[1].X := nleft + incX;
      pts[1].Y := ntop + incY;
      pts[2].X := nleft + incX;
      pts[2].Y := nbottom + incY;
      pts[3].X := nright + incX;
      pts[3].Y := nbottom + incY;
      pts[4].X := nright + incX;
      pts[4].Y := ntop + incY;
      pts[5].X := nleft + incX;
      pts[5].Y := ntop + incY;
      PolyLine(formDC, pts, 5);
    end;
  end;
end;

procedure TsSkinProvider.SetUseGlobalColor(const Value: boolean);
begin
  if FUseGlobalColor <> Value then begin
    FUseGlobalColor := Value;
    if FCommonData.Skinned and Assigned(Form) and Value and not SkinData.CustomColor then Form.Color := FCommonData.SkinManager.GetGlobalColor else Form.Color := clBtnFace;
  end;
end;

procedure TsSkinProvider.RepaintMenu;
begin
  SkinData.BGChanged := True;
  MenuChanged := True;
  FLinesCount := -1;
  SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
end;

function TsSkinProvider.CaptionWidth: integer;
var
  R : TRect;
begin
  if IsIconic(Form.Handle) then begin
    GetWindowRect(Form.Handle, R);
    Result := WidthOf(R)
  end
  else Result := Form.Width + integer(BorderForm <> nil) * 2 * DiffBorder(Self.BorderForm);
  inc(Result, ShadowSize.Left + ShadowSize.Right);
end;

procedure TsSkinProvider.UpdateIconsIndexes;
begin
  if FCommonData.SkinManager.IsValidSkinIndex(FCommonData.SkinManager.ConstData.IndexGlobalInfo) then begin
    ButtonMin.HitCode := HTMINBUTTON;
    ButtonMax.HitCode := HTMAXBUTTON;
    ButtonClose.HitCode := HTCLOSE;
    with FCommonData.SkinManager do begin // For compatibility with skins with version < 4.33
      if BigButtons(Self) then begin
        ButtonMin.ImageIndex    := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMinimize);
        ButtonMax.ImageIndex    := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMaximize);
        ButtonClose.ImageIndex  := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconClose);
        ButtonHelp.ImageIndex   := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconHelp);
        ButtonMin.HaveAlignment := True;
      end
      else begin
        ButtonClose.ImageIndex  := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconClose);
        ButtonMin.ImageIndex    := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconMinimize);
        ButtonMax.ImageIndex    := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconMaximize);
        ButtonHelp.ImageIndex   := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconHelp);
        if ButtonHelp.ImageIndex < 0 then ButtonHelp.ImageIndex := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconHelp);
        ButtonMin.HaveAlignment := False;
      end;
      ButtonMax.HaveAlignment   := ButtonMin.HaveAlignment;
      ButtonClose.HaveAlignment := ButtonMin.HaveAlignment;
      ButtonHelp.HaveAlignment  := ButtonMin.HaveAlignment;

      if ButtonClose.ImageIndex < 0 then begin
        ButtonClose.ImageIndex  := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconClose);
        ButtonMin.ImageIndex    := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMinimize);
        ButtonMax.ImageIndex    := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMaximize);
        ButtonHelp.ImageIndex   := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconHelp);
        ButtonMin.HaveAlignment   := True;
        ButtonMax.HaveAlignment   := True;
        ButtonClose.HaveAlignment := True;
        ButtonHelp.HaveAlignment  := True;

        if (Form.FormStyle = fsMDIForm) and not (csDesigning in ComponentState) then begin
          MDIMin.ImageIndex       := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMinimize);
          MDIMax.ImageIndex       := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMaximize);
          MDIClose.ImageIndex     := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconClose);
        end;
        MDIMin.HaveAlignment   := True;
        MDIMax.HaveAlignment   := True;
        MDIClose.HaveAlignment := True;
      end
      else begin
        if (Form.FormStyle = fsMDIForm) and not (csDesigning in ComponentState) then begin
          MDIMin.ImageIndex       := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconMinimize);
          MDIMax.ImageIndex       := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconMaximize);
          MDIClose.ImageIndex     := GetMaskIndex(ConstData.IndexGlobalInfo, s_GlobalInfo, s_SmallIconClose);
          MDIMin.HaveAlignment   := False;
          MDIMax.HaveAlignment   := False;
          MDIClose.HaveAlignment := False;
        end;
        if MDIMin.ImageIndex < 0 then begin // Leaved for compatibility, should be removed later
          MDIMin.ImageIndex       := ButtonMin.ImageIndex;
          MDIMax.ImageIndex       := ButtonMax.ImageIndex;
          MDIClose.ImageIndex     := ButtonClose.ImageIndex;
          MDIMin.HaveAlignment   := True;
          MDIMax.HaveAlignment   := True;
          MDIClose.HaveAlignment := True;
        end;
      end;
    end;        
    UserBtnIndex := FCommonData.SkinManager.GetMaskIndex(FCommonData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_TitleButtonMask);
  end;
end;

procedure TsSkinProvider.SetTitleSkin(const Value: TsSkinSection);
begin
  if FTitleSkin <> Value then begin
    FTitleSkin := Value;
    FCommonData.BGChanged := True;
    if Form.Visible then SendMessage(Form.Handle, WM_NCPAINT, 0, 0);
    if BorderForm <> nil then BorderForm.UpdateExBordersPos;
  end;
end;

function TsSkinProvider.TitleSkinSection: string;
begin
  if FTitleSkin = '' then Result := s_FormTitle else Result := FTitleSkin
end;

procedure TsSkinProvider.SetMenuLineSkin(const Value: TsSkinSection);
begin
  if (FMenuLineSkin <> Value) then begin
    FMenuLineSkin := Value;
    if (csDesigning in ComponentState) then SkinData.Invalidate;
  end;
end;

procedure TsSkinProvider.PrepareForm;
begin
  if (FCommonData.SkinManager = nil) or (Form = nil) or not Form.HandleAllocated then Exit;
  FCommonData.Loaded;
  CheckSysMenu(FCommonData.SkinManager.SkinData.Active);
//  if not FDrawNonClientArea then SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_SYSMENU);
  if SystemMenu = nil then begin
    SystemMenu := TsSystemMenu.Create(Self);
    SystemMenu.FForm := Form;
    SystemMenu.UpdateItems;
  end;

  if ClearButtons and FCommonData.SkinManager.SkinData.Active then begin
    ClearButtons := False;
    if (Form.FormStyle = fsMDIForm) and not (csDesigning in ComponentState) then HookMDI;
  end;
  FCommonData.UpdateIndexes;
  UpdateIconsIndexes;

  RegionChanged := True;
  CaptChanged := True;
  CaptRgnChanged :=True;

  // If form is MDIChild and menus are merged then
  if (Form.FormStyle = fsMDIChild) then begin
    if Assigned(MDISkinProvider) and
         not (csDestroying in TsSkinProvider(MDISkinProvider).ComponentState) and
           not (csDestroying in TsSkinProvider(MDISkinProvider).Form.ComponentState) and SkinData.Skinned
             then begin
      TsSkinProvider(MDISkinProvider).FCommonData.BGChanged := True;
      TsSkinProvider(MDISkinProvider).FLinesCount := -1;
    end;
  end;
  if (Form <> nil) and not (csCreating in Form.ControlState) and not (csReadingState in Form.ControlState) and
       not (csLoading in componentState) and (SkinData.SkinManager <> nil) and UseGlobalColor and not SkinData.CustomColor
    then Form.Color := SkinData.SkinManager.GetGlobalColor;
  InitMenuItems(SkinData.Skinned);
  if not MenusInitialized then begin
    if UpdateMenu then MenusInitialized := True;
  end;
  if SystemMenu <> nil then SystemMenu.UpdateGlyphs;

  if not (csLoading in Form.ComponentState) then InitExBorders(SkinData.SkinManager.ExtendedBorders);
end;

procedure TsSkinProvider.HookMDI(Active: boolean);
begin
  if Active then begin
    if not Assigned(MDIForm) then begin
      MDISkinProvider := Self;
      TsMDIForm(MDIForm) := TsMDIForm.Create(Self);
      if MDIForm <> nil then TsMDIForm(MDIForm).ConnectToClient;
    end;
  end
  else begin
    if Assigned(MDIForm) then FreeAndNil(MDIForm);
  end;
end;

procedure TsSkinProvider.DsgnWndProc(var Message: TMessage);
begin
  if ChangeFormsInDesign and (csDesigning in ComponentState) and
       Assigned(SkinData) and
         Assigned(SkinData.SkinManager) and
           Assigned(Form) and
             UseGlobalColor and
               not SkinData.CustomColor and
                 (Message.WParamHi in [AC_SETNEWSKIN, AC_REFRESH, AC_REMOVESKIN]) and
                   (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) then if Message.Msg = SM_ALPHACMD then case Message.WParamHi of
    AC_SETNEWSKIN, AC_REFRESH : Form.Color := SkinData.SkinManager.GetGlobalColor;
    AC_REMOVESKIN : Form.Color := clBtnFace;
  end;
end;

function TsSkinProvider.TitleBtnsWidth: integer;
var
  i : integer;
begin
  Result := FCommonData.SkinManager.SkinData.BIRightMargin;
  if Assigned(SystemMenu) and SystemMenu.VisibleClose then begin
    inc(Result, SysButtonWidth(ButtonClose));// v6.41 + integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing);
    if SystemMenu.VisibleMax then inc(Result, SysButtonWidth(ButtonMax) + integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing);
    if SystemMenu.VisibleMin then inc(Result, SysButtonWidth(ButtonMin) + integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing);
    if (biHelp in Form.BorderIcons) then inc(Result, SysButtonWidth(ButtonHelp) + integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing);
  end;

  if TitleButtons.Count > 0 then inc(Result, UserButtonsOffset);
  for i := 0 to TitleButtons.Count - 1 do begin
    inc(Result, UserButtonWidth(TitleButtons[i]) + integer(BigButtons(Self)) * FCommonData.SkinManager.SkinData.BISpacing);
  end;
end;

function TsSkinProvider.UserButtonWidth(Btn: TsTitleButton): integer;
begin
  if Assigned(Btn.Glyph) then Result := Btn.Glyph.Width + 2 else Result := 0;
  if FCommonData.SkinManager.IsValidImgIndex(UserBtnIndex)
    then Result := max(Result, WidthOf(FCommonData.SkinManager.ma[UserBtnIndex].R) div FCommonData.SkinManager.ma[UserBtnIndex].ImageCount)
    else Result := max(Result, 21);
end;

procedure TsSkinProvider.AdapterCreate;
begin
  if not (csDesigning in ComponentState) and FCommonData.Skinned then begin
    Adapter := TacCtrlAdapter.Create(Self);
    TacCtrlAdapter(Adapter).AddAllItems;
  end;
end;

procedure TsSkinProvider.AdapterRemove;
begin
  if not (csDesigning in ComponentState) then begin
    SendToAdapter(MakeMessage(SM_ALPHACMD, MakeWParam(0, AC_REMOVESKIN), LongWord(SkinData.SkinManager), 0));
    FreeAndNil(Adapter);
  end;
end;

procedure TsSkinProvider.SendToAdapter(Message: TMessage);
begin
  if not (csDesigning in ComponentState) and Assigned(Adapter) then TacCtrlAdapter(Adapter).WndProc(Message)
end;

procedure TsSkinProvider.MdiIcoFormPaint(Sender: TObject);
begin
{ Is not required while form is not drawn
  with TForm(Sender) do BitBlt(Canvas.Handle, 0, 0,
      60, GetSystemMetrics(SM_CYMENU) - 1 + 4, SkinData.FCacheBmp.Canvas.Handle,
      Form.Width - 60 + SysBorderWidth(False) - ShadowSize.Right, CaptionHeight + ShadowSize.Top, SRCCOPY);
}
end;

procedure TsSkinProvider.CaptFormPaint(Sender: TObject);
begin
{ Is not required while form is not drawn
  if (CaptForm <> nil) and not (csDestroying in CaptForm.ComponentState)
    then BitBlt(CaptForm.Canvas.Handle, 0, 0, CaptForm.Width, CaptForm.Height, SkinData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);
}
end;

procedure TsSkinProvider.NewCaptFormProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_ERASEBKGND : Exit;
  end;
  OldCaptFormProc(Message);
end;

procedure TsSkinProvider.SaveBGForBtns(Full : boolean = False);
begin
  TempBmp.PixelFormat := FCommonData.FCacheBmp.PixelFormat;
  TempBmp.Width := TitleBtnsWidth + SysBorderWidth(Form.Handle, BorderForm) + 10 + ShadowSize.Right;
  TempBmp.Height := CaptionHeight + SysBorderHeight(Form.Handle, BorderForm) + SysBorderWidth(Form.Handle, BorderForm, False) + MenuHeight + ShadowSize.Top;
  BitBlt(TempBmp.Canvas.Handle, 0, 0, TempBmp.Width, iffi(Full, TempBmp.Height, CaptionHeight + SysBorderHeight(Form.Handle, BorderForm)),
         FCommonData.FCacheBmp.Canvas.Handle, CaptionWidth - TempBmp.Width - 1, 0, SRCCOPY);
end;

procedure TsSkinProvider.RestoreBtnsBG;
begin
  if Assigned(TempBmp) then BitBlt(FCommonData.FCacheBmp.Canvas.Handle, CaptionWidth - TempBmp.Width - 1, 0, TempBmp.Width, TempBmp.Height, TempBmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

procedure TsSkinProvider.AC_WMEraseBkGnd(const aDC: hdc);
var
  DC, SavedDC : hdc;
begin
  if aDC = 0 then DC := GetDC(Form.Handle) else DC := aDC;
  try
    FCommonData.FUpdating := False;
    if not fAnimating and not (csDestroying in Form.ComponentState) and not ((Form.FormStyle = fsMDIChild) and (MDISkinProvider <> nil) and not MDICreating and
         Assigned(TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) and (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState = wsMaximized)
           and (Form <> TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild)) then begin
      SavedDC := SaveDC(DC);
      ExcludeControls(DC, Form, actGraphic, 0, 0);
      PaintForm(DC);

      if IsGripVisible(Self) then begin
        MoveWindowOrg(DC, -OffsetX, -OffsetY);
        PaintGrip(DC, Self);
      end;
      RestoreDC(DC, SavedDC);
      PaintControls(DC, Form, True, Point(0, 0));
    end;
  finally
    if aDC = 0 then ReleaseDC(Form.Handle, DC);
  end;
end;

procedure TsSkinProvider.AC_WMNCPaint;
var
  DC, SavedDC : hdc;
  i, y, th, sbw, dy : integer;
begin
  if MDICreating or not FDrawNonClientArea then Exit; // If maximized mdi child was created
  if (ResizeMode = rmBorder) and AeroIsEnabled then ResizeMode := rmStandard;
  if (Form.FormStyle = fsMDIChild) then begin
    if (MDISkinProvider <> nil) and
          Assigned(TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) and
            (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState = wsMaximized)
              and (Form <> TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) then Exit;
  end;

  if not MenusInitialized and UpdateMenu then MenusInitialized := True;

  if not RgnChanging and RgnChanged and (HaveBorder(Self) or IsSizeBox(Form.Handle) or IsIconic(Form.Handle)) then begin
    FillArOR(Self);
    RgnChanged := False;
    if (fsShowing in Form.FormState) and (Form.Position <> poDefault) and (Form.WindowState <> wsMaximized) then UpdateRgn(Self, False) else begin
      UpdateRgn(Self, True);
      Exit
    end;
  end;
  FCommonData.Updating := False;
  if (SkinData.FCacheBmp <> nil) and (SkinData.FCacheBmp.Width = 0) then SkinData.BGChanged := True; // If Cache is not ready

  DC := GetWindowDC(Form.Handle);
  SavedDC := SaveDC(DC);

  try
    if (BorderForm <> nil) then begin
      i := Form.BorderWidth;
      y := CaptionHeight(False);
      inc(y, SysBorderWidth(Form.Handle, BorderForm, False));
      if FSysExHeight then dec(y, 4);
      if FCommonData.BGChanged then PaintAll;

      th := y + MenuHeight * LinesCount + integer(Form.Menu <> nil) + Form.BorderWidth;
      dy := OffsetY - MenuHeight * LinesCount - Form.BorderWidth;
      BitBlt(DC, SysBorderWidth(Form.Handle, BorderForm, False), y, FCommonData.FCacheBmp.Width - ShadowSize.Left - ShadowSize.Right, MenuHeight * LinesCount + integer(Form.Menu <> nil) + Form.BorderWidth,
        FCommonData.FCacheBmp.Canvas.Handle,
        SysBorderWidth(Form.Handle, BorderForm) + ShadowSize.Left, dy, SRCCOPY); // Title and menu line update

      if i <> 0 then begin
        sbw := SysBorderWidth(Form.Handle, BorderForm, False);

        // Left
        BitBlt(DC, sbw, th, i, Form.Height - sbw, FCommonData.FCacheBmp.Canvas.Handle, OffsetX - Form.BorderWidth, OffsetY, SRCCOPY);
        // Bottom
        BitBlt(DC, sbw + Form.BorderWidth, Form.Height - i - sbw, Form.Width - i - sbw - Form.BorderWidth, i, FCommonData.FCacheBmp.Canvas.Handle, BorderWidth + ShadowSize.Left, FCommonData.FCacheBmp.Height - BorderWidth - ShadowSize.Bottom, SRCCOPY); // Bottom border update
        // Right
        BitBlt(DC, Form.Width - i - sbw, th, i, FCommonData.FCacheBmp.Height - sbw, FCommonData.FCacheBmp.Canvas.Handle, FCommonData.FCacheBmp.Width - BorderWidth - ShadowSize.Right, OffsetY, SRCCOPY); // Right border update
      end;
    end
    else if not HaveBorder(Self) and IsSizeBox(Form.Handle) and not IsIconic(Form.Handle) then begin
      if FCommonData.BGChanged then PaintAll;

      i := BorderWidth + 3;
      BitBlt(DC, 0, 0, Form.Width, i, FCommonData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY); // Title and menu line update
      BitBlt(DC, 0, i, i, FCommonData.FCacheBmp.Height, FCommonData.FCacheBmp.Canvas.Handle, 0, i, SRCCOPY); // Left border update
      BitBlt(DC, i, Form.Height - i, Form.Width - i, i, FCommonData.FCacheBmp.Canvas.Handle, i, Form.Height - i, SRCCOPY); // Bottom border update
      BitBlt(DC, FCommonData.FCacheBmp.Width - i, i, i, FCommonData.FCacheBmp.Height, FCommonData.FCacheBmp.Canvas.Handle, FCommonData.FCacheBmp.Width - i, i, SRCCOPY); // Right border update
    end
    else PaintCaption(DC);

  finally
    RestoreDC(DC, SavedDC);
    ReleaseDC(Form.Handle, DC);
  end;

  RgnChanging := False;
end;

function TsSkinProvider.FormColor: TColor;
begin
  if FCOmmonData.Skinned and not SkinData.CustomColor then begin
    if FormActive
      then Result := FCommonData.SkinManager.gd[FCommonData.Skinindex].HotColor
      else Result := FCommonData.SkinManager.gd[FCommonData.Skinindex].Color
  end
  else Result := ColorToRGB(Form.Color);
end;

procedure TsSkinProvider.OurPaintHandler(const Msg: TWMPaint);
var
  SavedDC : hdc;
  PS : TPaintStruct;
begin
  if InAnimationProcess and (Msg.DC = 0) then Exit;
  if not InAnimationProcess then BeginPaint(Form.Handle, PS);
  SavedDC := SaveDC(Form.Canvas.Handle);
  try
    Form.Canvas.Lock;
    FCommonData.FUpdating := False;
    if not fAnimating and not (csDestroying in Form.ComponentState) and not ((Form.FormStyle = fsMDIChild) and (MDISkinProvider <> nil) and not MDICreating and
         Assigned(TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild) and (TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild.WindowState = wsMaximized)
           and (Form <> TsSkinProvider(MDISkinProvider).Form.ActiveMDIChild)) then begin
      PaintForm(Form.Canvas.Handle);
    end;
  finally
    Form.Canvas.UnLock;
    RestoreDC(Form.Canvas.Handle, SavedDC);
    Form.Canvas.Handle := 0;
    if not InAnimationProcess then EndPaint(Form.Handle, PS);
  end;
end;

procedure TsSkinProvider.CheckSysMenu(const Skinned: boolean);
begin
  if Skinned then begin
    if (GetWindowLong(Form.Handle, GWL_STYLE) and WS_SYSMENU = WS_SYSMENU) or HaveSysMenu then begin
      if FDrawNonClientArea
        then SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) and not WS_SYSMENU)
        else SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_SYSMENU);
      HaveSysMenu := True;
    end
    else HaveSysMenu := False;
  end
  else begin
    if HaveSysMenu then SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_SYSMENU);
    HaveSysMenu := False;
  end;
end;

procedure TsSkinProvider.SetDrawNonClientArea(const Value: boolean);
begin
  if (FDrawNonClientArea <> Value) then begin
    FDrawNonClientArea := Value;
    if (csDesigning in ComponentState) then Exit;
    if Value then begin
      CheckSysMenu(True);

      if not (csDesigning in ComponentState) and (Form <> nil) and Form.Showing and SkinData.Skinned then begin
        SkinData.BGChanged := True;
        FreeAndNil(TitleBG);
        SkinData.SkinManager.SkinableMenus.InitMenuLine(Form.Menu, True);
        InitExBorders(SkinData.SkinManager.ExtendedBorders);
        RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_UPDATENOW);
        RefreshFormScrolls(Self, ListSW, False);
      end;
    end
    else begin
      if BorderForm <> nil then FreeAndNil(BorderForm);
        SkinData.SkinManager.SkinableMenus.InitMenuLine(Form.Menu, False);
      if (uxthemeLib <> 0) then Ac_SetWindowTheme(Form.Handle, nil, nil);
      if ListSW <> nil then FreeAndNil(ListSW);
      if HaveSysMenu then SetWindowLong(Form.Handle, GWL_STYLE, GetWindowLong(Form.Handle, GWL_STYLE) or WS_SYSMENU);
      if Form.Showing then SetWindowRgn(Form.Handle, 0, True);
      if BorderForm <> nil then BorderForm.UpdateExBordersPos;
    end;
  end;
end;

procedure TsSkinProvider.AC_WMNCCalcSize(var Message: TWMNCCalcSize);
begin
{  if Message.CalcValidRects and FDrawNonClientArea and (Form.WindowState = wsMaximized) and (BorderForm <> nil) then begin
    inc(Message.CalcSize_Params.rgrc[0].Top, CaptionHeight(BorderForm = nil) + MenuHeight * LinesCount + BorderHeight(BorderForm = nil));
    inc(Message.CalcSize_Params.rgrc[0].Left, BorderWidth(BorderForm = nil));
    dec(Message.CalcSize_Params.rgrc[0].Right, BorderWidth(BorderForm = nil));
    dec(Message.CalcSize_Params.rgrc[0].Bottom, BorderWidth(BorderForm = nil));
    Message.Result := 0;
  end
  else}
  OldWndProc(TMessage(Message));
end;
(*
procedure TsSkinProvider.AC_NCMouseMove(var Message: TWMMouse);
//var
//  p : TPoint;
//  cy1, cy2 : integer;
begin
  p := CursorToPoint(Message.XPos, Message.YPos);
  cy1 := CaptionHeight(False) + SysBorderHeight(False);
  cy2 := cy1 + MenuHeight;
  if Between(p.Y, cy1, cy2)
    then inc(Message.YPos, SkinMenuOffset(Self).Y) {???}
    else begin
{    cy1 := CaptionHeight(False) + SysBorderHeight(False);
    cy2 := cy1 + MenuHeight;
    if Between(p.Y, cy1, cy2)
      then dec(Message.YPos, 12);}
  end;
  OldWndProc(TMessage(Message));
end;
*)
{
procedure TsSkinProvider.AC_WMDrawItem(var Message: TWMDrawItem);
begin
  if (Form.Menu <> nil) and (Message.DrawItemStruct^.CtlType = ODT_MENU) and (Message.DrawItemStruct^.hwndItem = Form.Menu.Handle) then begin
//    OffsetRect(Message.DrawItemStruct^.rcItem, SkinMenuOffset(Self).X, SkinMenuOffset(Self).Y);
    OldWndProc(TMessage(Message)) 
  end
  else OldWndProc(TMessage(Message))
end;
}
procedure TsSkinProvider.AC_WMInitMenuPopup(var Message: TWMInitMenuPopup);
begin
  if Message.SystemMenu then begin
    EnableMenuItem(Message.MenuPopup, SC_SIZE, MF_BYCOMMAND or MF_GRAYED);
  end
  else acCanHookMenu := True; // Menu skinning is supported ???
  OldWndProc(TMessage(Message));
end;

procedure TsSkinProvider.InitExBorders(const Active : boolean);
begin
  if Active and HaveBorder(Self) and DrawNonClientArea and (Form.Parent = nil) and (Form.FormStyle <> fsMDIChild) and FAllowExtBorders then begin
    if BorderForm = nil then begin
      BorderForm := TacBorderForm.Create(Self);
      BorderForm.SkinData := FCommonData;
      FCommonData.BGChanged := True;
      if FCommonData.FCacheBmp <> nil then FCommonData.FCacheBmp.PixelFormat := pf32bit;
      BorderForm.UpdateExBordersPos;
    end;
  end
  else begin
    if BorderForm <> nil then FreeAndNil(BorderForm);
    if FCommonData.FCacheBmp <> nil then FCommonData.FCacheBmp.PixelFormat := pf24bit;
  end;
end;

procedure TsSkinProvider.AC_WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
var
  R : TRect;
  sbwf, yOffs, addY : integer;
begin
  if FDrawNonClientArea and (Form.FormStyle <> fsMDIChild) and (Form.Parent = nil) then begin
    R := acWorkRect(Form);
    sbwf := SysBorderWidth(Form.Handle, BorderForm, False);
    if ((GetWindowLong(Form.Handle, GWL_STYLE) and WS_CAPTION = WS_CAPTION)) then begin
      if (CaptionHeight(True) > CaptionHeight(False) + sbwf)
        then yOffs := CaptionHeight(True) - CaptionHeight(False) - sbwf
        else yOffs := sbwf;
    end
    else yOffs := 0; // v6.43 

    if (FCommonData.SkinManager.SkinData.ExTitleHeight <> FCommonData.SkinManager.SkinData.ExMaxHeight)
      then addY := (FCommonData.SkinManager.SkinData.ExTitleHeight - FCommonData.SkinManager.SkinData.ExMaxHeight + FCommonData.SkinManager.SkinData.ExCenterOffs)
      else addY := 0;

    Message.MinMaxInfo^.ptMaxPosition.Y := yOffs - sbwf - addY;

    sbwf := sbwf * 2;
    Message.MinMaxInfo^.ptMaxSize.Y := HeightOf(R) - yOffs + sbwf + addY;
    Message.MinMaxInfo^.ptMaxSize.X := WidthOf(R) + sbwf;
    Message.Result := 0;
  end;
  OldWndProc(TMessage(Message));
end;

function TsSkinProvider.ShadowSize: TRect;
begin
  if BorderForm <> nil then Result := SkinData.SkinManager.FormShadowSize else Result := Rect(0, 0, 0, 0);
end;

procedure TsSkinProvider.KillAnimations;
var
  i : integer;
begin
  if ButtonMin.Timer <> nil then ButtonMin.Timer.Free;
  if ButtonMax.Timer <> nil then ButtonMax.Timer.Free;
  if ButtonClose.Timer <> nil then ButtonClose.Timer.Free;
  if ButtonHelp.Timer <> nil then ButtonHelp.Timer.Free;

  for i := 0 to TitleButtons.Count - 1 do begin
    if TitleButtons[i].BtnData.Timer <> nil then TitleButtons[i].BtnData.Timer.Free;
  end;
end;

procedure TsSkinProvider.SetAllowExtBorders(const Value: boolean);
begin
  if FAllowExtBorders <> Value then begin
    FAllowExtBorders := Value;
    if not (csLoading in ComponentState) then begin
      InitExBorders(True);
      FCommonData.BGChanged := True;
      RedrawWindow(Form.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE);
    end;
  end;
end;

procedure TsSkinProvider.AssignTo(Dest: TPersistent);
begin
  inherited;
end;

{ TsSystemMenu }

procedure TsSystemMenu.CloseClick(Sender: TObject);
begin
  Sendmessage(FForm.Handle, WM_SYSCOMMAND, SC_CLOSE, 0);
end;

constructor TsSystemMenu.Create(AOwner: TComponent);
begin
  FOwner := TsSkinProvider(AOwner);
  FForm := FOwner.Form;
  inherited Create(AOwner);
  Name := 'SysMenu';
  Generate
end;

function TsSystemMenu.EnabledMax: boolean;
begin
  Result := ((TForm(FForm).FormStyle = fsMDIChild) or ((FForm.WindowState <> wsMaximized) and (FForm.BorderStyle in [bsSingle, bsSizeable]))) and
      (biMaximize in FOwner.Form.BorderIcons);
end;

function TsSystemMenu.EnabledMin: boolean;
begin
  Result := (biMinimize in FOwner.Form.BorderIcons) and (FForm.WindowState <> wsMinimized);
end;

function TsSystemMenu.EnabledMove: boolean;
begin
  Result := (FForm.WindowState <> wsMaximized);
end;

function TsSystemMenu.EnabledRestore: boolean;
begin
  Result := ((biMaximize in FOwner.Form.BorderIcons) and (FForm.WindowState <> wsNormal)) or
    (FForm.WindowState = wsMinimized);
end;

function TsSystemMenu.EnabledSize: boolean;
begin
  Result := (FForm.BorderStyle <> bsSingle) and not IsIconic(FForm.Handle);
end;

procedure TsSystemMenu.ExtClick(Sender: TObject);
begin
  PostMessage(FForm.Handle, WM_SYSCOMMAND, TComponent(Sender).Tag, 0);
end;

procedure TsSystemMenu.Generate;
var
  Menu : HMENU;
  i, j : integer;
  s : acString;
  sCut : string;
  TmpItem : TMenuItem;
  function CreateSystemItem(const Caption : acString; const Name : string; EventProc : TNotifyEvent) : TMenuItem; begin
{$IFDEF TNTUNICODE}
    Result := TTntMenuItem.Create(Self);
{$ELSE}
    Result := TMenuItem.Create(Self);
{$ENDIF}
    Result.Caption := Caption;
    Result.OnClick := EventProc;
    Result.Name := Name;
  end;
  function GetItemText(ID : Cardinal; var Caption : acString; var ShortCut : String; uFlag : Cardinal) : boolean;
  var
    Text: array[0..MaxByte] of acChar;
{$IFDEF TNTUNICODE}
    ws : WideString;
{$ENDIF}
    P : integer;
  begin
{$IFDEF TNTUNICODE}
    Result := GetMenuStringW(Menu, ID, Text, MaxByte, uFlag) <> 0;
{$ELSE}
    Result := GetMenuString(Menu, ID, Text, MaxByte, uFlag) <> 0;
{$ENDIF}
    if Result then begin
      P := Pos(#9, Text);
      if P = 0 then ShortCut := '' else begin
        ShortCut := Copy(Text, P + 1, Length(Text) - P);
{$IFDEF TNTUNICODE}
        ws := Text;
        ws := Copy(ws, 1, P - 1);
        Caption := ws;
        Exit;
{$ELSE}
        StrLCopy(Text, Text, P - 1);
{$ENDIF}
      end;
      Caption := Text;
    end;
  end;
begin
  Items.Clear;
  ExtItemsCount := 0;
  Menu := GetSystemMenu(FForm.Handle, False);

  if Menu = 0 then Exit;  

  if not GetItemText(SC_RESTORE, s, sCut, MF_BYCOMMAND) then s := LoadStr(s_RestoreStr);
  ItemRestore := CreateSystemItem(s, 'acIR', RestoreClick);
  ItemRestore.Tag := SC_RESTORE;
  Self.Items.Add(ItemRestore);

  if not GetItemText(SC_MOVE, s, sCut, MF_BYCOMMAND) then s := LoadStr(s_MoveStr);
  ItemMove := CreateSystemItem(s, 'acIM', MoveClick);
  Self.Items.Add(ItemMove);
  ItemMove.Tag := SC_MOVE;

  if not GetItemText(SC_SIZE, s, sCut, MF_BYCOMMAND) then s := LoadStr(s_SizeStr);
  ItemSize := CreateSystemItem(s, 'acIS', SizeClick);
  Self.Items.Add(ItemSize);
  ItemSize.Tag := SC_SIZE;

  if not GetItemText(SC_MINIMIZE, s, sCut, MF_BYCOMMAND) then s := LoadStr(s_MinimizeStr);
  ItemMinimize := CreateSystemItem(s, 'acIN', MinClick);
  Self.Items.Add(ItemMinimize);
  ItemMinimize.Tag := SC_MINIMIZE;

  if not GetItemText(SC_MAXIMIZE, s, sCut, MF_BYCOMMAND) then s := LoadStr(s_MaximizeStr);
  ItemMaximize := CreateSystemItem(s, 'acIX', MaxClick);
  Self.Items.Add(ItemMaximize);
  ItemMaximize.Tag := SC_MAXIMIZE;

  Self.Items.InsertNewLineAfter(ItemMaximize);

  i := GetMenuItemCount(Menu);
  TmpItem := nil;
  for i := 0 to i - 1 do begin
    j := GetMenuItemID(Menu, i);
    if (j < $F000) and GetItemText(i, s, sCut, MF_BYPOSITION) then begin // If some external menuitems are exists
{$IFDEF TNTUNICODE}
      TmpItem := TTntMenuItem.Create(Self);
{$ELSE}
      TmpItem := TMenuItem.Create(Self);
{$ENDIF}
      TmpItem.Caption := s;
      TmpItem.Tag := j;
      if sCut <> '' then TmpItem.ShortCut := TextToShortCut(sCut);
      TmpItem.OnClick := ExtClick;
      Self.Items.Add(TmpItem);
      inc(ExtItemsCount);
    end;
  end;
  if ExtItemsCount > 0 then Self.Items.InsertNewLineAfter(TmpItem);

  if not GetItemText(SC_CLOSE, s, sCut, MF_BYCOMMAND) then s := LoadStr(s_CloseStr);
  ItemClose := CreateSystemItem(s, 'acIC', CloseClick);
  if sCut <> '' then ItemClose.ShortCut := TextToShortCut(sCut);
  Self.Items.Add(ItemClose);
  ItemClose.Tag := SC_CLOSE;
end;

procedure TsSystemMenu.MakeSkinItems;
var
  sl : TacStringList;
  i : integer;
  SkinItem, TempItem : TMenuItem;
begin
  if Assigned(FOwner.SkinData.SkinManager) then begin
    sl := TacStringList.Create;
    FOwner.SkinData.SkinManager.GetSkinNames(sl);

    if sl.Count > 0 then begin
{$IFDEF TNTUNICODE}
      SkinItem := TTntMenuItem.Create(Self);
{$ELSE}
      SkinItem := TMenuItem.Create(Self);
{$ENDIF}
      SkinItem.Caption := LoadStr(s_AvailSkins);
      SkinItem.Name := s_SkinSelectItemName;
      Self.Items.Insert(0, SkinItem);
      Self.Items.InsertNewLineAfter(SkinItem);
      for i := 0 to sl.Count - 1 do begin
{$IFDEF TNTUNICODE}
        TempItem := TTntMenuItem.Create(Self);
{$ELSE}
        TempItem := TMenuItem.Create(Self);
{$ENDIF}
        TempItem.Caption := sl[i];
        TempItem.OnClick := SkinSelect;
        TempItem.Name := s_SkinSelectItemName + IntToStr(i);
        TempItem.RadioItem := True;
        if TempItem.Caption = FOwner.SkinData.SkinManager.SkinName then TempItem.Checked := True;
        if (i <> 0) and (i mod 20 = 0) then TempItem.Break := mbBreak;
        SkinItem.Add(TempItem);
      end;
    end;
    FreeAndNil(sl);
  end;
end;

procedure TsSystemMenu.MaxClick(Sender: TObject);
begin
  Sendmessage(FForm.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  UpdateItems;
end;

procedure TsSystemMenu.MinClick(Sender: TObject);
begin
  if (Application.MainForm = FForm) then begin
    Application.Minimize;
    FOwner.SystemMenu.UpdateItems;
  end
  else begin
    SendMessage(FOwner.Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  end;
end;

procedure TsSystemMenu.MoveClick(Sender: TObject);
begin
  Sendmessage(FForm.Handle, WM_SYSCOMMAND, SC_MOVE, 0);
end;

procedure TsSystemMenu.RestoreClick(Sender: TObject);
begin
  Sendmessage(FForm.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
  UpdateItems;
  if (FOwner.Form.FormStyle = fsMDIChild) then begin
  end;
end;

procedure TsSystemMenu.SizeClick(Sender: TObject);
begin
  Sendmessage(FForm.Handle, WM_SYSCOMMAND, SC_SIZE, 0);
end;

procedure TsSystemMenu.SkinSelect(Sender: TObject);
var
  sSkinName, sInternalSkin : String;
  iIndex : Integer;
begin
  if Assigned(FOwner.SkinData.SkinManager) then begin
    sSkinName := DelChars(TMenuItem(Sender).Caption, '&');
    sInternalSkin := LoadStr(s_InternalSkin);
    iIndex := Pos(sInternalSkin, sSkinName);
    if iIndex > 0 then begin
      sSkinName := Copy(sSkinName, 1, iIndex - 1 + Length(sInternalSkin));
    end;
    FOwner.SkinData.SkinManager.SkinName := sSkinName;
//    FOwner.SkinData.SkinManager.SkinName := DelChars(TMenuItem(Sender).Caption, '&'); v6.31
  end;
end;

procedure TsSystemMenu.UpdateGlyphs;
begin
// 
end;

procedure TsSystemMenu.UpdateItems(Full : boolean = False);
begin
  if Full then begin
    Generate;
  end;
  if Assigned(Self) and Assigned(FForm) then begin
    if ItemRestore <> nil then begin
      ItemRestore.Visible := VisibleRestore;
      ItemRestore.Enabled := EnabledRestore;
    end;
    if ItemMove <> nil then begin
      ItemMove.Visible := True;
      ItemMove.Enabled := EnabledMove;
    end;
    if ItemSize <> nil then begin
      ItemSize.Visible := VisibleSize;
      ItemSize.Enabled := EnabledSize;
    end;
    if ItemMinimize <> nil then begin
      ItemMinimize.Visible := VisibleMin;
      ItemMinimize.Enabled := EnabledMin;
    end;
    if ItemMaximize <> nil then begin
      ItemMaximize.Visible := VisibleMax;
      ItemMaximize.Enabled := EnabledMax;
    end;
    if ItemClose <> nil then begin
      ItemClose.Visible := VisibleClose;
      ItemClose.Enabled := True;
    end;
  end;
end;

function TsSystemMenu.VisibleClose: boolean;
begin
  Result := FOwner.HaveSysMenu;// and (GetSystemMenu(FForm.Handle, False) <> 0);
{  Result := (biSystemMenu in FOwner.Form.BorderIcons);
  Result := GetWindowLong(FOwner.Form.Handle, GWL_STYLE) and WS_SYSMENU = WS_SYSMENU;}
end;

function TsSystemMenu.VisibleMax: boolean;
begin
  Result := False;
  if (Self = nil) or not VisibleClose then Exit;

  Result := IsIconic(Self.FForm.Handle) or (TForm(FForm).FormStyle = fsMDIChild) or
    ((FForm.BorderStyle <> bsDialog) and
    ((FForm.BorderStyle <> bsSingle) or (biMaximize in FOwner.Form.BorderIcons)) and
    (FForm.BorderStyle <> bsNone) and
    (FForm.BorderStyle <> bsSizeToolWin) and
    (FForm.BorderStyle <> bsToolWindow) and VisibleClose) and (biMaximize in FOwner.Form.BorderIcons);
end;

function TsSystemMenu.VisibleMin: boolean;
begin
  Result := False;
  if (Self = nil) or not VisibleClose then Exit;
  if IsIconic(FForm.Handle) or (TForm(FForm).FormStyle = fsMDIChild) then begin
    Result := True
  end
  else begin
    Result :=
      (FForm.BorderStyle <> bsDialog) and
      (FForm.BorderStyle <> bsNone) and
      ((FForm.BorderStyle <> bsSingle) or (biMinimize in FOwner.Form.BorderIcons)) and
      (FForm.BorderStyle <> bsSizeToolWin) and
      (FForm.BorderStyle <> bsToolWindow) and (biMinimize in FOwner.Form.BorderIcons) and VisibleClose;
  end;
end;

function TsSystemMenu.VisibleRestore: boolean;
begin
  Result := False;
  if (Self = nil) or not VisibleClose then Exit;
  Result := (TForm(FForm).FormStyle = fsMDIChild) or
    ((FForm.BorderStyle <> bsDialog) and
    (FForm.BorderStyle <> bsNone) and
    (FForm.BorderStyle <> bsSizeToolWin) and
    (FForm.BorderStyle <> bsToolWindow)) and VisibleClose;
end;

function TsSystemMenu.VisibleSize: boolean;
begin
  Result := False;
  if Self = nil then Exit;
  Result := (TForm(FForm).FormStyle = fsMDIChild) or
    ((FForm.BorderStyle <> bsDialog) and
    (FForm.BorderStyle <> bsNone) and
    (FForm.BorderStyle <> bsToolWindow));
end;

{ TsTitleIcon }

constructor TsTitleIcon.Create;
begin
  FGlyph := TBitmap.Create;
  FHeight := 0;
  FWidth := 0;
end;

destructor TsTitleIcon.Destroy;
begin
  FreeAndNil(FGlyph);
  inherited Destroy; 
end;

procedure TsTitleIcon.SetGlyph(const Value: TBitmap);
begin
  FGlyph.Assign(Value);
end;

procedure TsTitleIcon.SetHeight(const Value: integer);
begin
  FHeight := Value;
end;

procedure TsTitleIcon.SetWidth(const Value: integer);
begin
  FWidth := Value;
end;

{ TsTitleButtons }

constructor TsTitleButtons.Create(AOwner: TsSkinProvider);
begin
  inherited Create(TsTitleButton);
  FOwner := AOwner;
end;

destructor TsTitleButtons.Destroy;
begin
  FOwner := nil;
  inherited Destroy;
end;

function TsTitleButtons.GetItem(Index: Integer): TsTitleButton;
begin
  Result := TsTitleButton(inherited GetItem(Index))
end;

function TsTitleButtons.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

procedure TsTitleButtons.SetItem(Index: Integer; Value: TsTitleButton);
begin
  inherited SetItem(Index, Value);
end;

procedure TsTitleButtons.Update(Item: TCollectionItem);
begin
  inherited;
end;

{ TsTitleButton }

procedure TsTitleButton.AssignTo(Dest: TPersistent);
begin
  if Dest = nil then inherited else begin
    TsTitleButton(Dest).Enabled := Enabled;
    TsTitleButton(Dest).Glyph := Glyph;
    TsTitleButton(Dest).Hint := Hint;
    TsTitleButton(Dest).Name := Name;
    TsTitleButton(Dest).UseSkinData := UseSkinData;
    TsTitleButton(Dest).OnMouseDown := OnMouseDown;
    TsTitleButton(Dest).OnMouseUp := OnMouseUp;
  end;
end;

constructor TsTitleButton.Create(Collection: TCollection);
begin
  FGlyph := TBitmap.Create;
  FUseSkinData := True;
  FEnabled := True;
  HintWnd := nil;
  inherited Create(Collection);
  if FName = '' then FName := ClassName;
end;

destructor TsTitleButton.Destroy;
begin
  if BtnData.Timer <> nil then BtnData.Timer.Free;
  FreeAndNil(FGlyph);
  if HintWnd <> nil then FreeAndNil(HintWnd);
  inherited Destroy;
end;

function TsTitleButton.GetDisplayName: string;
begin
  Result := Name;
end;

procedure TsTitleButton.MouseDown(BtnIndex : integer; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
end;

procedure TsTitleButton.MouseUp(BtnIndex : integer; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y);
end;

procedure TsTitleButton.SetGlyph(const Value: TBitmap);
begin
  FGlyph.Assign(Value);
end;

procedure TsTitleButton.SetName(const Value: string);
begin
  if FName <> Value then FName := Value;
end;

{ TacCtrlAdapter }

procedure TacCtrlAdapter.AddNewItem(const Ctrl: TWinControl);
begin
  AddNewItem(Ctrl, DefaultSection);
end;

procedure TacCtrlAdapter.AddNewItem(const Ctrl: TWinControl; const SkinSection: string);
var
  i, Index, l : integer;
  Found : boolean;
  CanAdd : boolean;
  s : string;
begin
  if (Ctrl = nil) or (Ctrl.Tag = ExceptTag) then Exit;
  if (Ctrl.Parent = nil) or GetBoolMsg(Ctrl, AC_CTRLHANDLED) then Exit;
  CanAdd := True;
  s := SkinSection;
  if Assigned(Provider.OnSkinItem) then Provider.FOnSkinItem(Ctrl, CanAdd, s);
  if not CanAdd then Exit;

  if Ctrl is TFrame then begin
{$IFNDEF ALITE}
    with TsFrameAdapter.Create(Ctrl) do SkinData.SkinSection := s_GroupBox;
{$ENDIF}
    Exit;
  end;

  Index := -1;
  l := Length(Items);
  Found := False;
  for i := 0 to l - 1 do if (Items[i].WinCtrl = Ctrl) then begin // If added in list already, then go to Exit
    Index := i;
    Found := True;
    Break;
  end;
  if Index = -1 then begin
    SetLength(Items, l + 1);
    l := Length(Items);
    Index := l - 1;
    Items[Index] := TacAdapterItem.Create;
    Items[Index].Adapter := Self;
    Items[Index].WinCtrl := Ctrl;
  end;
  Items[Index].SkinData.SkinSection := s;
  if Found and Assigned(Items[Index].ScrollWnd) and Items[Index].ScrollWnd.Destroyed then begin
    FreeAndNil(Items[Index].ScrollWnd);
    if (Items[Index].WinCtrl.Parent <> nil) then Items[Index].DoHook(Ctrl);
  end
  else if not Found then begin
    if (Items[Index].WinCtrl.Parent <> nil) then Items[Index].DoHook(Ctrl);
    if Items[Index].ScrollWnd = nil then begin
      FreeAndNil(Items[Index]);
      SetLength(Items, Index);
    end;
  end;
end;

procedure TacCtrlAdapter.AddNewItem(const Ctrl: TSpeedButton);
var
  i, Index, l : integer;
  Found : boolean;
  CanAdd : boolean;
  s : string;
begin
  if (Ctrl = nil) or (Ctrl.Tag = ExceptTag) then Exit;
  if (Ctrl.Parent = nil) or (SendAMessage(Ctrl, AC_CTRLHANDLED) = 1) then Exit;
  CanAdd := True;
  s := s_SpeedButton;
  if Assigned(Provider.OnSkinItem) then Provider.FOnSkinItem(Ctrl, CanAdd, s);
  if not CanAdd then Exit;

  Index := -1;
  l := Length(GraphItems);
  Found := False;

  for i := 0 to l - 1 do if (GraphItems[i].Ctrl = Ctrl) then begin // If added in list already, then go to Exit
    Index := i;
    Found := True;
    Break;
  end;
  if Index = -1 then begin
    SetLength(GraphItems, l + 1);
    l := Length(GraphItems);
    Index := l - 1;
    GraphItems[Index] := TacGraphItem.Create;
    GraphItems[Index].Adapter := Self;
    GraphItems[Index].Ctrl := Ctrl;
  end;
  if Ctrl.Flat then GraphItems[Index].SkinData.SkinSection := s_SpeedButton_Small else GraphItems[Index].SkinData.SkinSection := s_SpeedButton;
  if Found and Assigned(GraphItems[Index].Handler) and GraphItems[Index].Handler.Destroyed then begin
    FreeAndNil(GraphItems[Index].Handler);
    GraphItems[Index].DoHook(Ctrl);
  end
  else if not Found then begin
    if (GraphItems[Index].Ctrl.Parent <> nil) then GraphItems[Index].DoHook(Ctrl);
    if GraphItems[Index].Handler = nil then begin
      FreeAndNil(GraphItems[Index]);
      SetLength(GraphItems, Index);
    end;
  end;
end;

procedure TacCtrlAdapter.AddAllItems(OwnerCtrl : TWinControl = nil);// CheckHandle : boolean = True);
var
  i : integer;
  sSection : string;
  Owner : TWinControl;
begin
{$IFDEF CHECKXP}
{  Provider.StdBgIsUsed := False;
  for i := 0 to Provider.Form.ControlCount - 1 do if (Provider.Form.Controls[i] is TWinControl) and TacAccessWinCtrl(Provider.Form.Controls[i]).ParentBackground then begin
    Provider.StdBgIsUsed := True;
    Break
  end;}
{$ENDIF}

  if bFlag or not (srThirdParty in Provider.SkinData.SkinManager.SkinningRules) then Exit;
  bFlag := True;
  if OwnerCtrl = nil then Owner := Provider.Form else Owner := OwnerCtrl;
  if Owner = nil then Exit;
  CleanItems;
  for i := 0 to Owner.ComponentCount - 1 do begin
    if IsControlSupported(Owner.Components[i]) then begin
      if (Owner.Components[i] is TWinControl) then begin
        sSection := s_Edit;
        AddNewItem(TWinControl(Owner.Components[i]), sSection);
      end
      else if (Owner.Components[i] is TCustomLabel) and not (Owner.Components[i] is TsCustomLabel) and (Owner.Components[i].Tag <> -ExceptTag) then begin
        TLabel(Owner.Components[i]).Transparent := True;
        TLabel(Owner.Components[i]).Font.Color := DefaultManager.GetGlobalFontColor;
      end;
    end;
    if (Owner.Components[i] is TWinControl) then begin
      if TWinControl(Owner.Components[i]).HandleAllocated then begin
        if (TWinControl(Owner.Components[i]).Parent <> nil) then begin
          bFlag := False;
          AddAllItems(TWinControl(Owner.Components[i])); // Recursion
        end;
      end;
    end;
  end;
  for i := 0 to Owner.ControlCount - 1 do begin
    if IsControlSupported(Owner.Controls[i]) then begin
      if (Owner.Controls[i] is TWinControl) then begin
        sSection := s_Edit;
        AddNewItem(TWinControl(Owner.Controls[i]), sSection);
      end
      else if (Owner.Controls[i] is TLabel) then begin
        TLabel(Owner.Controls[i]).Transparent := True;
        TLabel(Owner.Controls[i]).Font.Color := DefaultManager.GetGlobalFontColor;
      end
      else if (Owner.Controls[i] is TSpeedButton) then begin
        AddNewItem(TSpeedButton(Owner.Controls[i]));
      end
    end;
    if (Owner.Controls[i] is TWinControl) then begin
      if TWinControl(Owner.Controls[i]).HandleAllocated then begin
        if (TWinControl(Owner.Controls[i]).Parent <> nil) then begin
          bFlag := False;
          AddAllItems(TWinControl(Owner.Controls[i])); // Recursion
        end
      end;
    end;
  end;
  bFlag := False;
end;

function TacCtrlAdapter.Count: integer;
begin
  Result := Length(Items);
end;

destructor TacCtrlAdapter.Destroy;
begin
  CleanItems;
  RemoveAllItems;
  inherited Destroy;
end;

function TacCtrlAdapter.GetCommonData(Index: integer): TsCommonData;
begin
  Result := nil;
end;

function TacCtrlAdapter.GetItem(Index: integer) : TacAdapterItem;
begin
  if (Index > -1) and (Index < Count) then Result := Items[Index] else Result := nil;
end;

function TacCtrlAdapter.IndexOf(Ctrl : TWinControl): integer;
var
  i : integer;
begin
  Result := -1;
  for i := 0 to Length(Items) - 1 do if Items[i].WinCtrl = Ctrl then begin
    Result := i;
    Exit;
  end;
end;

procedure TacCtrlAdapter.RemoveItem(Index: integer);
var
  l : integer;
begin
  l := Count;
  if (Index < l) and (l > 0) then begin
    if Items[Index] <> nil then FreeAndNil(Items[Index]);
    Items[Index] := Items[l - 1];
    SetLength(Items, l - 1);
  end;
end;

function TacCtrlAdapter.IsControlSupported(Control: TComponent): boolean;
var
  i, j : integer;
  CanAdd : boolean;
  s : string;
begin
  Result := False;
  if (Control.Tag = ExceptTag) or ((Control is TWinControl) and not CtrlIsReadyForHook(TWinControl(Control))) then Exit;

  if (Control is TWinControl) and GetBoolMsg(TWinControl(Control), AC_CTRLHANDLED) then Exit else begin
    if not (Control is TGraphicControl) then begin
      if Control is TFrame then begin
        CanAdd := True;
        s := '';
        if Assigned(Provider.OnSkinItem) then Provider.FOnSkinItem(Control, CanAdd, s);
        Result := CanAdd;
        Exit;
      end
      else for j := 0 to Length(Provider.SkinData.SkinManager.ThirdLists) - 1 do begin
        for i := 0 to Provider.SkinData.SkinManager.ThirdLists[j].Count - 1 do if Provider.SkinData.SkinManager.ThirdLists[j][i] = Control.ClassName then begin
          Result := True;
          Exit;
        end;
      end;
    end
    else if (Control is TCustomLabel) then begin
      CanAdd := True;
      s := '';
      if Assigned(Provider.OnSkinItem) then Provider.FOnSkinItem(Control, CanAdd, s);
      Result := CanAdd;
      Exit;
    end
    else if (Control is TSpeedButton) then begin
      // Search if control exists in the List of supported
      for j := 0 to Length(Provider.SkinData.SkinManager.ThirdLists) - 1 do begin
        for i := 0 to Provider.SkinData.SkinManager.ThirdLists[j].Count - 1 do begin
          s := Provider.SkinData.SkinManager.ThirdLists[j][i];
          if s = Control.ClassName then begin
            CanAdd := True;
            s := '';
            if Assigned(Provider.OnSkinItem) then Provider.FOnSkinItem(Control, CanAdd, s);
            Result := CanAdd;
            Exit;
          end;
        end;
      end;
    end
  end;
end;

procedure TacCtrlAdapter.RemoveAllItems;
var
  l : integer;
begin
  if bRemoving then Exit;
  bRemoving := True;
  while Length(Items) > 0 do begin
    l := Length(Items);
    FreeAndNil(Items[l - 1]);
    SetLength(Items, l - 1);
  end;
  while Length(GraphItems) > 0 do begin
    l := Length(GraphItems);
    FreeAndNil(GraphItems[l - 1]);
    SetLength(GraphItems, l - 1);
  end;
  bRemoving := False;
end;

procedure TacCtrlAdapter.WndProc(var Message: TMessage);
var
  i, l : integer;
begin
  l := Length(Items) - 1;
  for i := 0 to l do if (Items[i].ScrollWnd <> nil) and not Items[i].ScrollWnd.Destroyed then begin
    if (Items[i].WinCtrl.Parent <> nil) then SendMessage(Items[i].WinCtrl.Handle, Message.Msg, Message.WParam, Message.LParam)
  end;
{ // Not used for TSpeedButton because we not know control exists still or not (we haven't a message about control destroying) // }
end;

procedure TacCtrlAdapter.AfterConstruction;
begin
  inherited;
end;

constructor TacCtrlAdapter.Create(AProvider: TsSkinProvider);
begin
  Provider := AProvider;
  Items := nil;
end;

procedure TacCtrlAdapter.CleanItems;
var
  i, j : integer;
begin
  i := 0;
  while i < Length(Items) do begin
    if (Items[i] = nil) or (Items[i].ScrollWnd = nil) or Items[i].ScrollWnd.Destroyed then begin
      if Items[i] <> nil then FreeAndNil(Items[i]);
      for j := i to Length(Items) - 2 do begin
        Items[j] := Items[j + 1];
        Items[j + 1] := nil;
      end;
      SetLength(Items, Length(Items) - 1);
    end;
    inc(i)
  end;

  i := 0;
  while i < Length(GraphItems) do begin
    if (GraphItems[i] = nil) or (GraphItems[i].Handler = nil) or GraphItems[i].Handler.Destroyed then begin
      if GraphItems[i] <> nil then FreeAndNil(GraphItems[i]);
      for j := i to Length(GraphItems) - 2 do begin
        GraphItems[j] := GraphItems[j + 1];
        GraphItems[j + 1] := nil;
      end;
      SetLength(GraphItems, Length(GraphItems) - 1);
    end;
    inc(i)
  end;
end;

{ TacAdapterItem }
constructor TacAdapterItem.Create;
begin
//  inherited Create;
  OldFontColor := -1;
  SkinData := TsCommonData.Create(Self, True);
  SkinData.COC := COC_TsAdapter;
  ScrollWnd := nil;
end;

destructor TacAdapterItem.Destroy;
begin
  if (ScrollWnd <> nil) then FreeAndNil(ScrollWnd);
  FreeAndNil(SkinData);
  inherited Destroy;
end;

procedure TacAdapterItem.DoHook(Control: TWinControl);
var
  i, j : integer;
begin
  if (Control.Tag = ExceptTag) or not CtrlIsReadyForHook(Control) then Exit;
  if (Control.Parent <> nil) then if GetBoolMsg(Control, AC_CTRLHANDLED) then Exit;

  Self.WinCtrl := Control;
  SkinData.FOwnerControl := Control;
  SkinData.FOwnerObject := TObject(Control);
  if (Control.Parent <> nil) then begin
    for j := 0 to Length(SkinData.SkinManager.ThirdLists) - 1 do begin
      for i := 0 to SkinData.SkinManager.ThirdLists[j].Count - 1 do if SkinData.SkinManager.ThirdLists[j][i] = Control.ClassName then begin
        case j of
          ord(tpEdit) : begin
            ScrollWnd := TacEditWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpButton) : begin
            SkinData.SkinSection := s_Button;
            ScrollWnd := TacBtnWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Button);
            Exit;
          end;
          ord(tpBitBtn) : begin
            SkinData.SkinSection := s_Button;
            ScrollWnd := TacBitBtnWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Button);
            Exit;
          end;
          ord(tpCheckBox) : begin
            SkinData.SkinSection := s_CheckBox;
            ScrollWnd := TacCheckBoxWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, '');
            Exit;
          end;
          ord(tpComboBox) : begin
            ScrollWnd := TacComboBoxWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpGrid) : begin
            ScrollWnd := TacGridWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpGroupBox) : begin
            SkinData.SkinSection := s_GroupBox;
            ScrollWnd := TacGroupBoxWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, '');
            Exit;
          end;
          ord(tpListView) : begin
            ScrollWnd := TacListViewWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpPanel) : begin
            SkinData.SkinSection := s_Panel;
            ScrollWnd := TacPanelWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Panel);
            Exit;
          end;
          ord(tpTreeView) : begin
            ScrollWnd := TacTreeViewWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpwwEdit) : begin
            ScrollWnd := TacWWComboBoxWnd.Create(Control, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpGridEh) : begin
            ScrollWnd := TacGridEhWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpVirtualTree) : begin
            ScrollWnd := TacVirtualTreeViewWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_Edit);
            Exit;
          end;
          ord(tpPageControl) : begin
            SkinData.SkinSection := s_PageControl;
            ScrollWnd := TacPageControlWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_PageControl);
            Exit;
          end;
          ord(tpTabControl) : begin
            SkinData.SkinSection := s_PageControl;
            ScrollWnd := TacTabControlWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_PageControl);
            Exit;
          end;
          ord(tpToolBar) : begin
            SkinData.SkinSection := s_ToolBar;
            ScrollWnd := TacToolBarVCLWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_ToolBar);
            Exit;
          end;
          ord(tpStatusBar) : begin
            SkinData.SkinSection := s_StatusBar;
            ScrollWnd := TacStatusBarWnd.Create(Control.Handle, SkinData, SkinData.SkinManager, s_StatusBar);
            Exit;
          end;
        end;
      end;
    end;
  end;
end;

{ TacBorderForm }

procedure TacBorderForm.BorderProc(var Message: TMessage);
var
  Rgn, NewRgn : hrgn;
  p : TPoint;
  Wnd : hwnd;
begin
{$IFDEF LOGGED}
//  AddToLog(Message);
{$ENDIF}
  case Message.Msg of
    WM_MOUSEMOVE..WM_MBUTTONDBLCLK : if MouseAboveTheShadow(TWMMouse(Message)) then begin
      acInMouseMsg := True;
      NewRgn := CreateRectRgn(TWMMouse(Message).XPos, TWMMouse(Message).YPos, TWMMouse(Message).XPos + 1, TWMMouse(Message).YPos + 1);
      Rgn := MakeRgn;
      if Rgn = 0 then Rgn := CreateRectRgn(0, 0, AForm.Width, AForm.Height);
      CombineRgn(Rgn, Rgn, NewRgn, RGN_XOR);
      DeleteObject(NewRgn);

      if (FOwner is TsSkinProvider) then begin
        if not (fsModal in TAccessForm(TsSkinProvider(FOwner).Form).FormState {Report builder repaint bug} ) then SetWindowRgn(AForm.Handle, Rgn, False);
      end
      else SetWindowRgn(AForm.Handle, Rgn, False);

      Wnd := WindowFromPoint(Point(TWMMouse(Message).XPos + AForm.Left, TWMMouse(Message).YPos + AForm.Top));
      if (Wnd <> AForm.Handle) and (Wnd <> OwnerHandle) {and (GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_LAYERED = WS_EX_LAYERED) }
        then SendMessage(Wnd, Message.Msg, Message.wParam, Message.lParam);
      acInMouseMsg := False;
      Exit;
    end;
  end;
  case Message.Msg of
    WM_NCHITTEST : if MouseAboveTheShadow(TWMMouse(Message)) then begin
      Message.Result := HTTRANSPARENT;
      OldBorderProc(Message);
    end
    else Message.Result := integer(Windows.HTOBJECT);
    WM_NCLBUTTONDBLCLK : begin
      if (FOwner is TsSkinProvider) and (TsSkinProvider(FOwner).ResizeMode = rmBorder) and bInProcess then begin
        p := TsSkinProvider(FOwner).Form.ClientToScreen(Point(TWMMouse(Message).XPos, TWMMouse(Message).YPos));
        TsSkinProvider(FOwner).StopMove(p.x, p.y);
        ReleaseCapture;
        bInProcess := False;
      end;
      DoStartMove := False;
      TWMNCHitMessage(Message).HitTest := Ex_WMNCHitTest(TWMNCHitTest(Message));
      case TWMNCHitMessage(Message).HitTest of
        HTSYSMENU : begin SendMessage(OwnerHandle, WM_SYSCOMMAND, SC_CLOSE, 0); end;
        HTCAPTION : if (FOwner is TsSkinProvider) then with TsSkinProvider(FOwner) do begin
          if SystemMenu.VisibleClose and (SystemMenu.EnabledMax or SystemMenu.EnabledRestore) or not HaveBorder(TsSkinProvider(FOwner)) and IsIconic(Form.Handle) then begin
            if (Form.WindowState = wsMaximized) or IsIconic(Form.Handle)
              then SendMessage(Form.Handle, WM_SYSCOMMAND, SC_RESTORE, 0)
              else SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
            SystemMenu.UpdateItems;
          end;
          TWMNCHitMessage(Message).HitTest := 0;
        end;
      end;
    end;

    WM_SETCURSOR : if not Ex_WMSetCursor(TWMSetCursor(Message)) then OldBorderProc(Message);
    WM_MOUSEACTIVATE: begin
      Message.Result := MA_NOACTIVATE;
      SetForegroundWindow(OwnerHandle); // Solving a problem when form activated after taskbar
    end;
    WM_NCRBUTTONUP : if not MouseAboveTheShadow(TWMMouse(Message)) then begin
      TWMNCLButtonDown(Message).HitTest := HTTRANSPARENT;
      SendMessage(OwnerHandle, Message.Msg, Message.wParam, Message.lParam);
    end;
    WM_NCLBUTTONUP : if not MouseAboveTheShadow(TWMMouse(Message)) then begin
      TWMNCLButtonDown(Message).HitTest := HTTRANSPARENT;
      SendMessage(OwnerHandle, Message.Msg, Message.wParam, Message.lParam);
    end;
    WM_NCRBUTTONDOWN : if not MouseAboveTheShadow(TWMMouse(Message)) then begin
      TWMNCLButtonDown(Message).HitTest := Ex_WMNCHitTest(TWMNCHitTest(Message));
      SendMessage(OwnerHandle, Message.Msg, Message.wParam, Message.lParam);
    end;
    WM_NCLBUTTONDOWN : if not MouseAboveTheShadow(TWMMouse(Message)) then begin
      TWMNCLButtonDown(Message).HitTest := HTTRANSPARENT;
      SendMessage(OwnerHandle, Message.Msg, Message.wParam, Message.lParam);
    end;
    WM_WINDOWPOSCHANGED : begin
      KillAnimations;
      OldBorderProc(Message);
      if not acInMouseMsg then UpdateExBordersPos(False); // Update z-order ( BDS )
    end;
    WM_ERASEBKGND, WM_NCPAINT :;
    else OldBorderProc(Message);
  end;
end;

constructor TacBorderForm.Create(AOwner: TObject);
begin
  FOwner := AOwner;
  ExBorderShowing := False;
  acInMouseMsg := False;
  AForm := TForm.Create(nil);
  AForm.Tag := ExceptTag;
  AForm.Visible := False;
  AForm.BorderStyle := bsNone;

  SetWindowLong(AForm.Handle, GWL_EXSTYLE, GetWindowLong(AForm.Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE);
  OldBorderProc := AForm.WindowProc;
  AForm.WindowProc := BorderProc;
end;

destructor TacBorderForm.Destroy;
begin
  KillAnimations;
  if AForm <> nil then FreeAndNil(AForm);
  inherited;
end;

function TacBorderForm.Ex_WMNCHitTest(var Message: TWMNCHitTest): integer;
const
  BtnSpacing = 1;
  DefRESULT = HTTRANSPARENT;
var
  Handle : hwnd;
  SysMenu : TsCustomSysMenu;
  p : TPoint;
  i, SysBtnCount, BtnIndex : integer;
  GripVisible, HelpIconVisible : boolean;
  R, hrect, vrect : TRect;
  function GetBtnIndex : integer;
  var
    i, c : integer;
  begin
    Result := 0;
    c := 0; 
    if FOwner is TsSkinProvider then with FOwner as TsSkinProvider do begin
      if SystemMenu.VisibleClose and Assigned(SystemMenu) then begin
        inc(c);
        if PtInRect(ButtonClose.Rect, p) then Result := c else begin
          if SystemMenu.VisibleMax then begin
            inc(c);
            if PtInRect(ButtonMax.Rect, p) then begin
              Result := c;
              Exit;
            end;
          end;
          if SystemMenu.VisibleMin then begin
            inc(c);
            if PtInRect(ButtonMin.Rect, p)
              then Result := c
          end;
          if Result <> 0 then Exit;
          if (biHelp in Form.BorderIcons) then begin
            inc(c);
            if PtInRect(ButtonHelp.Rect, p) then begin
              Result := c;
              Exit;
            end;
          end;
        end;
      end;
      for i := 0 to TitleButtons.Count - 1 do begin
        inc(c);
        if PtInRect(TitleButtons[i].BtnData.Rect, p) then begin
          Result := c;
          Exit;
        end;
      end;
    end
    else with FOwner as TacDialogWnd do begin
      inc(c);
      if SystemMenu.VisibleClose then begin
        if PtInRect(ButtonClose.Rect, p)
          then Result := c
          else if TacDialogWnd(FOwner).VisibleHelp then begin
            inc(c);
            if PtInRect(ButtonHelp.Rect, p) then begin
              Result := c;
              Exit;
            end;
          end
      end;
    end
  end;
begin
  Result := DefRESULT;
  if not IsWindowEnabled(OwnerHandle) then Exit;
  p := Point(Message.XPos - AForm.Left, Message.YPos - AForm.Top);

  if FOwner is TsSkinProvider then begin
    SysMenu := TsSkinProvider(FOwner).SystemMenu;
    Handle := TsSkinProvider(FOwner).Form.Handle;
  end
  else begin
    SysMenu := TacDialogWnd(FOwner).SystemMenu;
    Handle := TacDialogWnd(FOwner).CtrlHandle;
  end;
  HelpIconVisible := GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_CONTEXTHELP = WS_EX_CONTEXTHELP;

  with FOwner do begin

    BtnIndex := GetBtnIndex;
    if (BtnIndex > 0) then begin
      SysBtnCount := 0;
      if SysMenu.VisibleClose then begin
        inc(SysBtnCount);
        if SysMenu.VisibleMax then inc(SysBtnCount);
        if SysMenu.VisibleMin or IsIconic(OwnerHandle) then inc(SysBtnCount);
        if HelpIconVisible then inc(SysBtnCount);
      end;
      if (BtnIndex <= SysBtnCount) then begin
        case BtnIndex of
          1 : if SysMenu.VisibleClose then Result := HTCLOSE;
          2 : begin
            if SysMenu.VisibleMax then begin
              if (SysMenu.EnabledMax or (SysMenu.EnabledRestore and not IsIconic(Handle))) then Result := HTMAXBUTTON else Result := HTCAPTION;
            end
            else if (SysMenu.VisibleMin) or IsIconic(Handle) then begin
              if SysMenu.EnabledMin then Result := HTMINBUTTON else Result := HTCAPTION;
            end
            else if HelpIconVisible then Result := HTHELP;
          end;
          3 : begin
            if (SysMenu.VisibleMin) or IsIconic(Handle) then begin
              if not IsIconic(Handle) then begin
                if SysMenu.EnabledMin then Result := HTMINBUTTON else Result := HTCAPTION;
              end
              else Result := HTMINBUTTON;
            end
            else if HelpIconVisible then Result := HTHELP;
          end;
          4 : if HelpIconVisible and SysMenu.VisibleMax then Result := HTHELP;
        end;
      end
      else if (FOwner is TsSkinProvider) and (BtnIndex <= TsSkinProvider(FOwner).TitleButtons.Count + SysBtnCount) then begin // UDF button
        BtnIndex := BtnIndex - SysBtnCount - 1;
        if TsSkinProvider(FOwner).TitleButtons.Items[BtnIndex].Enabled then Result := HTUDBTN + BtnIndex;
      end;
      if Result <> DefRESULT then begin
        SetHotHT(Result);
        Exit;
      end;
    end;

    if not IsZoomed(Handle) and (GetWindowLong(Handle, GWL_STYLE) and WS_SIZEBOX = WS_SIZEBOX) then begin
      if Between(p.Y, ShadowSize.Top, SysBorderWidth(Handle, Self, False) + ShadowSize.Top) then Result := HTTOP;
      if Between(p.Y, AForm.Height - SysBorderWidth(Handle, Self, False) - ShadowSize.Bottom, AForm.Height - ShadowSize.Bottom) then Result := HTBOTTOM;
      if Between(p.X, ShadowSize.Left, SysBorderWidth(Handle, Self, False) + ShadowSize.Left) then if Result = HTTOP then Result := HTTOPLEFT else if Result = HTBOTTOM then Result := HTBOTTOMLEFT else Result := HTLEFT;
      if Between(p.X, AForm.Width - SysBorderWidth(Handle, Self, False) - ShadowSize.Right, AForm.Width - ShadowSize.Right) then if Result = HTTOP then Result := HTTOPRIGHT else if Result = HTBOTTOM then Result := HTBOTTOMRIGHT else Result := HTRIGHT;
      if Result <> DefRESULT then begin
        SetHotHT(-1);
        Exit;
      end;
    end;
    SetHotHT(HTTRANSPARENT);

    if Between(p.Y, 0, CaptionHeight + SysBorderHeight(OwnerHandle, Self) + ShadowSize.Top) then begin
      if Between(p.Y, CaptionHeight(False) + SysBorderHeight(OwnerHandle, Self, False), CaptionHeight(False) + SysBorderHeight(OwnerHandle, Self, False) + MenuHeight) then begin
        Result := HTCAPTION;
        Exit;
      end;
      if PtInRect(IconRect, p) then Result := HTSYSMENU else Result := HTCAPTION;
    end
    else begin
      if p.Y <= CaptionHeight + SysBorderHeight(OwnerHandle, Self) + MenuHeight then begin
        // MDI child buttons
{        if MDIButtonsNeeded then begin // Is not used, may be removed later (see HTProcess)
          if PtInRect(MDICLose.Rect, p)
            then Result := HTCHILDCLOSE
            else if PtInRect(MDIMax.Rect, p)
              then Result := HTCHILDMAX
              else if PtInRect(MDIMin.Rect, p) then Result := HTCHILDMIN else Result := HTMENU;
          if Result <> DefRESULT then SetHotHT(Result) else SetHotHT(0);
        end
        else}
        Result := HTMENU;
      end
      else begin
        GripVisible := False;
        if (FOwner is TsSkinProvider) then with TsSkinProvider(FOwner) do begin
          if IsGripVisible(TsSkinProvider(FOwner)) then GripVisible := True else if Assigned(ListSW) and Assigned(ListSW.sbarVert) and ListSW.sbarVert.fScrollVisible and ListSW.sbarHorz.fScrollVisible then begin
            Ac_GetHScrollRect(ListSW, Form.Handle, hrect);
            Ac_GetVScrollRect(ListSW, Form.Handle, vrect);
            GetWindowRect(Form.Handle, R);
            GripVisible := PtInRect(Rect(hrect.Right - R.Left, hrect.Top - R.Top, vrect.Right - R.Left, hrect.Bottom - R.Top), p)
          end;
        end;
        if GripVisible then begin
          i := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_GripImage);
          if SkinData.SkinManager.IsValidImgIndex(i) then begin
            if (p.y > TsSkinProvider(FOwner).RBGripPoint(i).y) and (p.x > TsSkinProvider(FOwner).RBGripPoint(i).x) then Result := HTBOTTOMRIGHT;
          end;
        end;
        if Result <> DefRESULT then SetHotHT(Result) else SetHotHT(0);
      end;
    end;
  end;
end;

function TacBorderForm.Ex_WMSetCursor(var Message: TWMSetCursor) : boolean;
var
  M : TWMNCHitTest;
  nCursor : HCURSOR;
begin
  M.Msg := WM_NCHitTest;
  M.XPos := SmallInt(acMousePos.X);
  M.YPos := SmallInt(acMousePos.Y);
  M.Unused := 0;
  M.Result := 0;
{$IFDEF D2009}
  Message.HitTest := SmallInt(Ex_WMNCHitTest(M));
{$ELSE}  
  Message.HitTest := Word(Ex_WMNCHitTest(M));
{$ENDIF}  
  Result := False;
  if not MouseAboveTheShadow(TWMMouse(M)) then begin
    nCursor := 0;
    case Message.HitTest of
      HTCAPTION, HTMENU : nCursor := LoadCursor(0, IDC_ARROW);
      HTLEFT, HTRIGHT : nCursor := LoadCursor(0, IDC_SIZEWE);
      HTTOP, HTBOTTOM : nCursor := LoadCursor(0, IDC_SIZENS);
      HTTOPRIGHT, HTBOTTOMLEFT : nCursor := LoadCursor(0, IDC_SIZENESW);
      HTTOPLeft, HTBOTTOMRIGHT : nCursor := LoadCursor(0, IDC_SIZENWSE)
    end;
    if nCursor <> 0 then begin
      SetCursor(nCursor);
      Result := True;
    end;
  end
end;

procedure TacBorderForm.FinishAnimation(const BtnIndex: integer);
begin
end;

function TacBorderForm.MouseAboveTheShadow(Message: TWMMouse): boolean;
var
  p : TPoint;
begin
  Result := False;
  if Message.Msg = WM_MOUSEMOVE then p := Point(Message.XPos, Message.YPos) else p := Point(Message.XPos - AForm.Left, Message.YPos - AForm.Top);
  if not IsZoomed(OwnerHandle) then begin
    if (p.Y < ShadowSize.Top) or (p.Y > AForm.Height - ShadowSize.Bottom) or (p.X < ShadowSize.Left) or (p.X > AForm.Width - ShadowSize.Right) then begin
      Result := True;
      SetHotHT(HTTRANSPARENT);
    end;
  end;
end;

procedure TacBorderForm.UpdateExBordersPos(Redraw : boolean = True; Blend : byte = MaxByte);
var
  fR : TRect;
  w, h, cy, cx : integer;
  Flags : Cardinal;
  DC : hdc;
  FBmpSize: TSize;
  FBmpTopLeft: TPoint;
  bSizeChanged : boolean;
  iInsAfter : Cardinal;
begin
  with FOwner do begin
    if (AForm = nil) or Application.Terminated or ExBorderShowing or (OwnerHandle = 0) or not GetWindowRect(OwnerHandle, fR) then Exit;

    if FOwner is TsSkinProvider then begin
      if InAnimation(TsSkinProvider(FOwner)) or SkinData.FUpdating or not TsSkinProvider(FOwner).DrawNonClientArea then Exit;
//      if fsShowing in TAccessForm(TsSkinProvider(FOwner).Form).FormState then Exit;

      if (csDestroying in TsSkinProvider(FOwner).ComponentState) or (csDestroying in TsSkinProvider(FOwner).Form.ComponentState) then begin
        TsSkinProvider(FOwner).InitExBorders(False);
        Exit;
      end
      else if not TsSkinProvider(FOwner).Form.Visible or IsIconic(Application.Handle) then begin
        ShowWindow(AForm.Handle, SW_HIDE);
        Exit;
      end;
    end
    else if not IsWindowVisible(OwnerHandle) then Exit; // If dialog is not visible still

    ExBorderShowing := True;

    if SkinData.BGChanged then begin
      PaintAll;
      Redraw := True;
    end;

    if (FOwner is TsSkinProvider) and TsSkinProvider(FOwner).FSysExHeight
      then cy := ShadowSize.Top + DiffTitle(Self) + SysBorderWidth(OwnerHandle, Self, False) //  4 { For MinMax patching }
      else begin
{      if IsZoomed(OwnerHandle) and (SkinData.SkinManager.SkinData.ExMaxHeight <> SkinData.SkinManager.SkinData.ExTitleHeight)
        then cy := SkinTitleHeight(Self) - CaptionHeight(False) + ShadowSize.Top - SysBorderWidth(OwnerHandle, Self, False) + SkinData.SkinManager.SkinData.ExTitleHeight - SkinData.SkinManager.SkinData.ExMaxHeight
        else}
{      cy := ShadowSize.Top;
      cy := cy - SysBorderWidth(OwnerHandle, Self, False);

      cy := cy + SkinTitleHeight(Self) - CaptionHeight(False);}
      cy := OffsetY;
//      if IsZoomed(OwnerHandle) then inc(cy, SysBorderWidth(OwnerHandle, Self, False));
    end;
    cx := SkinBorderWidth(Self) - SysBorderWidth(OwnerHandle, Self, False) + ShadowSize.Left;
    w := SkinData.FCacheBmp.Width;
    h := SkinData.FCacheBmp.Height;

    iInsAfter := OwnerHandle; // GetNextWindow(OwnerHandle, GW_HWNDPREV);
    if (GetWindowLong(OwnerHandle, GWL_EXSTYLE) and WS_EX_TOPMOST = WS_EX_TOPMOST) then begin
      AForm.FormStyle := fsStayOnTop;
    end
    else if not (FOwner is TsSkinProvider) then begin
      if (GetWindowLong(OwnerHandle, GWL_STYLE) and WS_POPUP = WS_POPUP) then begin
        SetWindowLong(AForm.Handle, GWL_STYLE, GetWindowLong(AForm.Handle, GWL_STYLE) or WS_POPUP);
      end;
    end;

    Flags := SWP_NOACTIVATE or SWP_NOSENDCHANGING or SWP_NOOWNERZORDER;

    if Redraw or (AForm.Width <> w) or (AForm.Height <> h) then bSizeChanged := True else begin
      Flags := Flags or SWP_NOSIZE;
      bSizeChanged := False;
    end;
    if not Redraw then Flags := Flags or SWP_NOREDRAW;

    // SetWindowPos has a problems under Aero
    AForm.Left := fR.Left - cx;
    AForm.Top := fr.Top - cy;
    AForm.Width := w;
    AForm.Height := h;
    if acLayered and bSizeChanged and not acInMouseMsg then begin
      FBmpSize.cx := SkinData.FCacheBmp.Width;
      FBmpSize.cy := SkinData.FCacheBmp.Height;
      FBmpTopLeft := Point(0, 0);
{$IFDEF DELPHI6UP}
      if FOwner is TsSkinProvider and TsSkinProvider(FOwner).Form.AlphaBlend then begin
        FBlend.SourceConstantAlpha := TsSkinProvider(FOwner).Form.AlphaBlendValue;
      end
      else
{$ENDIF}
      FBlend.SourceConstantAlpha := Blend;
      FBlend.BlendOp := AC_SRC_OVER;
      FBlend.BlendFlags := 0;
      FBlend.AlphaFormat := AC_SRC_ALPHA;

      SetWindowLong(AForm.Handle, GWL_EXSTYLE, GetWindowLong(AForm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED or WS_EX_NOACTIVATE);
      SetWindowPos(AForm.Handle, iInsAfter, 0, 0, 0, 0, Flags or SWP_NOSIZE or SWP_NOMOVE);

      SetWindowRgn(AForm.Handle, MakeRgn, False);
      DC := GetDC(0);
      UpdateLayeredWindow(AForm.Handle, DC, nil, @FBmpSize, SkinData.FCacheBmp.Canvas.Handle, @FBmpTopLeft, clNone, @FBlend, ULW_ALPHA);

      if Blend = 0 then SetWindowLong(OwnerHandle, GWL_STYLE, GetWindowLong(OwnerHandle, GWL_STYLE) and not WS_VISIBLE); // Preventing of main form painting
      ShowWindow(AForm.Handle, SW_SHOWNOACTIVATE);
      if Blend = 0 then SetWindowLong(OwnerHandle, GWL_STYLE, GetWindowLong(OwnerHandle, GWL_STYLE) or WS_VISIBLE);

      ReleaseDC(DC, 0);
    end
    else SetWindowPos(AForm.Handle, iInsAfter, 0, 0, 0, 0, Flags or SWP_NOSIZE or SWP_NOMOVE);
  end;
  ExBorderShowing := False;
end;

procedure TacBorderForm.KillAnimations;
begin
  if FOwner is TsSkinProvider then TsSkinProvider(FOwner).KillAnimations else if FOwner is TacDialogWnd then TacDialogWnd(FOwner).KillAnimations;
end;

function TacBorderForm.OffsetX: integer;
begin
  Result := SkinBorderWidth(Self) - SysBorderWidth(OwnerHandle, Self, False) + ShadowSize.Left
end;

function TacBorderForm.OffsetY: integer;
begin
  Result := ShadowSize.Top - SysBorderWidth(OwnerHandle, Self, False) + SkinTitleHeight(Self) - CaptionHeight(False)
end;

function TacBorderForm.OwnerHandle: hwnd;
begin
  Result := 0;
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).Form.Handle else if (FOwner is TacDialogWnd) then Result := TacDialogWnd(FOwner).CtrlHandle
end;

function TacBorderForm.ShadowSize: TRect;
begin
  Result := SkinData.SkinManager.FormShadowSize;
end;

procedure TacBorderForm.SetHotHT(const i: integer; Repaint: boolean);
begin
  if FOwner is TsSkinProvider then TsSkinProvider(FOwner).SetHotHT(i) else TacDialogWnd(FOwner).SetHotHT(i);
end;

function TacBorderForm.CaptionHeight(CheckSkin : boolean = True) : integer;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).CaptionHeight(CheckSkin) else Result := TacDialogWnd(FOwner).CaptionHeight(CheckSkin)
end;

function TacBorderForm.MenuHeight: integer;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).MenuHeight else Result := 0;
end;

function TacBorderForm.IconRect: TRect;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).IconRect else Result := TacDialogWnd(FOwner).IconRect
end;

procedure TacBorderForm.PaintAll;
begin
  if FOwner is TsSkinProvider then TsSkinProvider(FOwner).PaintAll else TacDialogWnd(FOwner).PaintAll
end;

function TacBorderForm.ButtonClose: TsCaptionButton;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).ButtonClose else Result := TacDialogWnd(FOwner).ButtonClose
end;

function TacBorderForm.ButtonHelp: TsCaptionButton;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).ButtonHelp else Result := TacDialogWnd(FOwner).ButtonHelp
end;

function TacBorderForm.ButtonMax: TsCaptionButton;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).ButtonMax else Result := TacDialogWnd(FOwner).ButtonMax
end;

function TacBorderForm.ButtonMin: TsCaptionButton;
begin
  if FOwner is TsSkinProvider then Result := TsSkinProvider(FOwner).ButtonMin else Result := TacDialogWnd(FOwner).ButtonMin
end;

function TacBorderForm.MakeRgn: HRGN;
var
  R : TRect;
  i, cx, dx : integer;
{$IFDEF DELPHI7UP}
  SubRgn : hrgn;
{$ENDIF}  
begin
  if IsZoomed(OwnerHandle) then begin
    i := SysBorderWidth(OwnerHandle, Self, False);
    cx := i;
    dx := DiffBorder(Self);
    R := Rect(cx + dx + ShadowSize.Left, 4 + ShadowSize.Top, AForm.Width - cx - dx - ShadowSize.Right, AForm.Height - cx - dx - ShadowSize.Bottom);
    Result := CreateRectRgn(R.Left, R.Top, R.Right, R.Bottom);
{$IFDEF DELPHI7UP}
    if (FOwner is TsSkinProvider) and TsSkinProvider(FOwner).Form.AlphaBlend then begin
      R.Left := TsSkinProvider(FOwner).OffsetX;
      R.Top := TsSkinProvider(FOwner).OffsetY;
      R.Right := R.Left + TsSkinProvider(FOwner).Form.ClientWidth;
      R.Bottom := R.Top + TsSkinProvider(FOwner).Form.ClientHeight;
      SubRgn := CreateRectRgn(R.Left, R.Top, R.Right, R.Bottom);
      CombineRgn(Result, Result, SubRgn, RGN_XOR);
      DeleteObject(SubRgn);
    end;
{$ENDIF}
  end
{$IFDEF DELPHI7UP}
  else if (FOwner is TsSkinProvider) and TsSkinProvider(FOwner).Form.AlphaBlend then begin
    Result := CreateRectRgn(0, 0, AForm.Width, AForm.Height);
    R.Left := TsSkinProvider(FOwner).OffsetX;
    R.Top := TsSkinProvider(FOwner).OffsetY;
    R.Right := R.Left + TsSkinProvider(FOwner).Form.ClientWidth;
    R.Bottom := R.Top + TsSkinProvider(FOwner).Form.ClientHeight;
    SubRgn := CreateRectRgn(R.Left, R.Top, R.Right, R.Bottom);
    CombineRgn(Result, Result, SubRgn, RGN_XOR);
    DeleteObject(SubRgn);
  end
{$ENDIF}
  else Result := 0;
end;

{ TacSBAnimation }

procedure TacSBAnimation.ChangeState(NewState: integer; ToUp : boolean);
begin
  Up := ToUp;
  Enabled := True;
end;

procedure TacSBAnimation.CheckMouseLeave;
var
  P : TPoint;
  R : TRect;
begin
  if BorderForm <> nil then p := Point(acMousePos.X - BorderForm.AForm.Left, acMousePos.Y - BorderForm.AForm.Top) else begin
    GetWindowRect(FormHandle, R);
    p := Point(acMousePos.X - R.Left, acMousePos.Y - R.Top);
  end;
//  P := CursorToPoint(acMousePos.X, acMousePos.Y);//acMousePos;!
  if not PtInRect(PBtnData^.Rect, P) then begin
    Enabled := False;
    SendMessage(FormHandle, WM_MOUSELEAVE, 0, 0);
{    if CurrentHT = PBtnData^.HitCode then CurrentHT := 0;

    PBtnData^.State := 0;
    PBtnData^.Timer := nil;
    Free;
{
    FreeAndNil(AForm);
    FreeAndNil(ABmp);}
//    SetHotHT(0);
  end;
end;

constructor TacSBAnimation.Create(AOwner: TComponent);
begin
  inherited;
  CurrentLevel := 0;
  CurrentState := 0;
  Up := False;
  OnTimer := OnAnimTimer;
end;

destructor TacSBAnimation.Destroy;
begin
  Enabled := False;
  if AForm <> nil then FreeAndNil(AForm);
  if ABmp <> nil then FreeAndNil(ABmp);
  PBtnData^.Timer := nil;
  inherited;
end;

function TacSBAnimation.GetFormBounds: TRect;
var
  mi, mOffset : integer;
begin
  if BorderForm <> nil then GetWindowRect(BorderForm.AForm.Handle, Result) else GetWindowRect(FormHandle, Result);
  OffsetRect(Result, PBtnData^.Rect.Left, PBtnData^.Rect.Top);

  mOffset := Offset;

  if mOffset <> 0 then begin
    mi := SkinData.SkinManager.GetMaskIndex(s_GlobalInfo, SkinData.SkinManager.ma[PBtnData^.ImageIndex].PropertyName + s_Glow + '0');
    if (mi > -1) then begin
      Result.Left := Result.Left - mOffset;
      Result.Top := Result.Top - mOffset;
      Result.Right := Result.Left + WidthOf(SkinData.SkinManager.ma[mi].R);
      Result.Bottom := Result.Top + HeightOf(SkinData.SkinManager.ma[mi].R);
    end
    else mOffset := 0;
  end;
  if mOffset = 0 then begin
    Result.Right := Result.Left + WidthOf(PBtnData^.Rect, True);
    Result.Bottom := Result.Top + HeightOf(PBtnData^.Rect, True);            
  end;
end;

procedure TacSBAnimation.MakeForm;
begin
  if AForm = nil then begin
    AForm := TForm.Create(nil);
    AForm.Tag := ExceptTag;
    AForm.Visible := False;
    AForm.BorderStyle := bsNone;
    AForm.Color := clRed;
    SetWindowLong(AForm.Handle, GWL_EXSTYLE, GetWindowLong(AForm.Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE or WS_EX_TRANSPARENT);
  end;
end;

procedure TacSBAnimation.MakeImg;
var
  R : TRect;
  mi : integer;
  b : boolean;
  CI : TCacheInfo;
  x, y, j : integer;
  p : PRGBAArray;
begin
  if (CurrentState = 0) and (ABmp <> nil) then Exit; // Updating is not required
  R := GetFormBounds;

  b := SkinData.SkinManager.AllowGlowing and (CurrentState = 1) and (PBtnData^.HitCode in [HTCLOSE, HTMAXBUTTON, HTMINBUTTON]);
  if b then begin
    mi := SkinData.SkinManager.GetMaskIndex(s_GlobalInfo, SkinData.SkinManager.ma[PBtnData^.ImageIndex].PropertyName + s_Glow + '0');
    b := mi <> -1;
  end;
  if ABmp = nil then ABmp := CreateBmp32(WidthOf(R, True), HeightOf(R, True));

  if b then with SkinData.SkinManager do begin
    BitBlt(ABmp.Canvas.Handle, 0, 0, ABmp.Width, ABmp.Height, ma[mi].Bmp.Canvas.Handle, 0, 0, SRCCOPY);
  end
  else begin
    CI.X := PBtnData^.Rect.Left;
    CI.Y := PBtnData^.Rect.Top;
    if (SkinData.FOwnerObject is TsSkinProvider) and (TsSkinProvider(SkinData.FOwnerObject).TempBmp <> nil) then begin
      CI.X := CI.X - (TsSkinProvider(SkinData.FOwnerObject).CaptionWidth - TsSkinProvider(SkinData.FOwnerObject).TempBmp.Width - 1);
      CI.Bmp := TsSkinProvider(SkinData.FOwnerObject).TempBmp;
    end
    else CI.Bmp := SkinData.FCacheBmp;
    CI.Ready := True;
    BitBlt(ABmp.Canvas.Handle, 0, 0, ABmp.Width, ABmp.Height, CI.Bmp.Canvas.Handle, CI.X, CI.Y, SRCCOPY);
    if (PBtnData^.ImageIndex > -1) then begin
      DrawSkinGlyph(ABmp, Point(0, 0), PBtnData^.State, 1, SkinData.SkinManager.ma[PBtnData^.ImageIndex], MakeCacheInfo(ABmp));
    end;
    if BorderForm = nil then for y := 0 to ABmp.Height - 1 do begin // If AlphaChannel must be updated
      p := ABmp.ScanLine[y];
      for x := 0 to ABmp.Width - 1 do p[x].A := MaxByte;
    end;
  end;
  if (SkinData.FOwnerObject is TsSkinProvider) then with TsSkinProvider(SkinData.FOwnerObject) do if Between(PBtnData^.HitCode, HTUDBTN, HTUDBTN + TitleButtons.Count - 1) then begin // User defined button glyph
    j := PBtnData^.HitCode - HTUDBTN;
    if not TitleButtons.Items[j].Glyph.Empty then begin
      if TitleButtons.Items[j].Glyph.PixelFormat = pf32bit then begin
        x := (ABmp.Width - TitleButtons.Items[j].Glyph.Width) div 2;
        y := (ABmp.Height - TitleButtons.Items[j].Glyph.Height) div 2;
        if (PBtnData^.State = 2) then begin inc(x); inc(y) end;
        CopyByMask(Rect(x, y, x + TitleButtons.Items[j].Glyph.Width, y + TitleButtons.Items[j].Glyph.Height),
                   Rect(0, 0, TitleButtons.Items[j].Glyph.Width, TitleButtons.Items[j].Glyph.Height),
                   ABmp, TitleButtons.Items[j].Glyph, EmptyCI, True);
      end
      else begin
        TitleButtons.Items[j].Glyph.PixelFormat := pf24bit;
        CopyTransBitmaps(ABmp, TitleButtons.Items[j].Glyph,
             integer(PBtnData^.State = 2) + (WidthOf(PBtnData^.Rect) - TitleButtons.Items[j].Glyph.Width) div 2,
             integer(PBtnData^.State = 2) + (HeightOf(PBtnData^.Rect) - TitleButtons.Items[j].Glyph.Height) div 2,
             ColorToSColor(TitleButtons.Items[j].Glyph.Canvas.Pixels[0, TitleButtons.Items[j].Glyph.Height - 1]));
      end;
    end
  end;
end;

function TacSBAnimation.Offset: integer;
begin
  Result := 0;
  if SkinData.SkinManager.AllowGlowing and (CurrentState = 1) and (PBtnData^.HitCode in [HTCLOSE, HTMAXBUTTON, HTMINBUTTON]) then begin
    case PBtnData^.HitCode of
      HTCLOSE      : Result := SkinData.SkinManager.SkinData.BICloseGlowMargin;
      HTMAXBUTTON  : Result := SkinData.SkinManager.SkinData.BIMaxGlowMargin;
      HTMINBUTTON  : Result := SkinData.SkinManager.SkinData.BIMinGlowMargin;
    end;
  end
end;

procedure TacSBAnimation.OnAnimTimer(Sender: TObject);
begin
  if not Enabled then Exit;
  if Up then begin
    if CurrentLevel >= MaxIterations then begin
      CheckMouseLeave;
      if MaxIterations <> -1 then begin
        MaxIterations := -1;
        UpdateForm($FF);
      end;
    end
    else begin
      UpdateForm(max(min(CurrentLevel * Step, MaxByte), 0));
      inc(CurrentLevel);
    end;
  end
  else begin
    if CurrentLevel <= 0 then begin
      CurrentState := -1;
      Enabled := False;
      UpdateForm(0);
      FreeAndNil(AForm);
      FreeAndNil(ABmp);
    end
    else begin
      UpdateForm(max(0, min(CurrentLevel * Step, MaxByte)));
      dec(CurrentLevel);
    end;
  end;
end;

procedure TacSBAnimation.StartAnimation(NewState: integer; ToUp : boolean);
begin
  if CurrentState <> NewState then begin
    CurrentState := NewState;
    if NewState <> 0 then begin
      if NewState = 2 then begin
        FreeAndNil(AForm);
        FreeAndNil(ABmp);
      end;
      CurrentLevel := 1;
      Up := ToUp;
      UpdateForm(min(Step, MaxByte));
      inc(CurrentLevel);
      if Maxiterations > 1 then Enabled := True;
    end
    else begin
      Up := False;
      dec(CurrentLevel);
      UpdateForm(min(Step, MaxByte));
      if Maxiterations > 1 then Enabled := True;
    end;
  end;
end;

function TacSBAnimation.Step: integer;
begin
  Result := max($FF div MaxIterations, 0); 
end;

procedure TacSBAnimation.UpdateForm(const Blend: integer);
var
  R : TRect;
  iInsAfter, Flags : Cardinal;
  FBmpSize : TSize;
  DC : hdc;
  FBmpTopLeft : TPoint;
begin
  if ABmp = nil then MakeImg;
  if AForm = nil then MakeForm;
  FBmpSize.cx := ABmp.Width;
  FBmpSize.cy := ABmp.Height;

  R := GetFormBounds;
  if FBmpSize.cx <> WidthOf(R) then begin // If in hiding of image
    InflateRect(R, (FBmpSize.cx - WidthOf(R)) div 2, (FBmpSize.cy - HeightOf(R)) div 2);
  end;
  if BorderForm <> nil
    then iInsAfter := GetNextWindow(BorderForm.AForm.Handle, GW_HWNDPREV)
    else iInsAfter := GetNextWindow(FormHandle, GW_HWNDPREV);
  Flags := SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_NOSENDCHANGING;

  // Replacement of SetWindowPos (for Aero)
  AForm.Left := R.Left;
  AForm.Top := R.Top;
  AForm.Width := FBmpSize.cx;
  AForm.Height := FBmpSize.cy;

  FBmpTopLeft := Point(0, 0);
  FBlend.SourceConstantAlpha := Blend;
  FBlend.BlendOp := AC_SRC_OVER;
  FBlend.BlendFlags := 0;
  FBlend.AlphaFormat := AC_SRC_ALPHA;

  SetWindowPos(AForm.Handle, iInsAfter, 0, 0, 0, 0, Flags or SWP_NOMOVE or SWP_NOSIZE);
//  SetWindowPos(AForm.Handle, iInsAfter, R.Left, R.Top, FBmpSize.cx, FBmpSize.cy, Flags);
  DC := GetDC(0);
  SetWindowLong(AForm.Handle, GWL_EXSTYLE, GetWindowLong(AForm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED or WS_EX_NOACTIVATE or WS_EX_TRANSPARENT);
  UpdateLayeredWindow(AForm.Handle, DC, nil, @FBmpSize, ABmp.Canvas.Handle, @FBmpTopLeft, clNone, @FBlend, ULW_ALPHA);
  ShowWindow(AForm.Handle, SW_SHOWNOACTIVATE);
  ReleaseDC(DC, 0);
end;

{ TacGraphItem }

constructor TacGraphItem.Create;
begin
  SkinData := TsCommonData.Create(Self, True);
  SkinData.COC := COC_TsAdapter;
  Handler := nil;
end;

destructor TacGraphItem.Destroy;
begin
  if (Handler <> nil) then FreeAndNil(Handler);
  FreeAndNil(SkinData);
  inherited Destroy;
end;

procedure TacGraphItem.DoHook(Control: TControl);
begin
  if (Control.Tag = ExceptTag) then Exit;

  Self.Ctrl := Control;
  SkinData.FOwnerControl := Control;
  SkinData.FOwnerObject := TObject(Control);

  Handler := TacSpeedButtonHandler.Create(Ctrl, SkinData, SkinData.SkinManager, SkinData.SkinSection);
end;

initialization

finalization
  if hDWMAPI > 0 then FreeLibrary(hDWMAPI);

end.

