unit acDials;
{$I sDefs.inc}
{.$DEFINE LOGGED}

interface

uses
  Windows, Controls, Graphics, Messages, SysUtils, Classes, Forms, sSkinProvider, acSBUtils, sCommonData, sSkinManager,
  sConst, menus;

type
  TacBorderStyle = (acbsDialog, acbsSingle, acbsNone, acbsSizeable, acbsToolWindow, acbsSizeToolWin);
  TacDialogWnd = class;

  TacSystemMenu = class(TsCustomSysMenu)
  public
    FOwner : TacDialogWnd;

    ItemRestore : TMenuItem;
    ItemMove : TMenuItem;
    ItemSize : TMenuItem;
    ItemMinimize : TMenuItem;
    ItemMaximize : TMenuItem;
    ItemClose : TMenuItem;

    constructor Create(AOwner : TComponent); override;
    function EnabledMove : boolean;
    function EnabledSize : boolean;
    procedure UpdateItems;

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

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

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

    function VisibleSize : boolean;
  end;

  TacProvider = class;

  TacDialogWnd = class(TacScrollWnd)
  protected
    ArOR : TAOR;
    CurrentHT : integer;
    FFormActive : boolean;
    FWMPaintForbidden : boolean;
    Initialized : boolean;
    procedure InitExBorders(const Active : boolean);
  public
    BorderForm : TacBorderForm;
    ButtonMin : TsCaptionButton;
    ButtonMax : TsCaptionButton;
    ButtonClose : TsCaptionButton;
    ButtonHelp : TsCaptionButton;

    TitleGlyph : TBitmap;
    TitleIcon : HIcon;
    TitleFont : TFont;
    dwStyle: LongInt;
    dwExStyle: LongInt;
    RgnChanged : boolean;
    WndRect : TRect;
    WndSize : TSize;
    BorderStyle : TacBorderStyle;
    TitleBG : TBitmap;
    TempBmp : TBitmap;
    Adapter : TacCtrlAdapter;
    SystemMenu : TacSystemMenu;
    Provider : TacProvider;
    procedure AdapterRemove;
    procedure SendToAdapter(Message : TMessage);
    // Drawing
    procedure MakeTitleBG;
    procedure PaintAll;
    procedure PaintBorderIcons;
    procedure PaintCaption(const DC : hdc);
    procedure PaintForm(var DC : hdc; SendUpdated : boolean = True);
    procedure PrepareTitleGlyph;
    procedure RepaintButton(i : integer);

    procedure acWndProc(var Message: TMessage); override;
    constructor Create(AHandle : hwnd; ASkinData : TsCommonData; ASkinManager : TsSkinManager; const SkinSection : string; Repaint : boolean = True); override;
    destructor Destroy; override;
    procedure InitParams;
    procedure UpdateIconsIndexes;
    procedure KillAnimations;

    // Messages
    procedure Ac_WMPaint(var Msg : TWMPaint);
    procedure Ac_WMNCPaint(var Message : TMessage);
    procedure Ac_WMNCHitTest(var Message : TMessage);
    procedure Ac_WMNCLButtonDown(var Message : TWMNCLButtonDown);
    procedure Ac_WMLButtonUp(var Message : TMessage);
    procedure Ac_WMActivate(var Message : TMessage);
    procedure Ac_WMNCActivate(var Message : TMessage);
    procedure Ac_DrawStaticItem(var Message : TWMDrawItem);
    function HTProcess(var Message : TWMNCHitTest) : integer;
    procedure SetHotHT(i : integer; Repaint : boolean = True);
    procedure SetPressedHT(i : integer);
    procedure DropSysMenu(x, y : integer);

    // Calculations
    function AboveBorder(Message : TWMNCHitTest) : boolean;
    function BarWidth(i : integer) : integer;
    function BorderHeight: integer;
    function ButtonHeight(Index : integer) : integer;
    function CaptionHeight(CheckSkin : boolean = True): integer;
    function CursorToPoint(x, y : integer) : TPoint;
    function FormActive : boolean;
    function HeaderHeight : integer;
    function OffsetX : integer;
    function OffsetY : integer;
    function IconRect : TRect;
    function ShadowSize : TRect;
    function SysButtonWidth(Btn : TsCaptionButton) : integer;
    function TitleBtnsWidth : integer;

    function VisibleMax : boolean;
    function VisibleMin : boolean;
    function VisibleHelp : boolean;
    function VisibleClose : boolean;
    function VisibleRestore : boolean;

    function EnabledMax : boolean;
    function EnabledMin : boolean;
    function EnabledClose : boolean;
    function EnabledRestore : boolean;
  end;

  TacProvider = class(TComponent)
  protected
    FForm: TForm;
  public
    BiDiLeft : boolean;
    CtrlHandle : THandle;
    sp : TsSkinProvider;
    ListSW : TacDialogWnd;

    acSkinnedCtrls : TList;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure InitForm(Form: TCustomForm);
    function InitSkin(aHandle : hwnd) : boolean;
    function InitHwndControls(hWnd : hwnd) : boolean;
    function AddControl(aHwnd : hwnd) : boolean;
    function FindCtrlInList(hwnd: THandle): TObject;
  end;

{$IFNDEF NOMNUHOOK}
  TacMnuArray = array of TacMnuWnd;
{$ENDIF}

var
  HookCallback, WndCallBack, WndCallRet : HHOOK;
  acSupportedList : TList;
  fRect : TRect;
  DlgLeft : integer = -1;
  DlgTop : integer = -1;
{$IFNDEF NOMNUHOOK}
  MnuArray : TacMnuArray;
{$ENDIF}

function VisibleDlgCount : integer;
function ControlExists(CtrlHandle : hwnd; const Name : string) : boolean;
function AddSupportedForm(hwnd: THandle): boolean;
function SkinHookCBT(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
function GetWndClassName(hwnd: THandle): string;
function FindFormInList(hwnd: THandle): TObject;
function FindFormOnScreen(hwnd: THandle): TCustomForm;
procedure InitDialog(hwnd: THandle; var ListSW : TacDialogWnd);
procedure DrawAppIcon(ListSW : TacDialogWnd);
function GetWndText(hwnd: THandle): WideString;
procedure FillArOR(ListSW : TacDialogWnd);
procedure UpdateRgn(ListSW : TacDialogWnd; Repaint : boolean = True);
function GetRgnFromArOR(ListSW : TacDialogWnd; X : integer = 0; Y : integer = 0) : hrgn;
procedure BroadCastHwnd(const hWnd: hwnd; Message: TMessage);
procedure ClearMnuArray;
procedure CleanArray;

implementation

uses
  sVclUtils, sMessages, acntUtils, FlatSB, sSkinProps{$IFDEF LOGGED}, sDebugMsgs{$ENDIF}, sGraphUtils, sMaskData,
  sAlphaGraph, sStrings, sStyleSimply, Commctrl, IniFiles, sSkinMenus, sDefaults, acGlow, math;

const
  rsfName = '#32770';
  s_TMessageForm = 'TMessageForm';

var
  biClicked : boolean = False;
  RgnChanging : boolean = False;

procedure BroadCastHwnd(const hWnd: hwnd; Message: TMessage);
var
  hCtrl : THandle;
begin
  hCtrl := GetTopWindow(hWnd);
  while hCtrl <> 0 do begin
    SendMessage(hCtrl, Message.Msg, Message.WParam, Message.LParam);
    hCtrl := GetNextWindow(hCtrl, GW_HWNDNEXT);
  end;
end;

function VisibleDlgCount : integer;
var
  i: integer;
  ap: TacProvider;
begin
  Result := 0;
  for i := 0 to acSupportedList.Count - 1 do begin
    ap := TacProvider(acSupportedList[i]);
    if (ap <> nil) and (ap.ListSW <> nil) and IsWindowVisible(ap.ListSW.CtrlHandle) then inc(Result);
  end;
end;

function ControlExists(CtrlHandle : hwnd; const Name : string) : boolean;
var
  hCtrl : THandle;
  s : string;
begin
  Result := False;
  hCtrl := GetTopWindow(CtrlHandle);
  while hCtrl <> 0 do begin
    s := LowerCase(GetWndClassName(hCtrl));
    if (s = Name) then begin
      Result := True;
      Exit;
    end
    else if ControlExists(hCtrl, Name) then begin
      Result := True;
      Exit;
    end;
    hCtrl := GetNextWindow(hCtrl, GW_HWNDNEXT);
  end;
end;

function SkinHookCBT(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
var
  wHandle : THandle;
  i : integer;
  s : string;
begin
{.$IFDEF LOGGED
  AddToLog(MakeMessage(code, wParam, lParam, 0));
$ENDIF}
  Result := CallNextHookEx(HookCallback, Code, wParam, lParam);
  case code of
    HCBT_CREATEWND : begin
      wHandle := Thandle(wParam);
      if wHandle = 0 then Exit;
      s := GetWndClassName(wHandle);
{$IFNDEF NOMNUHOOK}
      if (s = '#32768') then begin // Menu
        if not AeroIsEnabled and DefaultManager.SkinnedPopups then begin
          if not getboolmsg(whandle, ac_ctrlhandled) then begin
            i := length(mnuarray);
            setlength(mnuarray, i + 1);
            mnuarray[i] := tacmnuwnd.create(whandle, nil, defaultmanager, s_mainmenu, false);
            mnuarray[i].ctrlhandle := whandle;
//          setwindowlong(whandle, gwl_exstyle, getwindowlong(whandle, gwl_exstyle) or ws_ex_layered);
//          setlayeredwindowattributes(whandle, clnone, $ff, lwa_alpha);
//          if aeroisenabled then redrawwindow(whandle, nil, 0, rdw_frame or rdw_invalidate or rdw_updatenow);
          end;
        end;
      end
      else
{$ENDIF}
      if (GetParent(wHandle) = 0)
        then {$IFDEF ACBETATEST} AddSupportedForm(wHandle) {$ENDIF};
    end;
    HCBT_ACTIVATE : AddSupportedForm(THandle(wParam));
    HCBT_DESTROYWND : CleanArray;
  end;
end;

function AddSupportedForm(hwnd: THandle): boolean;
var
  ap : TacProvider;
  Form : TCustomForm;
  s : string;
  b : boolean;
  i : integer;
begin
  Result := false;
  if GetBoolMsg(hwnd, AC_CTRLHANDLED) then Exit;
  if (DefaultManager = nil) then Exit;
  if FindFormInList(hwnd) = nil then begin
    Form := FindFormOnScreen(hwnd);
    if (Form <> nil) and (Form.Tag = ExceptTag) then Exit;
    s := GetWndClassName(hwnd); // Optimize !!
    if Form <> nil then begin

      if (s = 'TApplication') or (s = 'TQRStandardPreview') {$IFDEF DEVEX}or (s = 'TcxGridFilterPopup') or (s = 'TcxShellComboBoxPopupWindow'){$ENDIF} or (s = 'TfcPopup' {FastCube popup}) then exit;

      b := s = s_TMessageForm;
      if b then begin
        if not (srStdDialogs in DefaultManager.SkinningRules) then Exit;
      end
      else begin
        if not (srStdForms in DefaultManager.SkinningRules) {or (Form.Tag = ExceptTag) }then Exit;
      end;
      ap := TacProvider.Create(Form);
      acSupportedList.add(ap);
      ap.InitForm(Form);
      if b and Assigned(ap.sp) then ap.sp.MakeSkinMenu := False;
      // Add MDIChild which haven't a SkinProvider
      if TForm(Form).FormStyle = fsMDIForm then begin
        for i := 0 to TForm(Form).MDIChildCount - 1 do begin
          if not GetBoolMsg(TForm(Form).MDIChildren[i].Handle, AC_CTRLHANDLED) then begin
            ap := TacProvider.Create(TForm(Form).MDIChildren[i]);
            acSupportedList.add(ap);
            ap.InitForm(TForm(Form).MDIChildren[i]);
          end;
        end;
      end;
    end
    else begin
      if s <> rsfName then Exit; // If not Windows dialog
      if not (srStdDialogs in DefaultManager.SkinningRules) then Exit;
      if (VisibleDlgCount > 0) and not ControlExists(hwnd, 'toolbarwindow32') then begin
        Result := False;
        Exit;
      end;
      ap := TacProvider.Create(Form);
      acSupportedList.add(ap);
      if not ap.InitSkin(hwnd) then FreeAndNil(ap);
    end;
    Result := true;
  end;
end;

function GetWndClassName(Hwnd: THandle): string;
var
  Buf: array[0..128] of char;
begin
  GetClassName(Hwnd, Buf, 128);
  result := StrPas(Buf);
end;

function FindFormInList(hwnd: THandle): TObject;
var
  i: integer;
  ap: TacProvider;
begin
  Result := nil;
  for i := 0 to acSupportedList.Count - 1 do begin
    ap := TacProvider(acSupportedList[i]);
    if (ap <> nil) and (ap.CtrlHandle = hwnd) then begin
      Result := ap;
      Break;
    end;
  end;
end;

function FindFormOnScreen(hwnd: THandle): TCustomForm;
var
  i, j : integer;
  f : TCustomForm;
begin
  Result := nil;
  for i := 0 to Screen.CustomFormCount - 1 do begin
    f := Screen.CustomForms[i];
    if f.Handle = hwnd then begin
      Result := Screen.CustomForms[i];
      exit;
    end;
    with TForm(Screen.CustomForms[i]) do if FormStyle = fsMDIForm then for j := 0 to MDIChildCount - 1 do if MDIChildren[j].Handle = hwnd then begin
      Result := TForm(Screen.CustomForms[i]).MDIChildren[j];
      exit;
    end;
  end;
end;

{ TacProvider }

function TacProvider.AddControl(aHwnd: hwnd) : boolean;
var
  st : dword;
  Style : LongInt;
  s: string;
  Wnd : TacMainWnd;
  R : TRect;
begin
  if (aHwnd = 0) then Exit;
  Result := True;
  if GetBoolMsg(aHwnd, AC_CTRLHANDLED) then exit;

  acDlgMode := True;

  s := LowerCase(GetWndClassName(aHwnd));

  Style := GetWindowLong(aHwnd, GWL_STYLE);
  Wnd := nil;
  if s = 'static' then begin
    GetWindowRect(aHwnd, R);
    st := Style and SS_TYPEMASK;

    if (Style and SS_ICON = SS_ICON) then begin // Icon
      Wnd := TacIconWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
    end
    else if (Style and SS_BITMAP = SS_BITMAP) then begin // Bitmap
      Wnd := TacIconWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
    end
    else if (Style and SS_OWNERDRAW = SS_OWNERDRAW) then begin // Bitmap
    end
    else if st in [SS_SIMPLE, SS_GRAYRECT, SS_WHITERECT] then begin // Bitmap
    end
    else begin
      Wnd := TacStaticWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
    end;
  end
  else if (s = rsfName) then begin
    Wnd := TacTransPanelWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
  end
  else if (s = 'tpanel') then begin
    acSkinnedCtrls.Add(TacDlgPanelWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Panel))
  end
  else if (s = 'tsilentpaintpanel') then begin
    acSkinnedCtrls.Add(TacDlgPanelWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Panel))
  end
  else if (s = 'button') then begin
    if Style and BS_GROUPBOX = BS_GROUPBOX then begin
      Wnd := TacGroupBoxWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_GroupBox)
    end
    else if (Style and BS_AUTOCHECKBOX = BS_AUTOCHECKBOX) or (Style and BS_CHECKBOX = BS_CHECKBOX) or (Style and BS_3STATE = BS_3STATE) then begin
      Wnd := TacCheckBoxWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
    end
    else if (Style and BS_AUTORADIOBUTTON = BS_AUTORADIOBUTTON) or (Style and BS_RADIOBUTTON = BS_RADIOBUTTON) then begin
      Wnd := TacCheckBoxWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
    end
    else Wnd := TacBtnWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Button)
  end
  else if (s = 'combobox') then begin
    if ListSW <> nil then ListSW.FWMPaintForbidden := False;
    if (GetWindowLong(aHwnd, GWL_STYLE) and CBS_OWNERDRAWFIXED = CBS_OWNERDRAWFIXED) then begin
      Wnd := TacComboBoxWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_ComboBox)
    end
    else begin
      Wnd := TacComboBoxWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_ComboBox)
    end;
    TacEditWnd(Wnd).DlgMode := True;
  end
  else if (s = 'combolbox') then begin
    if ListSW <> nil then ListSW.FWMPaintForbidden := False;
    Wnd := TacEditWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_ComboBox);
  end
  else if (s = 'comboboxex32') then begin
    if ListSW <> nil then ListSW.FWMPaintForbidden := False;
    Wnd := TacComboBoxWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_ComboBox)
  end
  else if (s = 'scrollbar') then begin
    Wnd := TacSizerWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
  end
{  else if (s = 'msctls_trackbar32') then begin
    Result := False; // Is not supported
  end}
  else if (s = 'systabcontrol32') then begin
    if ((Style and TCS_OWNERDRAWFIXED) <> TCS_OWNERDRAWFIXED) then begin
      Wnd := TacTabControlWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_PageControl);
    end;
//    if (WidthOf(R) = 470) and (HeightOf(R) = 349) then Result := False; // if Printer properties Dlg !!!
  end
  else if (s = 'syslistview32') then begin
    Wnd := TacListViewWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Edit);
    TacEditWnd(Wnd).DlgMode := True;
  end
  else if (s = 'msctls_updown32') then begin
    Wnd := TacSpinWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_SpeedButton_Small);
    TacSpinWnd(Wnd).lOffset := 2;
  end
{  else if (s = 'shelldll_defview') then begin
    acSkinnedCtrls.Add(TacBtnWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_DlgEdit));
  end}
  else if (s = 'listbox') then begin
    Wnd := TacEditWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Edit);
    TacEditWnd(Wnd).DlgMode := True;
  end
  else if (s = 'link window') or (s = 'syslink') then begin
    Wnd := TacLinkWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox);
  end
  else if (s = 'toolbarwindow32') then begin
    if GetWindowLong(aHwnd, GWL_STYLE) and TBSTYLE_WRAPABLE = TBSTYLE_WRAPABLE
      then Wnd := TacToolBarWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Bar)
      else Wnd := TacToolBarWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox);
  end
  else if (s = 'edit') then begin
    if ListSW <> nil then ListSW.FWMPaintForbidden := False;
    if IsWindowVisible(aHwnd) then begin // Solving a problem in non-sizeable file dialogs
      Wnd := TacEditWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Edit);
      TacEditWnd(Wnd).DlgMode := True;
    end
  end
  else if (s = 'systreeview32') then begin
    Wnd := TacTreeViewWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_Edit);
    TacEditWnd(Wnd).DlgMode := True;
  end
  else if (pos('shbrowseforfolder', s) > 0) then begin
    Wnd := TacTransPanelWnd.Create(aHwnd, nil, ListSW.SkinData.SkinManager, s_CheckBox)
  end;
  if Wnd <> nil then begin
    acSkinnedCtrls.Add(Wnd);
    InitCtrlData(CtrlHandle, Wnd.ParentWnd, Wnd.WndRect, Wnd.ParentRect, Wnd.WndSize, Wnd.WndPos, Wnd.Caption);
  end;
  acDlgMode := False;
end;

constructor TacProvider.Create(AOwner: TComponent);
begin
  inherited;
  BiDiLeft := False;
end;

destructor TacProvider.Destroy;
var
  i : integer;
begin
  if (sp = nil) then begin
    if acSkinnedCtrls <> nil then begin
      for i := 0 to acSkinnedCtrls.Count - 1 do if acSkinnedCtrls[i] <> nil then TObject(acSkinnedCtrls[i]).Free;
      FreeAndNil(acSkinnedCtrls);
    end;
    if (ListSW <> nil) then FreeAndNil(ListSW);
  end
  else for i := 0 to acSupportedList.Count - 1 do if acSupportedList[i] = Self then begin
    acSupportedList[i] := nil;
    Break;
  end;
  inherited;
end;

function TacProvider.FindCtrlInList(hwnd: THandle): TObject;
var
  i: integer;
begin
  Result := nil;
  for i := 0 to acSkinnedCtrls.Count - 1 do if TacScrollWnd(acSkinnedCtrls[i]).CtrlHandle = hwnd then begin
    Result := TacScrollWnd(acSkinnedCtrls[i]);
    Break;
  end;
end;

procedure TacProvider.InitForm(Form: TCustomForm);
begin
  sp := TsSkinProvider.Create(Form);
  sp.Form := TForm(Form);
  if AeroIsEnabled then begin // Special initialization is required later
    if sp.Adapter = nil then sp.Loaded;//AdapterCreate;
//    SendAMessage(sp.Form.Handle, AC_CONTROLLOADED);
    SetWindowLong(sp.Form.Handle, GWL_STYLE, GetWindowLong(sp.Form.Handle, GWL_STYLE) or WS_VISIBLE);
    RedrawWindow(sp.Form.Handle, nil, 0, RDW_FRAME or RDW_ALLCHILDREN or RDW_INVALIDATE or RDW_ERASE or RDW_UPDATENOW);
  end;
  sp.MakeSkinMenu := (Form.BorderStyle in [bsSizeable, bsSingle]) and DefMakeSkinMenu;
end;

function TacProvider.InitHwndControls(hWnd : hwnd) : boolean;
var
  hCtrl : THandle;
begin
  Result := True;
  hCtrl := GetTopWindow(hWnd);
  while hCtrl <> 0 do begin
    if not InitHwndControls(hCtrl) then begin
      Result := False;
      Exit;
    end;
    if (GetWindowLong(hCtrl, GWL_STYLE) and WS_CHILD) = WS_CHILD then if not AddControl(hCtrl) then begin
      Result := False;
      Exit;
    end;
    hCtrl := GetNextWindow(hCtrl, GW_HWNDNEXT);
  end;
end;

function TacProvider.InitSkin(aHandle : hwnd) : boolean;
var
  xStyle: LongInt;
  WndClassName : string;
  Manager : TsSkinManager;
  i : integer;
begin
  Result := True;
  CtrlHandle := aHandle;
  acSkinnedCtrls := TList.Create;
  Manager := DefaultManager;
  if (ListSW = nil) and (Manager <> nil) and Manager.Active then begin
    style := GetWindowLong(CtrlHandle, GWL_STYLE);
    xStyle := GetWindowLong(CtrlHandle, GWL_EXSTYLE);
    BiDiLeft := (xStyle and WS_EX_LEFTSCROLLBAR) > 0;
    WndClassName := GetWndClassName(CtrlHandle);
    if (WndClassName = rsfName) or (WndClassName = s_TMessageForm) then begin
      InitDialog(CtrlHandle, ListSW);
      ListSW.Provider := Self;
      if (DlgLeft <> -1) or (DlgTop <> -1) then SetWindowPos(CtrlHandle, 0, DlgLeft, DlgTop, 0, 0, SWP_NOOWNERZORDER or SWP_NOREDRAW or SWP_NOSIZE);
      if InitHwndControls(CtrlHandle) then begin
        ListSW.InitParams;
        SendAMessage(CtrlHandle, AC_SETNEWSKIN, longword(DefaultManager));
//        RedrawWindow(CtrlHandle, nil, 0, RDW_FRAME or RDW_ALLCHILDREN or RDW_INVALIDATE or RDW_ERASE or RDW_UPDATENOW);
      end
      else begin
        for i := 0 to acSupportedList.Count - 1 do if acSupportedList[i] = Self then acSupportedList[i] := nil;
        Result := False;
      end;
    end;
  end;
end;

procedure InitDialog(hwnd: THandle; var ListSW : TacDialogWnd);
begin
  if Assigned(DefaultManager) and DefaultManager.Active then begin
    UninitializeFlatSB(hwnd);
    if (ListSW <> nil) and ListSW.Destroyed then FreeAndNil(ListSW);
    if ListSW = nil then begin
      ListSW := TacDialogWnd.Create(hwnd, nil, DefaultManager, s_Dialog, False);
      ListSW.CtrlHandle := hwnd;
    end;
  end
  else begin
    if ListSW <> nil then FreeAndNil(ListSW);
    InitializeFlatSB(hwnd);
  end;
end;

procedure DrawAppIcon(ListSW : TacDialogWnd);
var
  SmallIcon: HIcon;
  IcoSize : TSize;
  x, y : integer;
begin
  if ListSW.TitleIcon <> 0 then begin
    IcoSize.cx := GetSystemMetrics(SM_CXSMICON);
    IcoSize.cy := GetSystemMetrics(SM_CYSMICON);
    x := SysBorderWidth(ListSW.CtrlHandle, ListSW.BorderForm) + ListSW.SkinData.SkinManager.SkinData.BILeftMargin;
    y := (ListSW.CaptionHeight + SysBorderHeight(ListSW.CtrlHandle, ListSW.BorderForm) - IcoSize.cy) div 2;
    if ListSW.BorderForm <> nil then begin
      inc(x, ListSW.BorderForm.ShadowSize.Left);
      inc(y, ListSW.BorderForm.ShadowSize.Top);
    end;
    SmallIcon := Windows.CopyImage(ListSW.TitleIcon, IMAGE_ICON, IcoSize.cx, IcoSize.cy, LR_COPYFROMRESOURCE);
    if SmallIcon <> 0 then begin
      DrawIconEx(ListSW.SkinData.FCacheBmp.Canvas.Handle, x, y, SmallIcon, IcoSize.cx, IcoSize.cy, 0, 0, DI_NORMAL);
      DestroyIcon(SmallIcon);
    end
    else DrawIconEx(ListSW.SkinData.FCacheBmp.Canvas.Handle, x, y, LoadIcon(0, IDI_APPLICATION), IcoSize.cx, IcoSize.cy, 0, 0, DI_NORMAL);
  end
end;

function GetWndText(hwnd: THandle): WideString;
var
  buf: array[0..1000] of char;
begin
  Result := '';
  if Win32Platform = VER_PLATFORM_WIN32_NT then begin
    SetLength(Result, GetWindowTextLengthW(hwnd) + 1);
    GetWindowTextW(hwnd, PWideChar(Result), Length(Result));
    SetLength(Result, Length(Result) - 1);
  end
  else begin
    SendMessage(hwnd, WM_GETTEXT, 1000, integer(@buf));
    Result := StrPas(buf);
  end;
end;

procedure FillArOR(ListSW : TacDialogWnd);
var
  i : integer;
begin
  SetLength(ListSW.ArOR, 0);
  if ListSW.SkinData.SkinManager.IsValidImgIndex(ListSW.SkinData.BorderIndex) then begin
    // TopBorderRgn
    AddRgn(ListSW.ArOR, ListSW.WndSize.cx, ListSW.SkinData.SkinManager.ma[ListSW.SkinData.BorderIndex], 0, False);
    // BottomBorderRgn
    AddRgn(ListSW.ArOR, ListSW.WndSize.cx, ListSW.SkinData.SkinManager.ma[ListSW.SkinData.BorderIndex], ListSW.WndSize.cy - ListSW.SkinData.SkinManager.ma[ListSW.SkinData.BorderIndex].WB, True);
  end;

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

procedure UpdateRgn(ListSW : TacDialogWnd; Repaint : boolean = True);
const
  BE_ID = $41A2;
  CM_BEWAIT = CM_BASE + $0C4D;
var
  rgn : HRGN;
  sbw : integer;
begin
  if IsIconic(ListSW.CtrlHandle) or (ListSW.BorderStyle <> acbsNone) then with ListSW do begin
    if SendMessage(CtrlHandle, CM_BEWAIT, BE_ID, 0) = BE_ID then Exit; // BE compatibility
      RgnChanging := True;
      if (BorderForm <> nil) then begin
        sbw := SysBorderWidth(CtrlHandle, BorderForm, False);
        rgn := CreateRectRgn(sbw,
                             SysBorderHeight(CtrlHandle, BorderForm, False) + CaptionHeight(False) + SysBorderWidth(CtrlHandle, BorderForm, False),// + integer(sp.MenuHeight <> 0),
                             WndSize.cx - sbw,
                             WndSize.cy - sbw);
      end
      else rgn := GetRgnFromArOR(ListSW);
      SetWindowRgn(CtrlHandle, rgn, Repaint); // True - repainting required
  end;
end;

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

function EnumChildWndProc(Child: HWND; Data: LParam): BOOL; stdcall;
type
  PHWND = ^HWND;
var
  ParentWnd : hwnd;
begin
  ParentWnd := PHWND(Data)^;
  if GetParent(Child) = ParentWnd then begin
    PHWND(Data)^ := Child;
    Result := False;
  end
  else Result := True;
end;

type
  TExcludeData = record
    CtrlHandle : hwnd;
    DC : hdc;
    OffsetX : integer;
    OffsetY : integer;
  end;
  PExcludeData = ^TExcludeData;

function EnumCtrls(Child: HWND; Data: LParam): BOOL; stdcall;
var
  eData : TExcludeData;
  R{, cR} : TRect;
  Pos : TPoint;
  Style : Cardinal;
//  lFont : hFont;
//  i : integer;
begin
  eData := PExcludeData(Data)^;
  Result := True;
  if (GetParent(Child) = eData.CtrlHandle) then begin
    Style := GetWindowLong(Child, GWL_STYLE);
    if (Style and WS_VISIBLE = WS_VISIBLE) {(Style and WS_DISABLED <> WS_DISABLED) and (Style and SS_OWNERDRAW <> SS_OWNERDRAW) }then begin
      if (LowerCase(GetWndClassName(Child)) = 'static') and (Style and WS_TABSTOP = WS_TABSTOP) then Exit; // Skip Colors panel in Color dialog

      GetWindowRect(Child, R);
      Pos := R.TopLeft;
      ScreenToClient(eData.CtrlHandle, Pos);
      OffsetRect(R, Pos.X - R.Left + eData.OffsetX, Pos.Y - R.Top + eData.OffsetY);

      if (Style and BS_GROUPBOX = BS_GROUPBOX) then Exit{begin
        GetClientRect(Child, cR);
        ExcludeClipRect(eData.DC, R.Left, R.Top, R.Left + 3, R.Bottom);
        ExcludeClipRect(eData.DC, R.Left, R.Bottom - 3, R.Right, R.Bottom);
        ExcludeClipRect(eData.DC, R.Right - 3, R.Top, R.Right, R.Bottom);

        lFont := LongWord(SendMessage(Child, WM_GETFONT, 0, 0));
        if lFont <> 0 then begin
          i := GetFontHeight(lFont);
          ExcludeClipRect(eData.DC, R.Left, R.Top, R.Right, R.Top + i - 4);
        end;
      end}
      else ExcludeClipRect(eData.DC, R.Left, R.Top, R.Right, R.Bottom);
    end;
  end;
end;

procedure ExcludeControls(const DC : hdc; const Ctrl : hwnd; const OffsetX : integer; const OffsetY : integer);
var
  eData : TExcludeData;
begin
  eData.CtrlHandle := Ctrl;
  eData.DC := DC;
  eData.OffsetX := OffsetX;
  eData.OffsetY := OffsetY;
  EnumChildWindows(Ctrl, @EnumCtrls, LPARAM(@eData));
end;

{ TacDialogWnd }

procedure TacDialogWnd.acWndProc(var Message: TMessage);
var
  sw : TacMainWnd;
  PS : TPaintStruct;
//  p : PAnsiChar;
//  WndClass: TWndClassEx;
{  i, x, y, offX, offY, h, w, bw : integer;
  p : PRGBAArray;
  cR : TRect;
  SavedDC : hdc;
  tP : TPoint;}
begin
{$IFDEF LOGGED}
  AddToLog(Message);
{$ENDIF}
  case Message.Msg of
    WM_DESTROY, WM_NCDESTROY: begin
      if ((OldProc <> nil) or Assigned(OldWndProc)) then begin
        sw := Self;
        UninitializeACWnd(CtrlHandle, False, False, sw);
        Message.Result := CallPrevWndProc(CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      end;
      Exit;
    end;
  end;
  if Message.Msg = SM_ALPHACMD then case Message.WParamHi of
    AC_SETNEWSKIN : begin
      InitExBorders(SkinData.SkinManager.ExtendedBorders);
      if (LongWord(Message.LParam) = LongWord(SkinData.SkinManager)) then begin
        SkinData.UpdateIndexes;
        if (SkinData.SkinManager <> nil) then UpdateIconsIndexes;
        BroadCastHwnd(CtrlHandle, Message);
      end;
      Exit;
    end;
    AC_REFRESH : begin
      SkinData.UpdateIndexes;
      InitExBorders(SkinData.SkinManager.ExtendedBorders);
      SkinData.Invalidate;
      if (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos;
      Exit;
    end;
    AC_PREPARING : if (SkinData <> nil) then begin
      Message.Result := integer({SkinData.BGChanged or }SkinData.FUpdating);
      Exit;
    end;
    AC_UPDATING : begin
      SkinData.Updating := Message.WParamLo = 1;
      if SkinData.Updating then SkinData.BGChanged := True;
    end;
    AC_GETCONTROLCOLOR : begin
      Message.Result := GetBGColor(SkinData, 0);
      Exit;
    end;
    AC_GETBG : begin
      if PacBGInfo(Message.LParam)^.PleaseDraw then begin
        inc(PacBGInfo(Message.LParam)^.Offset.X, OffsetX);
        inc(PacBGInfo(Message.LParam)^.Offset.Y, OffsetY);
      end;
      InitBGInfo(SkinData, PacBGInfo(Message.LParam), 0);
      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 := SkinData.FCacheBmp;
          end;
          PacBGInfo(Message.LParam)^.Offset := Point(OffsetX, OffsetY);
        end;
      end;
      Exit;
    end;
    AC_UPDATECHILDREN : Provider.InitHwndControls(CtrlHandle); // SysListView re-init
    AC_CHILDCHANGED : begin
      Message.Result := integer((SkinData.SkinManager.gd[SkinData.SkinIndex].GradientPercent + SkinData.SkinManager.gd[SkinData.SkinIndex].ImagePercent > 0));
      Exit;
    end;
    AC_PARENTCLOFFSET : begin Message.Result := MakeLong(Word(OffsetX), Word(OffsetY)); Exit end;
    AC_INVALIDATE : if BorderForm <> nil then BorderForm.UpdateExBordersPos(False);
  end
  else case Message.Msg of
    DM_SETDEFID : begin
      inherited;
      Provider.InitHwndControls(CtrlHandle); // Rezerved searching of controls
    end;
{   Problem with returned file name
    WM_PARENTNOTIFY : begin
      inherited;
      if Message.WParamLo = WM_CREATE then Provider.InitHwndControls(CtrlHandle);
    end;                      }
    CM_VISIBLECHANGED : begin
      inherited;
      if (Message.WParam = 0) then KillAnimations;
    end;
    WM_GETDLGCODE : Exit;
    WM_MOUSEMOVE : begin
      if IsWindowEnabled(CtrlHandle) then DefaultManager.ActiveControl := 0;
    end;
    WM_NCHITTEST : begin
      Ac_WMNCHitTest(Message);
      Exit;
    end;
    WM_MOUSELEAVE : SetHotHT(0);
    WM_NCLBUTTONDOWN : begin
      if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTOBJECT) then begin
        Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
        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));
      Ac_WMNCLButtonDown(TWMNCLButtonDown(Message));
      Exit;
    end;
    WM_NCRBUTTONDOWN : begin
      if not (TWMNCLButtonUp(Message).HitTest in [HTCAPTION, HTSYSMENU]) then begin
        inherited
      end
      else Exit;
    end;
    WM_CTLCOLORDLG : begin
      Message.Result := LongInt(CreateSolidBrush(DefaultManager.GetGlobalColor));
      Exit;
    end;
    WM_DRAWITEM : begin
      case TWMDrawItem(Message).DrawItemStruct.CtlType of
        ODT_COMBOBOX : begin end;
        ODT_STATIC : Ac_DrawStaticItem(TWMDrawItem(Message));
      end
    end;
    WM_NCRBUTTONUP : begin
      if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTTRANSPARENT)
        then TWMNCLButtonDown(Message).HitTest := BorderForm.Ex_WMNCHitTest(TWMNCHitTest(Message));
      case TWMNCLButtonUp(Message).HitTest of
        HTCAPTION, HTSYSMENU : begin
          SetHotHT(0);
          DropSysMenu(TWMNCLButtonUp(Message).XCursor, TWMNCLButtonUp(Message).YCursor);
        end
      end;
      Exit;
    end;
    WM_NCLBUTTONUP, WM_LBUTTONUP: begin
      if (BorderForm <> nil) and (TWMNCLButtonDown(Message).HitTest = HTTRANSPARENT)
        then TWMNCLButtonDown(Message).HitTest := BorderForm.Ex_WMNCHitTest(TWMNCHitTest(Message));
      Ac_WMLButtonUp(Message);
      Exit;
    end;
    WM_NCLBUTTONDBLCLK : begin
      case TWMNCHitMessage(Message).HitTest of
        HTSYSMENU : SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
        HTCAPTION : begin
          if EnabledMax or EnabledRestore then begin
            if IsZoomed(CtrlHandle) or IsIconic(CtrlHandle)
              then SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_RESTORE, 0)
              else SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
            SystemMenu.UpdateItems;
          end;
          TWMNCHitMessage(Message).HitTest := 0;
        end;
      end;
      Exit;
    end;

    WM_SETFOCUS : begin
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      RedrawWindow(GetActiveWindow, nil, 0, RDW_FRAME or RDW_ALLCHILDREN or RDW_INVALIDATE or RDW_ERASE or RDW_UPDATENOW);
      Exit;
    end;

    WM_ERASEBKGND : begin
      InitCtrlData(CtrlHandle, ParentWnd, WndRect, ParentRect, WndSize, WndPos, Caption);
      if not Initialized then begin
        Initialized := True;
        Provider.InitHwndControls(CtrlHandle); // Rezerved searching of controls
      end;
      Ac_WMPaint(TWMPaint(Message));
      Message.Result := 1;
      Exit;
    end;
    WM_PAINT : begin
      if not FWMPaintForbidden then Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam) else begin
        BeginPaint(CtrlHandle, PS);
        EndPaint(CtrlHandle, PS);
        Message.Result := 0;
      end;
      Exit;
    end;
    WM_NCPAINT : if IsWindowVisible(CtrlHandle) then begin
      InitCtrlData(CtrlHandle, ParentWnd, WndRect, ParentRect, WndSize, WndPos, Caption);
      Caption := GetWndText(CtrlHandle);
      if Assigned(BorderForm) and Assigned(BorderForm.AForm) and not IsWindowVisible(BorderForm.AForm.Handle) and IsWindowVisible(CtrlHandle) and not InAnimationProcess then begin
        // First showing
        if AeroIsEnabled then begin
          UpdateRgn(Self, False); // Prevent an Aero borders showing

          BorderForm.UpdateExBordersPos(True, MaxByte);
          SetFocus(CtrlHandle);
        end
        else BorderForm.UpdateExBordersPos(False);
      end;
      Ac_WMNCPaint(Message);
      Message.Result := 1;
      Exit;
    end;

    WM_SHOWWINDOW : begin
      // Prevent of animation in Aero
      if AeroIsEnabled then SetWindowLong(CtrlHandle, GWL_EXSTYLE, GetWindowLong(CtrlHandle, GWL_EXSTYLE) or WS_EX_LAYERED);
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      if AeroIsEnabled then SetWindowLong(CtrlHandle, GWL_EXSTYLE, GetWindowLong(CtrlHandle, GWL_EXSTYLE) and not WS_EX_LAYERED);
      Exit;
    end;

    WM_WINDOWPOSCHANGED : begin
      SkinData.BGChanged := True;
      RgnChanged := True;
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      if (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos(False);
      Exit;
    end;

    WM_SIZE : begin
      SkinData.BGChanged := True;
      RgnChanged := True;
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      if not InAnimationProcess and (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos;
      RedrawWindow(CtrlHandle, nil, 0, RDW_ERASE or RDW_UPDATENOW or RDW_INVALIDATE or RDW_FRAME);
      Exit;
    end;
    WM_SETTEXT : if IsWindowVisible(CtrlHandle) then begin
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      SkinData.BGChanged := True;
      if (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos(False) else SendMessage(CtrlHandle, WM_NCPAINT, 0, 0);
      Exit;
    end;
    WM_ENABLE : if IsWindowVisible(CtrlHandle) then begin
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      SkinData.BGChanged := True;
      SendMessage(CtrlHandle, WM_NCPAINT, 0, 0);
      Exit;
    end;
    WM_NCACTIVATE : if IsWindowVisible(CtrlHandle) then begin
      SendMessage(CtrlHandle, WM_SETREDRAW, 0, 0);
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      FFormActive := (TWMActivate(Message).Active <> WA_INACTIVE);
      SendMessage(CtrlHandle, WM_SETREDRAW, 1, 0);
      Ac_WMNCActivate(Message);
      if (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos(False);
      Exit;
    end;
    1326 : begin
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      Provider.InitHwndControls(CtrlHandle); // SysListView re-init
      RedrawWindow(CtrlHandle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_UPDATENOW);
      Exit;
    end;
  end;
  inherited;
  case Message.Msg of
    WM_SYSCOMMAND : begin
      case Message.WParam of
        $F012 : begin
          UpdateWindow(CtrlHandle);
          if (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos(False);
        end;
        SC_MAXIMIZE, SC_RESTORE : begin
          if VisibleMax then CurrentHT := HTMAXBUTTON;
          SetHotHT(0);
        end;
      end;
    end;
    {WM_WINDOWPOSCHANGED, }WM_SIZING, WM_MOVE : begin
      if (BorderForm <> nil) and IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos(False);
    end;
    WM_WINDOWPOSCHANGING : if BorderForm <> nil then begin
      if (PWindowPos(Message.LParam)^.Flags and SWP_HIDEWINDOW = SWP_HIDEWINDOW)
        then InitExBorders(False)
        else if IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos(False);
    end;
  end;
end;

function TacDialogWnd.BarWidth(i: integer): integer;
begin
  if Assigned(SkinData.SkinManager.ma[i].Bmp) then begin
    Result := (SkinData.SkinManager.ma[i].Bmp.Width div 9) * 2 + TitleBtnsWidth;
  end
  else begin
    Result := WidthOfImage(SkinData.SkinManager.ma[i]) * 2 + TitleBtnsWidth;
  end;
end;

function TacDialogWnd.CaptionHeight(CheckSkin : boolean = True): integer;
begin
  Result := 0;
  if (GetWindowLong(CtrlHandle, GWL_STYLE) and WS_CAPTION = WS_CAPTION) or IsIconic(CtrlHandle) then begin
    if CheckSkin then Result := SkinTitleHeight(Self.BorderForm);
    if Result = 0 then begin
      if BorderStyle in [acbsToolWindow, acbsSizeToolWin]
        then Result := GetSystemMetrics(SM_CYSMCAPTION)
        else Result := GetSystemMetrics(SM_CYCAPTION)
    end;
  end
  else Result := 0;
end;

constructor TacDialogWnd.Create(AHandle: hwnd; ASkinData: TsCommonData; ASkinManager: TsSkinManager; const SkinSection : string; Repaint: boolean);
begin
  inherited;
  Initialized := False;
  RgnChanged := True;
  BorderStyle := acbsSingle;
  TempBmp := TBitmap.Create;
  FFormActive := True;
  FWMPaintForbidden := True;

  SystemMenu := TacSystemMenu.Create(nil);
  SystemMenu.FOwner := Self;
  SystemMenu.UpdateItems;
  SkinData.Updating := True;
  InitDwm(AHandle, True); // v6.43
  if (DefaultManager <> nil) and DefaultManager.SkinnedPopups then DefaultManager.SkinableMenus.HookPopupMenu(SystemMenu, True);
end;

destructor TacDialogWnd.Destroy;
begin
  if Assigned(Adapter) then FreeAndNil(Adapter);
  if Assigned(TitleGlyph) then FreeAndNil(TitleGlyph);
  if Assigned(TitleBG) then FreeAndNil(TitleBG);
  if Assigned(TempBmp) then FreeAndnil(TempBmp);
  FreeAndNil(SystemMenu);
  if TitleFont <> nil then FreeAndnil(TitleFont);
  KillAnimations;
  ClearGlows;
  InitExBorders(False);
  inherited;
end;

procedure TacDialogWnd.Ac_WMPaint(var Msg: TWMPaint);
var
  DC, SavedDC : hdc;
begin
  if Msg.DC = 0 then DC := GetDC(CtrlHandle) else DC := Msg.DC;
  SavedDC := SaveDC(DC);
  try
    SkinData.Updating := False;

    ExcludeControls(DC, CtrlHandle, 0, 0);

    PaintForm(DC);
  finally
    RestoreDC(DC, SavedDC);
    if Msg.DC = 0 then ReleaseDC(CtrlHandle, DC);
  end;
end;

function TacDialogWnd.EnabledClose: boolean;
begin
  Result := VisibleClose and (GetClassLong(CtrlHandle, GCL_STYLE) and CS_NOCLOSE <> CS_NOCLOSE)
end;

function TacDialogWnd.EnabledMax: boolean;
begin
  Result := VisibleMax and not IsZoomed(CtrlHandle) and (BorderStyle in [acbsSingle, acbsSizeable, acbsSizeToolWin]);
end;

function TacDialogWnd.EnabledMin: boolean;
begin
  Result := VisibleMin and not IsIconic(CtrlHandle);
end;

function TacDialogWnd.EnabledRestore: boolean;
begin
  Result := VisibleMax and (IsIconic(CtrlHandle) or IsZoomed(CtrlHandle));
end;

function TacDialogWnd.FormActive: boolean;
begin
  Result := FFormActive;
end;

function TacDialogWnd.HeaderHeight: integer;
begin
{  if GetWindowLong(CtrlHandle, GWL_STYLE) and WS_CAPTION <> WS_CAPTION
    then Result := WndSize.cy - GetClientHeight(CtrlHandle)
    else Result := WndSize.cy - GetClientHeight(CtrlHandle) - SysBorderHeight(CtrlHandle, BorderForm, False);
  if Result < 0 then Result := 0;}
  Result := CaptionHeight;
//  if IsIconic(CtrlHandle) then
  inc(Result, SysBorderHeight(CtrlHandle, BorderForm, False));
//  if BorderForm <> nil then dec(Result, SysBorderWidth(CtrlHandle, BorderForm, False));
end;

procedure TacDialogWnd.InitParams;
var
  NonClientMetrics: TNonClientMetrics;
  f : HFONT;
begin
  dwStyle := GetWindowLong(CtrlHandle, GWL_STYLE);
  dwExStyle := GetWindowLong(CtrlHandle, GWL_EXSTYLE);
  BorderStyle := acbsSizeable;
  if ((dwStyle and WS_POPUP) = WS_POPUP) and ((dwStyle and WS_CAPTION) <> WS_Caption)
    then BorderStyle := acbsNone
    else if ((dwStyle and WS_THICKFRAME) = WS_THICKFRAME) or ((dwStyle and WS_SIZEBOX) = WS_SIZEBOX)
      then BorderStyle := acbsSizeable
      else if ((dwStyle and DS_MODALFRAME) = DS_MODALFRAME) then BorderStyle := acbsDialog;
  PrepareTitleGlyph;
  UpdateIconsIndexes;
  if TitleFont <> nil then FreeAndNil(TitleFont);
  TitleFont := TFont.Create;
  NonClientMetrics.cbSize := SizeOf(NonClientMetrics);
  if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then begin
    f := CreateFontIndirect(NonClientMetrics.lfCaptionFont);
    if f <> 0 then TitleFont.Handle := f
  end;
  SetWindowLong(CtrlHandle, GWL_STYLE, GetWindowLong(CtrlHandle, GWL_STYLE) and not WS_SYSMENU);
end;

procedure TacDialogWnd.MakeTitleBG;
begin
  if TitleBG <> nil then FreeAndNil(TitleBG);
  TitleBG := TBitmap.Create;
  TitleBG.Width := SkinData.FCacheBmp.Width;
  TitleBG.Height := CaptionHeight + SysBorderHeight(CtrlHandle, BorderForm);
  TitleBG.PixelFormat := pf24bit;
  BitBlt(TitleBG.Canvas.Handle, 0, 0, TitleBG.Width, TitleBG.Height, SkinData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

function TacDialogWnd.OffsetX: integer;
var
  i : integer;
begin
  Result := (GetWindowWidth(CtrlHandle) - GetClientWidth(CtrlHandle)) div 2;
  if (BorderForm <> nil) then begin
    i := DiffBorder(BorderForm);
    inc(Result, ShadowSize.Left + i)// + SysBorderWidth(CtrlHandle, BorderForm, False)) //else begin
  end
end;

function TacDialogWnd.OffsetY: integer;
begin
  Result := GetWindowHeight(CtrlHandle) - GetClientHeight(CtrlHandle) - SysBorderWidth(CtrlHandle, BorderForm, False) * integer(CaptionHeight <> 0);
  if (BorderForm <> nil) then inc(Result, ShadowSize.Top + DiffTitle(BorderForm));// + 1);
end;

procedure TacDialogWnd.PaintAll;
var
  i, TitleIndex : integer;
  x, w, h, y, fHeight, fWidth, fCaptHeight, ChangedIndex : integer;
  s : acString;
  r, rForm : TRect;
  ci : TCacheInfo;
  Iconic, exBorders : boolean;
  ShadowSize : TRect;
  ts : TSize;
  P, Src : PRGBAArray;
  SavedTitle : TBitmap;
  procedure PaintTitle;
  begin
    if (CaptionHeight <> 0) then begin // Paint title
      if not exBorders then begin
        TitleIndex := SkinData.SkinManager.GetSkinIndex(s_FormTitle);
        if SkinData.SkinManager.IsValidSkinIndex(TitleIndex) then begin
          if Iconic
            then PaintItem(TitleIndex, s_FormTitle, ci, True, integer(FormActive), Rect(rForm.Left, rForm.Top, rForm.Right, rForm.Bottom), Point(0, 0), SkinData.FCacheBmp, SkinData.SkinManager)
            else PaintItem(TitleIndex, s_FormTitle, ci, True, integer(FormActive), Rect(rForm.Left, rForm.Top, rForm.Right, fCaptHeight), Point(0, 0), SkinData.FCacheBmp, SkinData.SkinManager);
        end;
      end;
      DrawAppIcon(Self); // Draw app icon
    end;
    if (CaptionHeight <> 0) then begin
      // Out the title text
      SkinData.FCacheBmp.Canvas.Font.Handle := acGetTitleFont;// Assign(TitleFont);
      SkinData.FCacheBmp.Canvas.Font.Style := SkinData.FCacheBmp.Canvas.Font.Style + [fsBold];
      SkinData.FCacheBmp.Canvas.Font.Height := GetCaptionFontSize;
      R := Rect(SysBorderWidth(CtrlHandle, BorderForm) + integer(TitleIcon <> 0) * WidthOf(IconRect) + 4 + SkinData.SkinManager.SkinData.BILeftMargin + ShadowSize.Left,
                2 + {SysBorderHeight(False) + }ShadowSize.Top, rForm.Right - TitleBtnsWidth - 6 - ShadowSize.Right, fCaptHeight);

      if ExBorders then OffsetRect(R, 0, SkinData.SkinManager.SkinData.ExCenterOffs);

      if not IsRectEmpty(R) then begin
        s := Caption;
{$IFDEF TNTUNICODE}
        GetTextExtentPoint32W(SkinData.FCacheBmp.Canvas.Handle, PWideChar(s), Length(s), ts);
{$ELSE}
        GetTextExtentPoint32(SkinData.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(SkinData.FCacheBmp.Canvas, PacChar(s), True, R,
          {GetStringFlags(Form, FCaptionAlignment) or} DT_END_ELLIPSIS or DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX,
          SkinData.SkinManager.GetSkinIndex(s_FormTitle), FormActive, SkinData.SkinManager);
      end;
    end;
  end;
begin
  InitCtrlData(CtrlHandle, ParentWnd, WndRect, ParentRect, WndSize, WndPos, Caption);

  fHeight := WndSize.cy;
  if BorderForm <> nil then begin
    ShadowSize := BorderForm.ShadowSize;
    i := DiffTitle(BorderForm);
    inc(fHeight, DiffBorder(BorderForm) + i + ShadowSize.Top + ShadowSize.Bottom);
  end
  else ShadowSize := Rect(0, 0, 0, 0);
  fWidth := WndSize.cx;
  Iconic := IsIconic(CtrlHandle);
  if BorderForm <> nil then begin
    if not Iconic then inc(fWidth, 2 * DiffBorder(Self.BorderForm) + ShadowSize.Left + ShadowSize.Right);
  end;

  with SkinData do if FCacheBmp = nil then begin // If first loading
    if BorderForm <> nil then FCacheBmp := CreateBmp32(fWidth, fHeight) else FCacheBmp := CreateBmp24(fWidth, fHeight);
  end;

  fCaptHeight := CaptionHeight + SysBorderHeight(CtrlHandle, 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 SkinData.BGChanged then begin
    begin
      RgnChanged := True;
      ci.Ready := False;
      SkinData.FCacheBmp.Width := fWidth;
      SkinData.FCacheBmp.Height := fHeight;

      if SkinData.SkinManager.IsValidSkinIndex(SkinData.SkinIndex) then begin
        // Paint body
        exBorders := (BorderForm <> nil) and (SkinData.SkinManager.SkinData.ExDrawMode = 1);
        if exBorders
          then PaintItemBG(SkinData.SkinIndex, SkinData.SkinSection, EmptyCI, integer(FormActive), rForm, Point(0, 0), SkinData.FCacheBmp, SkinData.SkinManager)
          else PaintItem(SkinData, EmptyCI, False, integer(FormActive), rForm, Point(0, 0), SkinData.FCacheBmp, False);
        ci := MakeCacheInfo(SkinData.FCacheBmp, OffsetX, OffsetY); // Prepare cache info

        if not exBorders then PaintTitle;

        if BorderForm <> nil then begin // Paint shadow of form if required
          // Fill alphachannel
          h := SkinData.FCacheBmp.Height - ShadowSize.Bottom - 1;
          w := SkinData.FCacheBmp.Width - ShadowSize.Right - 1;
          for y := ShadowSize.Top to h do begin
            p := SkinData.FCacheBmp.ScanLine[y];
            for x := ShadowSize.Left to w do p[x].A := $FF;
          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(Self.SkinData.FCacheBmp, BorderForm.ShadowTemplate, Rect(0, 0, fWidth, fHeight),
                  Rect(0, 0, BorderForm.ShadowTemplate.Width, BorderForm.ShadowTemplate.Height),
                  Rect(ma[ChangedIndex].WL, ma[ChangedIndex].WT, ma[ChangedIndex].WR, 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, Self.SkinData.FCacheBmp.Canvas.Handle, 0, 0, SRCCOPY);

              PaintTitle;

              h := min(Self.SkinData.FCacheBmp.Height, SavedTitle.Height) - 1;
              w := SavedTitle.Width - 1;
              for y := 0 to h do begin // Must be optimized
                Src := SavedTitle.ScanLine[y];
                P := Self.SkinData.FCacheBmp.ScanLine[y];
                for x := 0 to w do if (Src[x].C <> P[x].C) then P[X].A := MaxByte;
              end;
              SavedTitle.Free;
            end
            else begin
              PaintControlByTemplate(SkinData.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 := SkinData.SkinManager.gd[TitleIndex].BorderIndex;
              if SkinData.SkinManager.IsValidImgIndex(TitleIndex) then begin // If title mask exists
                x := SkinData.SkinManager.MaskWidthRight(TitleIndex);
                // LeftTop
                R := Rect(ShadowSize.Left, ShadowSize.Top, ShadowSize.Left + SkinData.SkinManager.MaskWidthLeft(TitleIndex),
                          ShadowSize.Top + SkinData.SkinManager.MaskWidthTop(TitleIndex));
                FillTransPixels32(SkinData.FCacheBmp, BorderForm.ShadowTemplate, R, ShadowSize.TopLeft, TitleIndex, SkinData.SkinManager, HTTOPLEFT);
                // RightTop
                R := Rect(SkinData.FCacheBmp.Width - ShadowSize.Right - x, ShadowSize.Top, SkinData.FCacheBmp.Width - ShadowSize.Right,
                          ShadowSize.Top + SkinData.SkinManager.MaskWidthTop(TitleIndex));
                FillTransPixels32(SkinData.FCacheBmp, BorderForm.ShadowTemplate, R,
                  Point(BorderForm.ShadowTemplate.Width - ShadowSize.Right - x, ShadowSize.Top), TitleIndex, SkinData.SkinManager, HTTOPRIGHT);
              end
              else begin
                x := SkinData.SkinManager.MaskWidthRight(SkinData.BorderIndex);
                // LeftTop
                R := Rect(ShadowSize.Left, ShadowSize.Top, ShadowSize.Left + min(SkinData.SkinManager.MaskWidthLeft(SkinData.BorderIndex), 8), ShadowSize.Top + min(SkinData.SkinManager.MaskWidthTop(SkinData.BorderIndex), 8));
                FillTransPixels32(SkinData.FCacheBmp, BorderForm.ShadowTemplate, R, ShadowSize.TopLeft, SkinData.BorderIndex, SkinData.SkinManager, HTTOPLEFT);
                // RightTop
                R := Rect(SkinData.FCacheBmp.Width - ShadowSize.Right - x,  ShadowSize.Top, SkinData.FCacheBmp.Width - ShadowSize.Right,
                          ShadowSize.Top + SkinData.SkinManager.MaskWidthTop(SkinData.BorderIndex));
                FillTransPixels32(SkinData.FCacheBmp, BorderForm.ShadowTemplate, R, Point(BorderForm.ShadowTemplate.Width - ShadowSize.Right - x, ShadowSize.Top), SkinData.BorderIndex, SkinData.SkinManager, HTTOPRIGHT);
              end;
              y := SkinData.SkinManager.MaskWidthBottom(SkinData.BorderIndex);
              x := SkinData.SkinManager.MaskWidthRight(SkinData.BorderIndex);

              // LeftBottom
              R := Rect(ShadowSize.Left, SkinData.FCacheBmp.Height - ShadowSize.Bottom - y, ShadowSize.Left + SkinData.SkinManager.MaskWidthLeft(SkinData.BorderIndex),
                        SkinData.FCacheBmp.Height - ShadowSize.Bottom);
              FillTransPixels32(SkinData.FCacheBmp, BorderForm.ShadowTemplate, R, Point(ShadowSize.Left, BorderForm.ShadowTemplate.Height - ShadowSize.Bottom - y), SkinData.BorderIndex, SkinData.SkinManager, HTBOTTOMLEFT);
              // RightBottom
              R := Rect(SkinData.FCacheBmp.Width - ShadowSize.Right - x, SkinData.FCacheBmp.Height - ShadowSize.Bottom - y,
                        SkinData.FCacheBmp.Width - ShadowSize.Right, SkinData.FCacheBmp.Height - ShadowSize.Bottom);
              FillTransPixels32(SkinData.FCacheBmp, BorderForm.ShadowTemplate, R,
                Point(BorderForm.ShadowTemplate.Width - ShadowSize.Right - x, BorderForm.ShadowTemplate.Height - ShadowSize.Bottom - y), SkinData.BorderIndex, SkinData.SkinManager, HTBOTTOMRIGHT);
            end;
          end;
        end;
        // Save caption
        if IsBorderUnchanged(SkinData.BorderIndex, SkinData.SkinManager) and ((TitleBG = nil) or (TitleBG.Width <> fWidth)) then MakeTitleBG;
        if (CaptionHeight <> 0) then begin
//          SaveBGForBtns(True);
          // Paint buttons
          PaintBorderIcons;
        end;
      end;
    end;
    SkinData.BGChanged := False;
  end;
end;

procedure TacDialogWnd.PaintBorderIcons;
var
  i, b, Offset : integer;
  BigButtons : integer;

  procedure PaintButton(var Btn : TsCaptionButton; var Index : integer; SkinIndex : integer; BtnEnabled : boolean; UserBtn : TsTitleButton = nil);
  var
    w : integer;
  begin
    w := SysButtonWidth(Btn);
    Btn.Rect.Left := Btn.Rect.Right - w;
    if Btn.HaveAlignment { If not user button and not small } and (SkinData.SkinManager.SkinData.BIVAlign = 1) { Top } then begin
      Btn.Rect.Top := ShadowSize.Top;
      if (BorderForm <> nil) and IsZoomed(CtrlHandle) then inc(Btn.Rect.Top, 3 {4 - 1});
      Btn.Rect.Bottom := Btn.Rect.Top + ButtonHeight(Btn.ImageIndex);
    end
    else begin
      Btn.Rect.Top := (CaptionHeight - ButtonHeight(Btn.ImageIndex) + SysBorderHeight(CtrlHandle, BorderForm)) div 2 + ShadowSize.Top;
      if (BorderForm <> nil) and IsZoomed(CtrlHandle) then inc(Btn.Rect.Top, SysBorderWidth(CtrlHandle, BorderForm, False) div 2);
      if (BorderForm <> nil) and (SkinData.SkinManager.SkinData.ExDrawMode = 1) then inc(Btn.Rect.Top, SkinData.SkinManager.SkinData.ExCenterOffs);
      Btn.Rect.Bottom := Btn.Rect.Top + ButtonHeight(Btn.ImageIndex);

    end;
    if SkinIndex > -1 then DrawSkinGlyph(SkinData.FCacheBmp, Point(Btn.Rect.Left, Btn.Rect.Top),
      Btn.State, 1 + integer(not boolean(FormActive) or not BtnEnabled), SkinData.SkinManager.ma[SkinIndex], MakeCacheInfo(SkinData.FCacheBmp));
    inc(Index);
  end;
begin

  b := 1;
  BigButtons := integer((BorderStyle in [acbsSingle, acbsSizeable]) or (SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconClose) = ButtonClose.ImageIndex));
  Offset := SkinData.FCacheBmp.Width {- SkinData.SkinManager.SkinData.BISpacing} - SkinData.SkinManager.SkinData.BIRightMargin - ShadowSize.Right;
  dec(Offset, SysBorderWidth(CtrlHandle, BorderForm));
  if (dwStyle and WS_SYSMENU = WS_SYSMENU) then begin // Accommodation of a buttons in a special order...
    if SkinData.SkinManager.IsValidImgIndex(ButtonClose.ImageIndex) then begin
      ButtonClose.Rect.Right := Offset;
      PaintButton(ButtonClose, b, ButtonClose.ImageIndex, EnabledClose);
//      Offset := ButtonClose.Rect.Left;
      Offset := ButtonClose.Rect.Left - BigButtons * SkinData.SkinManager.SkinData.BISpacing;
    end;
    if VisibleMax then begin
      if not IsZoomed(CtrlHandle) then begin
        if SkinData.SkinManager.IsValidImgIndex(ButtonMax.ImageIndex) then begin
          ButtonMax.Rect.Right := Offset;
          PaintButton(ButtonMax, b, ButtonMax.ImageIndex, EnabledMax);
//          Offset := ButtonMax.Rect.Left;
          Offset := ButtonMax.Rect.Left - BigButtons * SkinData.SkinManager.SkinData.BISpacing;
        end;
      end
      else begin
        i := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_BorderIconNormalize);
        if i < 0 then i := SkinData.SkinManager.GetMaskIndex(SkinData.SkinIndex, SkinData.SkinSection, s_BorderIconNormalize); // For compatibility
        if i > -1 then begin
          ButtonMax.Rect.Right := Offset;
          PaintButton(ButtonMax, b, i, EnabledRestore);
          Offset := ButtonMax.Rect.Left - BigButtons * SkinData.SkinManager.SkinData.BISpacing;;
        end;
      end;
    end;
    if VisibleMin then begin
      if IsIconic(CtrlHandle) then begin // If form is minimized then changing to Normalize
        i := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGLobalInfo, s_GlobalInfo, s_BorderIconNormalize);
        if i < 0 then i := SkinData.SkinManager.GetMaskIndex(SkinData.SkinIndex, SkinData.SkinSection, s_BorderIconNormalize);
        if SkinData.SkinManager.IsValidImgIndex(i) then begin
          ButtonMin.Rect.Right := Offset;
          PaintButton(ButtonMin, b, i, EnabledRestore); // For compatibility
          Offset := ButtonMin.Rect.Left - BigButtons * SkinData.SkinManager.SkinData.BISpacing;;
        end;
      end
      else begin
        if SkinData.SkinManager.IsValidImgIndex(ButtonMin.ImageIndex) then begin
          ButtonMin.Rect.Right := Offset;
          PaintButton(ButtonMin, b, ButtonMin.ImageIndex, EnabledMin);
          Offset := ButtonMin.Rect.Left - BigButtons * SkinData.SkinManager.SkinData.BISpacing;;
        end;
      end;
    end;
    if VisibleHelp then begin
      if SkinData.SkinManager.IsValidImgIndex(ButtonHelp.ImageIndex) then begin
        ButtonHelp.Rect.Right := Offset;
        PaintButton(ButtonHelp, b, ButtonHelp.Imageindex, True);
      end;
    end;
  end;
end;

procedure TacDialogWnd.PaintForm(var DC: hdc; SendUpdated : boolean = True);
begin
  if SkinData.BGChanged then PaintAll;
  BitBlt(DC, 0, 0, WndSize.cx, WndSize.cy,
         SkinData.FCacheBmp.Canvas.Handle, SysBorderWidth(CtrlHandle, BorderForm) + ShadowSize.Left, HeaderHeight + ShadowSize.Top {- 4 * integer(BorderForm <> nil)}, SRCCOPY);
  SetParentUpdated(CtrlHandle);
end;

procedure TacDialogWnd.PrepareTitleGlyph;
var
  SmallIcon: HIcon;
  cx, cy: Integer;
  Bmp : TBitmap;
begin
  Bmp := TBitmap.Create;
  cx := GetSystemMetrics(SM_CXSMICON);
  cy := GetSystemMetrics(SM_CYSMICON);
  Bmp.Width := cx;
  Bmp.Height := cy;
  Bmp.Canvas.Brush.Color := clFuchsia;
  TitleIcon := hIcon(SendMessage(CtrlHandle, WM_GETICON, ICON_SMALL, 0));
  if TitleIcon = 0 then TitleIcon := hIcon(SendMessage(CtrlHandle, WM_GETICON, ICON_BIG, 0));

  if TitleIcon <> 0 then begin
    SmallIcon := Windows.CopyImage(TitleIcon, IMAGE_ICON, cx, cy, LR_COPYFROMRESOURCE);
    DrawIconEx(Bmp.Canvas.Handle, 0, 0, SmallIcon, cx, cy, 0, 0, DI_NORMAL);
    DestroyIcon(SmallIcon);
    if TitleGlyph = nil then TitleGlyph := TBitmap.Create;
    TitleGlyph.Assign(Bmp);
  end;
  FreeAndNil(Bmp);
end;

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

function TacDialogWnd.TitleBtnsWidth: integer;
begin
  Result := 0;
  if VisibleClose then begin
    inc(Result, SysButtonWidth(ButtonClose));
    if VisibleMax then inc(Result, SysButtonWidth(ButtonMax));
    if VisibleMin then inc(Result, SysButtonWidth(ButtonMin));
    if VisibleHelp then inc(Result, SysButtonWidth(ButtonHelp));
  end;
end;

function TacDialogWnd.VisibleClose: boolean;
begin
  Result := dwStyle and WS_SYSMENU = WS_SYSMENU
end;

function TacDialogWnd.VisibleHelp: boolean;
begin
  Result := dwExStyle and WS_EX_CONTEXTHELP = WS_EX_CONTEXTHELP
end;

function TacDialogWnd.VisibleMax: boolean;
begin
  Result := dwStyle and WS_MAXIMIZEBOX = WS_MAXIMIZEBOX

end;

function TacDialogWnd.VisibleMin: boolean;
begin
  Result := dwStyle and WS_MINIMIZEBOX = WS_MINIMIZEBOX
end;

procedure TacDialogWnd.Ac_WMNCPaint(var Message: TMessage);
var
  DC, SavedDC : hdc;
begin
  Provider.InitHwndControls(CtrlHandle);

  if not RgnChanging and RgnChanged and ((BorderStyle <> acbsNone) or (dwStyle and WS_SIZEBOX = WS_SIZEBOX)) then begin
    FillArOR(Self);
    RgnChanged := False;
    if not RgnChanging then UpdateRgn(Self);
  end;

  DC := GetWindowDC(CtrlHandle);
  SavedDC := SaveDC(DC);
  try
    PaintCaption(DC);
  finally
    RestoreDC(DC, SavedDC);
    ReleaseDC(CtrlHandle, DC);
  end;
  SkinData.Updating := False;

  RgnChanging := False;
end;

procedure TacDialogWnd.PaintCaption(const DC: hdc);
var
  h, bw, bh : integer;
  sSize : TRect;
begin
  if BorderForm <> nil then Exit;
  h := SysBorderHeight(CtrlHandle, BorderForm) + CaptionHeight;
  if IsIconic(CtrlHandle) then inc(h);
  if SkinData.BGChanged then begin
    PaintAll;
    SkinData.BGChanged := False;
    SkinData.Updating := False;
  end;

  sSize := ShadowSize;

  bw := SysBorderWidth(CtrlHandle, BorderForm);
  bh := SysBorderHeight(CtrlHandle, BorderForm);
  // Title update
  BitBlt(DC, 0, 0, WndSize.cx, HeaderHeight, SkinData.FCacheBmp.Canvas.Handle, sSize.Left, sSize.Top, SRCCOPY);
  // Left border update
  BitBlt(DC, 0, h, bw, WndSize.cy, SkinData.FCacheBmp.Canvas.Handle, sSize.Left, h + sSize.Top, SRCCOPY);
  // Bottom border update
  BitBlt(DC, bw, WndSize.cy - bh, WndSize.cx - bw, bh, SkinData.FCacheBmp.Canvas.Handle, SysBorderwidth(CtrlHandle, BorderForm) + sSize.Left, WndSize.cy - SysBorderWidth(CtrlHandle, BorderForm) - sSize.Bottom, SRCCOPY);
  // Right border update
  BitBlt(DC, WndSize.cx - bw, h, bw, WndSize.cy, SkinData.FCacheBmp.Canvas.Handle, SkinData.FCacheBmp.Width - bw, h, SRCCOPY);
end;

function TacDialogWnd.BorderHeight: integer;
begin
  Result := SysBorderHeight(CtrlHandle, BorderForm)
end;

procedure TacDialogWnd.UpdateIconsIndexes;
begin
  if SkinData.SkinManager.IsValidSkinIndex(SkinData.SkinManager.ConstData.IndexGlobalInfo) then with SkinData.SkinManager do begin
    ButtonMin.HitCode := HTMINBUTTON;
    ButtonMax.HitCode := HTMAXBUTTON;
    ButtonClose.HitCode := HTCLOSE;
    if BorderStyle in [acbsSingle, acbsSizeable] 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;
      ButtonMax.HaveAlignment   := True;
      ButtonClose.HaveAlignment := True;
      ButtonHelp.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;
      ButtonMax.HaveAlignment   := False;
      ButtonClose.HaveAlignment := False;
      ButtonHelp.HaveAlignment  := False;

      if ButtonClose.ImageIndex < 0 then begin // If small buttons are not defined in skin
        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;
      end;
    end;
  end;
end;

function TacDialogWnd.ButtonHeight(Index: integer): integer;
begin
  if SkinData.SkinManager.IsValidImgIndex(Index) then begin
    if SkinData.SkinManager.ma[Index].Bmp = nil then Result := HeightOfImage(SkinData.SkinManager.ma[Index]) else Result := SkinData.SkinManager.ma[Index].Bmp.Height div 2;
  end
  else Result := 21;
end;

procedure TacDialogWnd.AdapterRemove;
begin
  SendToAdapter(MakeMessage(SM_ALPHACMD, MakeWParam(0, AC_REMOVESKIN), LongWord(SkinData.SkinManager), 0));
  FreeAndNil(Adapter);
end;

procedure TacDialogWnd.SendToAdapter(Message: TMessage);
begin
  if Assigned(Adapter) then Adapter.WndProc(Message)
end;

function TacDialogWnd.VisibleRestore: boolean;
begin
  Result := not (BorderStyle in [acbsDialog, acbsNone, acbsSizeToolWin, acbsToolWindow]) and VisibleClose;
end;

procedure TacDialogWnd.Ac_WMNCHitTest(var Message: TMessage);
begin
  Message.Result := HTProcess(TWMNCHitTest(Message));
  case Message.Result of
    Windows.HTCAPTION, Windows.HTNOWHERE : begin
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
      SetHotHT(0);
    end;
  end;
end;

function TacDialogWnd.HTProcess(var Message: TWMNCHitTest): integer;
const
  BtnSpacing = 1;
var
  p : TPoint;
  cy1, cy2 : integer;
  SysBtnCount, BtnIndex : integer;
  b : boolean;
  function GetBtnIndex(x : integer) : integer;
  var
    c : integer;
  begin
    Result := 0;
    c := 0;
    if VisibleClose then begin
      inc(c);
      if Between(x, ButtonClose.Rect.Left, ButtonClose.Rect.Right) then begin
        Result := c;
        Exit;
      end;
      if VisibleMax then begin
        inc(c);
        if Between(x, ButtonMax.Rect.Left, ButtonMax.Rect.Right) then begin
          Result := c;
          Exit;
        end;
      end;
      if VisibleMin then begin
        inc(c);
        if Between(x, ButtonMin.Rect.Left, ButtonMin.Rect.Right) then begin
          Result := c;
          Exit;
        end;
      end;
      if VisibleHelp then begin
        inc(c);
        if Between(x, ButtonHelp.Rect.Left, ButtonHelp.Rect.Right) then begin
          Result := c;
          Exit;
        end;
      end;
    end;
  end;
begin
  p := CursorToPoint(Message.XPos, Message.YPos);
  cy1 := (CaptionHeight - ButtonHeight(ButtonClose.ImageIndex) + SysBorderHeight(CtrlHandle, BorderForm)) div 2;
  cy2 := cy1 + ButtonHeight(ButtonClose.ImageIndex);

  if Between(p.y, cy1, cy2) then begin // If in buttons
    if Between(p.x, SysBorderWidth(CtrlHandle, BorderForm), SysBorderWidth(CtrlHandle, BorderForm) + GetSystemMetrics(SM_CXSMICON)) // If system menu icon
      then begin SetHotHT(HTSYSMENU); Result := HTSYSMENU; Exit; end;
    // Title button?
    SysBtnCount := 0;
    if VisibleClose then inc(SysBtnCount);
    if VisibleMax then inc(SysBtnCount);
    if VisibleMin or IsIconic(CtrlHandle) then inc(SysBtnCount);
    if VisibleHelp then inc(SysBtnCount);
    BtnIndex := GetBtnIndex(p.x);

    if (BtnIndex > 0) and (BtnIndex <= SysBtnCount) then begin // If system button
      case BtnIndex of
        1 : if VisibleClose then begin
          SetHotHT(HTCLOSE); Result := HTCLOSE; Exit;
        end;
        2 : begin
          if VisibleMax then begin
            if (EnabledMax or EnabledRestore) then begin
              SetHotHT(HTMAXBUTTON); Result := HTMAXBUTTON; Exit;
            end
            else begin
              SetHotHT(HTCAPTION); Result := HTCAPTION; Exit;
            end;
          end
          else if VisibleMin or IsIconic(CtrlHandle) then begin
            if EnabledMin then begin
              SetHotHT(HTMINBUTTON); Result := HTMINBUTTON; Exit;
            end
            else begin
              SetHotHT(HTCAPTION); Result := HTCAPTION; Exit;
            end;
          end
          else if VisibleHelp then begin
            SetHotHT(HTHELP); Result := HTHELP; EXIT;
          end;
        end;
        3 : begin
          if (VisibleMin) or IsIconic(CtrlHandle) then begin
            if not IsIconic(CtrlHandle) then begin
              if EnabledMin then begin
                SetHotHT(HTMINBUTTON); Result := HTMINBUTTON; Exit;
              end
              else begin
                SetHotHT(HTCAPTION); Result := HTCAPTION; Exit;
              end;
            end
            else begin
              SetHotHT(HTMINBUTTON); Result := HTMINBUTTON; Exit;
            end;
          end
          else if VisibleHelp then begin
            SetHotHT(HTHELP); Result := HTHELP; EXIT;
          end;
        end;
        4 : if VisibleHelp and VisibleMax then begin
          SetHotHT(HTHELP); Result := HTHELP; EXIT;
        end;
      end;
    end
    else begin
      Result := HTCAPTION;
      Exit;
    end;
  end;
  b := IsZoomed(CtrlHandle);
  if b and AboveBorder(Message) then Result := HTTRANSPARENT else Result := Message.Result;
end;

procedure TacDialogWnd.SetHotHT(i: integer; Repaint: boolean);
begin
  if (CurrentHT = i) 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;
    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;
  end;
  biClicked := False;
  if Repaint then RepaintButton(CurrentHT);
end;

function TacDialogWnd.CursorToPoint(x, y: integer): TPoint;
begin
  GetWindowRect(CtrlHandle, WndRect);
  Result := WndRect.TopLeft;
  Result.x := x - Result.x;
  Result.y := y - Result.y;
end;

function TacDialogWnd.AboveBorder(Message: TWMNCHitTest): boolean;
var
  p : TPoint;
begin
  p := CursorToPoint(Message.XPos, Message.YPos);
  Result := not PtInRect(Rect(2, 2, WndSize.cx - 4, WndSize.cy - 4), p);
  if Result then SetHotHT(0);
end;

procedure TacDialogWnd.RepaintButton(i: integer);
var
  DC, SavedDC : hdc;
  CurButton : PsCaptionButton;
  cx, ind, x, y : integer;
  BtnDisabled : boolean;
  R : TRect;
begin
  CurButton := nil;
  case i of
    HTCLOSE      : CurButton := @ButtonClose;
    HTMAXBUTTON  : CurButton := @ButtonMax;
    HTMINBUTTON  : CurButton := @ButtonMin;
    HTHELP       : CurButton := @ButtonHelp;
  end;
  if not SkinData.SkinManager.AllowGlowing then begin 
    if (CurButton <> nil) and (CurButton^.State <> -1) then begin
      BtnDisabled := False;
      if CurButton^.Rect.Left <= GetSystemMetrics(SM_CXSMICON) + SysBorderWidth(CtrlHandle, BorderForm) then Exit;
      cx := SkinData.FCacheBmp.Width - CurButton^.Rect.Left;
      BitBlt(SkinData.FCacheBmp.Canvas.Handle, // Restore a button BG
             CurButton^.Rect.Left, CurButton^.Rect.Top, SysButtonwidth(CurButton^), ButtonHeight(CurButton^.ImageIndex),
             TempBmp.Canvas.Handle, TempBmp.Width - cx, CurButton^.Rect.Top, SRCCOPY);
      // if Max btn and form is maximized then Norm btn
      if (i = HTMAXBUTTON) and IsZoomed(CtrlHandle) then ind := SkinData.SkinManager.GetMaskIndex(SkinData.SkinIndex, s_GlobalInfo, s_BorderIconNormalize)
      else if IsIconic(CtrlHandle) then begin
        case i of
          HTMINBUTTON : begin
            ind := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconNormalize);
            if ind < 0 then ind := SkinData.SkinManager.GetMaskIndex(SkinData.SkinIndex, SkinData.SkinSection, s_BorderIconNormalize); // For compatibility
          end;
          HTMAXBUTTON : begin
            ind := SkinData.SkinManager.GetMaskIndex(SkinData.SkinManager.ConstData.IndexGlobalInfo, s_GlobalInfo, s_BorderIconMaximize);
            if ind < 0 then ind := SkinData.SkinManager.GetMaskIndex(SkinData.SkinIndex, SkinData.SkinSection, s_BorderIconMaximize); // For compatibility
            if not EnabledMax then BtnDisabled := True;
          end
          else ind := CurButton^.ImageIndex;
        end
      end else ind := CurButton^.ImageIndex;
      if SkinData.SkinManager.IsValidImgIndex(ind) then begin // Drawing of the button from skin
        if i < HTUDBTN // if not user defined
          then DrawSkinGlyph(SkinData.FCacheBmp, Point(CurButton^.Rect.Left, CurButton^.Rect.Top),
                 CurButton^.State, 1 + integer(not boolean(FormActive) or BtnDisabled) * integer(not (CurButton^.State > 0) or BtnDisabled), SkinData.SkinManager.ma[ind], MakeCacheInfo(SkinData.FCacheBmp));
      end;
      // Copying to form
      DC := GetWindowDC(CtrlHandle);
      SavedDC := SaveDC(DC);
      try
        BitBlt(DC, CurButton^.Rect.Left, CurButton^.Rect.Top, WidthOf(CurButton^.Rect), HeightOf(CurButton^.Rect),
          SkinData.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 := SkinData.SkinManager.SkinData.BICloseGlow;
            HTMAXBUTTON  : x := SkinData.SkinManager.SkinData.BIMaxGlow;
            HTMINBUTTON  : x := SkinData.SkinManager.SkinData.BIMinGlow;
          end;
          if x > 0 then begin
            case i of
              HTCLOSE      : y := SkinData.SkinManager.SkinData.BICloseGlowMargin;
              HTMAXBUTTON  : y := SkinData.SkinManager.SkinData.BIMaxGlowMargin;
              HTMINBUTTON  : y := SkinData.SkinManager.SkinData.BIMinGlowMargin;
            end;
            GetWindowRect(CtrlHandle, 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 then
              CurButton^.GlowID := ShowGlow(R, R, s_GlobalInfo, SkinData.SkinManager.ma[CurButton.ImageIndex].PropertyName + s_Glow, y, 255, CtrlHandle, SkinData.SkinManager);
          end;
        end
        else if CurButton^.GlowID <> -1 then begin
          HideGlow(CurButton^.GlowID);
          CurButton^.GlowID := -1;
        end;
      finally
        RestoreDC(DC, SavedDC);
        ReleaseDC(CtrlHandle, 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, nil, Self);
        2 : StartSBAnimation(CurButton, CurButton^.State, 1, CurButton^.State <> 0, nil, Self);
        else StartSBAnimation(CurButton, CurButton^.State, 10, False, nil, Self);
      end;
    end
  end;
end;

procedure TacDialogWnd.Ac_WMNCLButtonDown(var Message: TWMNCLButtonDown);
begin
  case TWMNCLButtonDown(Message).HitTest of
    HTCLOSE, HTMAXBUTTON, HTMINBUTTON, HTHELP, HTCHILDCLOSE..HTCHILDMIN : begin
      SetPressedHT(TWMNCLButtonDown(Message).HitTest);
    end;
    HTSYSMENU : begin
      if True{SkinData.SkinManager.SkinnedPopups} then begin
        SetHotHT(0);
        DropSysMenu(WndRect.Left + SysBorderWidth(CtrlHandle, BorderForm), WndRect.Top + BorderHeight + GetSystemMetrics(SM_CYSMICON));
      end
      else Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, TMessage(Message).WParam, TMessage(Message).LParam);
    end
    else begin
      if IsIconic(CtrlHandle) then begin
        SendMessage(CtrlHandle, WM_SYSCOMMAND, $F012, 0);
      end
      else begin
        SetHotHT(0);
        if not IsZoomed(CtrlHandle) or (CursorToPoint(0, TWMNCLButtonDown(Message).YCursor).y > SysBorderHeight(CtrlHandle, BorderForm) + CaptionHeight) then begin
          Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, TMessage(Message).WParam, TMessage(Message).LParam);
        end
        else if not FormActive then SetFocus(CtrlHandle); 
      end;
    end
  end;
end;

procedure TacDialogWnd.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;
    end;
    RepaintButton(CurrentHT);
  end;
  CurrentHT := i;
  case CurrentHT of
    HTCLOSE : ButtonClose.State := 2;
    HTMAXBUTTON : if EnabledMax or (IsZoomed(CtrlHandle) and EnabledRestore) then ButtonMax.State := 2;

    HTMINBUTTON : ButtonMin.State := 2;
    HTHELP : ButtonHelp.State := 2;
  end;
  biClicked := True;
  RepaintButton(CurrentHT);
end;

procedure TacDialogWnd.DropSysMenu(x, y: integer);
begin
  SystemMenu.WindowHandle := CtrlHandle;
  SystemMenu.Popup(x, y);
end;

procedure TacDialogWnd.Ac_WMLButtonUp(var Message: TMessage);
var
  p : TPoint;
begin
  case TWMNCHitMessage(Message).HitTest of
    HTCLOSE : if biClicked then begin
      ButtonClose.State := 0;
      SetHotHT(0);
      SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
    end;
    HTMAXBUTTON : if not IsIconic(CtrlHandle) or (IsIconic(CtrlHandle) and EnabledMax) then begin
      if biClicked then begin
        SetHotHT(0);
        if IsZoomed(CtrlHandle) then begin
          SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
        end
        else begin
          SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
        end;
        Application.ProcessMessages;
        SystemMenu.UpdateItems;
      end
      else SetHotHT(0);
    end;
    HTMINBUTTON : if biClicked then begin
      p := CursorToPoint(TWMMouse(Message).XPos, TWMMouse(Message).YPos);
      if PtInRect(ButtonMin.Rect, p) then begin
        SetHotHT(0);
        if IsIconic(CtrlHandle) then begin
          SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
        end
        else SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
      end
      else Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
    end else SetHotHT(0);
    HTHELP : if biClicked then begin
      SendMessage(CtrlHandle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
      SetHotHT(0);
      SystemMenu.UpdateItems;
      SendMessage(CtrlHandle, WM_NCPAINT, 0, 0);
    end else SetHotHT(0);
    // MDI child buttons
    else begin
      Message.Result := CallWindowProc(OldProc, CtrlHandle, Message.Msg, Message.WParam, Message.LParam);
    end
  end;
  TWMNCHitMessage(Message).HitTest := 0;
end;

procedure TacDialogWnd.Ac_WMNCActivate(var Message: TMessage);
begin
  SkinData.BGChanged := True;
  RedrawWindow(CtrlHandle, nil, 0, RDW_ALLCHILDREN or RDW_FRAME or RDW_INVALIDATE);
end;

procedure TacDialogWnd.Ac_WMActivate(var Message: TMessage);
begin
  SkinData.BGChanged := True;
  RedrawWindow(CtrlHandle, nil, 0, RDW_ALLCHILDREN or RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
  if Assigned(SystemMenu) then SystemMenu.UpdateItems;
end;

procedure TacDialogWnd.Ac_DrawStaticItem(var Message: TWMDrawItem); 
begin
  SetBkMode(TWMDrawItem(Message).DrawItemStruct.hDC, TRANSPARENT);
end;

procedure TacDialogWnd.InitExBorders(const Active: boolean);
begin
  if Active and not (csDesigning in SkinData.SkinManager.ComponentState) then begin
    if BorderForm = nil then begin
      BorderForm := TacBorderForm.Create(Self);

//      UpdateRgn(Self, False);

      BorderForm.SkinData := SkinData;
      SkinData.BGChanged := True;
      if SkinData.FCacheBmp <> nil then SkinData.FCacheBmp.PixelFormat := pf32bit;
      if IsWindowVisible(CtrlHandle) then BorderForm.UpdateExBordersPos;
    end;
  end
  else begin
    if BorderForm <> nil then FreeAndNil(BorderForm);
    if SkinData.FCacheBmp <> nil then SkinData.FCacheBmp.PixelFormat := pf24bit;
  end;
end;

function TacDialogWnd.IconRect: TRect;
begin
  Result.Left := SysBorderWidth(CtrlHandle, BorderForm) + SkinData.SkinManager.SkinData.BILeftMargin;
  if BorderForm <> nil then inc(Result.Left, BorderForm.ShadowSize.Left);
  Result.Right := Result.Left + GetSystemMetrics(SM_CXSMICON);
  Result.Top := (CaptionHeight + SysBorderHeight(CtrlHandle, BorderForm) - GetSystemMetrics(SM_CYSMICON)) div 2;
  if BorderForm <> nil then inc(Result.Top, BorderForm.ShadowSize.Top);
  Result.Bottom := Result.Top + GetSystemMetrics(SM_CYSMICON);

  if (BorderForm <> nil) and (SkinData.SkinManager.SkinData.ExDrawMode = 1) then OffsetRect(Result, 0, SkinData.SkinManager.SkinData.ExCenterOffs);
end;

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

procedure TacDialogWnd.KillAnimations;
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;
end;

{ TacSystemMenu }

procedure TacSystemMenu.CloseClick(Sender: TObject);
begin
  Sendmessage(FOwner.CtrlHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
end;

constructor TacSystemMenu.Create(AOwner: TComponent);
  function CreateSystemItem(const Caption, Name : string; EventProc : TNotifyEvent) : TMenuItem; begin
    Result := TMenuItem.Create(Self);
    Result.Caption := Caption;
    Result.OnClick := EventProc;
    Result.Name := Name;
  end;
begin
  inherited Create(AOwner);

  ItemRestore := CreateSystemItem(LoadStr(s_RestoreStr), 'miRestore', RestoreClick); Self.Items.Add(ItemRestore);
  ItemMove := CreateSystemItem(LoadStr(s_MoveStr), 'miMove', MoveClick);             Self.Items.Add(ItemMove);
  ItemSize := CreateSystemItem(LoadStr(s_SizeStr), 'miSize', SizeClick);             Self.Items.Add(ItemSize);
  ItemMinimize := CreateSystemItem(LoadStr(s_MinimizeStr), 'miMinimize', MinClick);  Self.Items.Add(ItemMinimize);
  ItemMaximize := CreateSystemItem(LoadStr(s_MaximizeStr), 'miMaximize', MaxClick);  Self.Items.Add(ItemMaximize);

  Self.Items.InsertNewLineAfter(ItemMaximize);

  ItemClose := CreateSystemItem(LoadStr(s_CloseStr), 'miClose', CloseClick);         Self.Items.Add(ItemClose);
  ItemClose.ShortCut := scAlt + 115;
end;

function TacSystemMenu.EnabledMax: boolean;
begin
  Result := False;
end;

function TacSystemMenu.EnabledMin: boolean;
begin
  Result := False;
end;

function TacSystemMenu.EnabledMove: boolean;
begin
  Result := not IsZoomed(FOwner.CtrlHandle);
end;

function TacSystemMenu.EnabledRestore: boolean;
begin
  Result := False;
end;

function TacSystemMenu.EnabledSize: boolean;
begin
  Result := (FOwner.BorderStyle <> acbsSingle) and not IsIconic(FOwner.CtrlHandle);
end;

procedure TacSystemMenu.MaxClick(Sender: TObject);
begin
  Sendmessage(FOwner.CtrlHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  UpdateItems;
end;

procedure TacSystemMenu.MinClick(Sender: TObject);
begin
  SendMessage(FOwner.CtrlHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);    
end;

procedure TacSystemMenu.MoveClick(Sender: TObject);
begin
  Sendmessage(FOwner.CtrlHandle, WM_SYSCOMMAND, SC_MOVE, 0);
end;

procedure TacSystemMenu.RestoreClick(Sender: TObject);
begin
  Sendmessage(FOwner.CtrlHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
  UpdateItems;
end;

procedure TacSystemMenu.SizeClick(Sender: TObject);
begin
  Sendmessage(FOwner.CtrlHandle, WM_SYSCOMMAND, SC_SIZE, 0);
end;

procedure TacSystemMenu.UpdateItems;
begin
  ItemRestore.Visible  := FOwner.VisibleRestore;
  ItemMove.Visible     := True;
  ItemSize.Visible     := VisibleSize;
  ItemMinimize.Visible := FOwner.VisibleMin;
  ItemMaximize.Visible := FOwner.VisibleMax;
  ItemClose.Visible    := FOwner.VisibleClose;

  ItemRestore.Enabled  := FOwner.EnabledRestore;
  ItemMove.Enabled     := EnabledMove;
  ItemSize.Enabled     := EnabledSize;
  ItemMinimize.Enabled := FOwner.EnabledMin;
  ItemMaximize.Enabled := FOwner.EnabledMax;
  ItemClose.Enabled    := True;
end;

function TacSystemMenu.VisibleClose: boolean;
begin
  Result := FOwner.dwStyle and WS_SYSMENU = WS_SYSMENU
end;

function TacSystemMenu.VisibleMax: boolean;
begin
  Result := False;
end;

function TacSystemMenu.VisibleMin: boolean;
begin
  Result := False;
end;

function TacSystemMenu.VisibleSize: boolean;
begin
  Result := not (FOwner.BorderStyle in [acbsDialog, acbsNone, acbsToolWindow]);
end;

procedure ClearMnuArray;
begin
{$IFNDEF NOMNUHOOK}
  SetLength(MnuArray, 0);
{$ENDIF}
end;

procedure CleanArray;
var
  i: integer;
  ap: TacProvider;
begin
  if acSupportedList <> nil then for i := 0 to acSupportedList.Count - 1 do begin
    ap := TacProvider(acSupportedList[i]);
    if (ap <> nil) and (ap.ListSW <> nil) and ap.ListSW.Destroyed then begin
      ap.ListSW.Destroyed := False;
      FreeAndNil(ap);
      acSupportedList[i] := nil;
    end;
  end;
end;

initialization

finalization
  ClearMnuArray;
  if acSupportedList <> nil then begin
    while acSupportedList.Count > 0 do begin
      TObject(acSupportedList[0]).Free;
      acSupportedList.Delete(0);
    end;
    FreeAndNil(acSupportedList);
  end;

end.
