www.pudn.com > VCLSkin.4.81.rar > WinSkinDlg.pas


unit WinSkinDlg; 
 
{$I Compilers.Inc} 
 
{$WARNINGS OFF} 
{$HINTS OFF} 
{$RANGECHECKS OFF} 
 
interface 
 
uses windows,Messages,SysUtils,Classes,Graphics,WinSkinMenu, 
  forms,ExtCtrls; 
 
const 
   skin_Creating=0; 
   skin_Active=1; 
   skin_uninstall=2; 
   skin_change=3; 
   skin_Destory=4; 
   skin_Updating=5; 
   skin_Deleted=6; 
   skin_update=7; 
 
   m_popup=0; 
   m_systemmenu=2; 
   m_menuitem=1; 
 
Type 
  TSkinThread = class(TObject) 
  public 
    hook:HHook; 
    ThreadID:integer; 
  end; 
 
  TSBAPI1=function(ahwnd:hwnd): HResult; stdcall; 
  TSBAPI2= function() :HResult; stdcall; 
 
  TSkinManage = class(Tobject) 
  protected 
    Timer : TTimer; 
    SBLib :Thandle; 
    pinitApp,pUninitApp:TSBAPI2; 
    pinitSB,pUninitSb:TSBAPI1; 
    HookCallback,WndCallBack,WndCallRet : HHOOK; 
    //function  FindSkinForm(aHwnd:THandle):boolean; 
    function  FindSkinForm(aHwnd:THandle):dword; 
    procedure DeleteAllForms; 
    function AddMenu(aHwnd:THandle):boolean; 
    function  FindSkinMenu(aHwnd:THandle):boolean; 
    function  DeleteMenu(aHwnd:THandle):boolean; 
    procedure DeleteAllMenus; 
    function  FindTForm(ahwnd:Thandle):Tform; 
    procedure OnTimer(Sender: TObject); 
    function NestedForm(ahwnd:Thandle):boolean; 
    procedure FindSkindata(var adata:pointer;ahwnd:Thandle); 
    function OnBeforeSkin(ahwnd:Thandle;aname:string):boolean; 
    procedure DeleteAllThreads; 
    procedure ActiveForm(aform:Tform); 
    procedure DeleteDeleted; 
    function IsDllForm(ahwnd:Thandle):boolean; 
    procedure DeleteAllSub; 
    procedure DeleteSubForm(amode:integer); 
//    function AddForm(aHwnd:THandle):boolean; 
     procedure WndProc(var Msg: TMessage); 
  public 
    Flist:Tlist; 
    Mlist:Tlist; 
    Dlist:Tlist; 
    Threadlist:Tlist; 
    sublist:Tlist; 
    active:boolean; 
    skinchildform:boolean; 
    state:integer; 
    menutype:integer; 
    menuactive:boolean; 
    MDIMax:boolean; 
    WMSetDraw:boolean; 
    clienthwnd:Thandle; 
    MDIForm : Tform; 
    action:integer; 
    UpdateData:pointer; 
    SBinstall :boolean; 
    MainData: pointer; 
    mode:integer; 
    handle : HWND; 
    lpara : integer; 
    mmgr:TSkinmanage; 
    constructor Create(amode:integer=0); 
    destructor Destroy; override; 
    procedure InstallHook; 
    function AddForm(aHwnd:THandle):boolean; 
//    function AddMDIForm(atform:Tform):boolean; 
    function DeleteForm(aHwnd:THandle):boolean; 
    function  GetMenuBg(amenu:Hmenu):Tbitmap; 
    procedure UpdateSkinMenu(amenu:Hmenu); 
    procedure  FindPopupMenu(amenu:Hmenu); 
    procedure  SetMDIMax(b:boolean); 
    procedure  SetMDIMax2(b:boolean); 
    procedure  SetCaption(b:boolean); 
    function  GetMDIChildNum:integer; 
    procedure SetAction(acode:integer;Interval:integer=250); 
    procedure AddSkinData(adata: Pointer); 
    procedure RemoveSkinData(adata: Pointer); 
    procedure DeleteSysbtn; 
    procedure InstallThread(aThreadID:integer); 
    procedure UnInstallThread(aThreadID:integer); 
    function initsb(ahwnd:Thandle):boolean; 
    function Uninitsb(ahwnd:Thandle):boolean; 
    procedure SetPopMenu; 
    procedure DeleteForm2(aHwnd:THandle); 
    procedure DeleteForm3; 
    procedure AssignData(adata: Pointer); 
    procedure SetHMenu(hmenu:Thandle); 
    procedure DeleteSub(p:Pointer); 
  end; 
//var HookCallback,WndCallBack,WndCallRet : HHOOK; 
var  SkinManager:TSkinManage; 
     RM_GetObjectInstance: DWORD; 
     ControlAtom: TAtom; 
     PropName:string; 
     myinstance:dword; 
 
function SkinHookCallback(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; 
function SkinHookCallRet(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT;stdcall; 
function SkinHookCBT(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; 
function SkinHookCBT2(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; 
 
implementation 
 
uses winskinform ,WinSkinData,menus,winsubclass; 
 
 
function SkinHookCallRet(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; 
var pwp:PCWPRETSTRUCT; 
   s:string; 
begin 
   if code= HC_ACTION then begin 
     pwp:=PCWPRETSTRUCT (lparam); 
     case pwp.message of 
        WM_DRAWITEM: begin 
//              SkinManager.WMDRAWITEM(PDrawItemStruct(pwp.lparam)); 
           end; 
     end; 
   end; 
   result:=CallNextHookEx( SkinManager.WndCallRet, Code, wParam, lParam ); 
end; 
 
function SkinHookCallback(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; 
var pwp:PCWPSTRUCT; 
   s:string; 
   msg:Tmessage; 
begin 
   if code= HC_ACTION then begin 
     pwp:=PCWPSTRUCT(lparam); 
{     if skincanlog then begin 
        msg.msg:=pwp.message; 
        msg.wparam:=pwp.wparam; 
        msg.lparam:=pwp.lparam; 
        skinaddlog('Hook:'+msgtostr(msg)); 
     end; } 
     case pwp.message of 
        WM_CREATE:SkinManager.AddMenu(pwp.hwnd); 
        WM_DESTROY,WM_NCDESTROY:SkinManager.DeleteMenu(pwp.hwnd); 
        WM_INITMENU: begin 
//              skinaddlog('WH_CALLWNDPROC : WM_INITMENU'); 
              skinmanager.FindPopupMenu(pwp^.wparam); 
           end; 
{        WM_DRAWITEM: begin 
              skinaddlog('WH_CALLWNDPROC : WM_DRAWITEM'); 
           end;} 
     end; 
   end; 
   result:=CallNextHookEx( SkinManager.WndCallback, Code, wParam, lParam ); 
end; 
 
function SkinHookCBT(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; 
var s:string; 
   hwnd:Thandle; 
   ptr:^CBT_CREATEWND; 
   sf: dword; 
   sd:Tskindata; 
begin 
//message box WM_ACTIVATE TMessageForm 
//Dlg ****WM_ACTIVATE #32770 WA_ACTIVE 
   if (code>=0) {and skinmanager.active} then begin 
      case code of 
        HCBT_ACTIVATE :begin 
           if skinmanager.state=skin_creating then 
              inc(skinmanager.state); 
           hwnd := Thandle(wParam); 
           if  SkinManager.addform(hwnd) then begin 
           end; 
         end; 
         HCBT_DESTROYWND : begin 
           hwnd := Thandle(wParam); 
           SkinManager.DeleteMenu(hwnd); 
           //if SkinManager.deleteform(hwnd) then begin 
           //end; 
         end; 
         HCBT_CREATEWND : begin 
           hwnd := Thandle(wParam); 
           ptr:=pointer(lparam); 
           s:= getwindowclassname(hwnd); 
//           skinAddlog(format('***HCBT_CREATEWND %s %1x,%1x',[s,hwnd,ptr^.lpcs^.hwndParent])); 
           if (s='ScrollBar') and ((ptr^.lpcs^.style and sbs_sizegrip)>0) then begin 
              s:= getwindowclassname(ptr^.lpcs^.hwndParent); 
              sf:= SkinManager.findskinform(ptr^.lpcs^.hwndParent); 
              if (sf>0)  then begin  //     and (s='#32770') 
                  Twinskinform(sf).addcontrolh(hwnd); 
//                  skinAddlog(format('*****Scrollbar %s %1x,%1x',[s,hwnd,ptr^.lpcs^.hwndParent])); 
//                  result:=10; 
//                  exit; 
              end; 
           end ; 
           if (ptr^.lpcs^.style and ws_child)=0 then begin 
               //skinAddlog(format('***Form Creater %s %1x (%1d,%1d)',[s,hwnd,ptr^.lpcs^.cx,ptr^.lpcs^.cy])); 
               s:= getwindowclassname(hwnd); 
               if (s='#32768') and (skinmanager.mmgr=nil) then 
                 SkinManager.AddMenu(hwnd)  ; 
//               sd:=SkinManager.maindata; 
//               sd.DoDebug(s); 
{               if (sd<>nil) and assigned(sd.OnNewform) then 
                  try 
                    sd.OnNewform(sd,hwnd,s); 
                  except 
                  end;       } 
           end; 
           if (ptr^.lpcs^.dwExStyle and ws_ex_mdichild)>0 then begin 
              SkinManager.addform(hwnd); 
           end; 
         end; 
{         HCBT_MINMAX : begin 
           hwnd := Thandle(wParam); 
           if lparam = SW_MAXIMIZE then 
               skinAddlog(format('***Form MAXIMIZE %1x ',[hwnd])); 
         end;} 
      end;//endcase 
   end else begin 
      if (code=HCBT_ACTIVATE) and (skinmanager.state=skin_creating) then 
              inc(skinmanager.state); 
   end; 
   result:=CallNextHookEx( SkinManager.HookCallback, Code, wParam, lParam ); 
end; 
 
function SkinHookCBT2(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; 
var s:string; 
   hwnd:Thandle; 
   ptr:^CBT_CREATEWND; 
begin 
//message box WM_ACTIVATE TMessageForm 
//Dlg ****WM_ACTIVATE #32770 WA_ACTIVE 
   if code>=0 then begin 
      case code of 
        HCBT_ACTIVATE :begin 
           if skinmanager.state=skin_creating then 
              inc(skinmanager.state); 
           hwnd := Thandle(wParam); 
             if  SkinManager.addform(hwnd) then begin 
//               s:='****HCBT_ACTIVATE '+s; 
//               skinAddlog(s); 
             end; 
         end; 
         HCBT_DESTROYWND : begin 
           hwnd := Thandle(wParam); 
           SkinManager.DeleteMenu(hwnd); 
           if SkinManager.deleteform(hwnd) then begin 
           end; 
         end; 
         HCBT_CREATEWND : begin 
           hwnd := Thandle(wParam); 
           ptr:=pointer(lparam); 
           s:= getwindowclassname(hwnd); 
//           skinAddlog(format('***HCBT_CREATEWND %s %1x,%1x',[s,hwnd,ptr^.lpcs^.hwndParent])); 
           if (s='ScrollBar') and (SkinManager.findskinform(ptr^.lpcs^.hwndParent)>0) then begin 
//              skinAddlog(format('***Scrollbar %s %1x,%1x',[s,hwnd,ptr^.lpcs^.hwndParent])); 
              result:=10; 
              exit; 
           end ; 
           if s='#32768' then 
              SkinManager.AddMenu(hwnd); //don't create scrollbar 
         end; 
      end;//endcase 
   end; 
   result:=CallNextHookEx( SkinManager.HookCallback, Code, wParam, lParam ); 
end; 
 
constructor TSkinManage.Create(amode:integer=0); 
begin 
   inherited create(); 
   if amode=0 then begin 
      flist:=Tlist.create; 
      Mlist:=Tlist.create; 
      dlist:=Tlist.create; 
      threadlist:=Tlist.create; 
      sublist:=Tlist.create; 
      mode:=0; 
   end else 
      mode := HInstance; 
   active:=false; 
   menuactive:=false; 
   MDIMax:=false; 
   menutype:=0; 
   mmgr:=nil; 
   Timer := TTimer.create(nil); 
   timer.Interval:=100; 
   timer.Ontimer:=Ontimer; 
   timer.enabled:=false; 
   SBinstall :=false; 
   skinchildform:=false; 
   wmsetdraw:=false;//true; 
   maindata:=nil; 
   state:=skin_creating; 
//   Handle := Classes.AllocateHWnd(WndProc); 
   SBLib:=0; 
//   SBLib := LoadLibrary('C:\MyFile\MySkin\ARTICLE\coolsb_src\coolsb2\Release\coolsb2.dll'); 
//   SBLib := LoadLibrary('coolsb2.dll'); 
   pinitapp:=nil; 
   sbinstall:=false; 
   if SBLib<>0 then begin 
    pinitApp:=GetProcAddress(SBLib,'CoolSB_InitializeApp'); 
    pUninitApp:= GetProcAddress(SBLib,'CoolSB_UninitializeApp'); 
    pinitSB:=GetProcAddress(SBLib,'InitializeCoolSB'); 
    pUninitSb:=GetProcAddress(SBLib,'UninitializeCoolSB'); 
   end; 
   if @pinitapp<>nil then 
       SBinstall := boolean(pinitapp); 
//   installhook; 
end; 
 
destructor TSkinManage.Destroy; 
begin 
   state:=skin_destory; 
   active:=false; 
   Timer.free; 
   if @pUninitapp<>nil then  pUninitapp; 
   if (sblib<>0) then 
       FreeLibrary(sblib); 
   if mode=0 then begin 
       DeleteAllThreads; 
       if (sublist.Count>0) or (flist.Count>0) then 
           deleteallforms; 
      if flist<>nil then flist.free; 
      deleteallmenus; 
      dlist.free; 
      deleteallsub; 
   end else if HookCallback<>0 then begin 
     if assigned(mmgr) then begin 
        mmgr.DeleteSub(self); 
        mmgr.DeleteSubForm(mode); 
     end; 
      //AssignData(nil); 
   end; 
//   Classes.DeallocateHWnd(Handle); 
   if HookCallback<>0 then 
     UnhookWindowsHookEx( HookCallback ); 
   inherited destroy; 
end; 
 
procedure TSkinManage.InstallHook; 
var dwThreadID:DWORD; 
begin 
   winversion:=GetVersion(); 
//   skinaddlog(format('Windows Version %1x',[winversion])); 
//   skinaddlog(format('Windows Version %1d %1d',[Win32MajorVersion,Win32MinorVersion])); 
//   skinaddlog(format('winversion %1x',[winversion])); 
   dwThreadID := GetCurrentThreadId; 
//   WndCallback :=SetWindowsHookEx( WH_CALLWNDPROC,SkinHookCallback,0,dwThreadID); 
//   WndCallRet :=SetWindowsHookEx( WH_CALLWNDPROCRET,SkinHookCallRet,0,dwThreadID); 
   HookCallback :=SetWindowsHookEx( WH_CBT,SkinHookCBT,0,dwThreadID); 
//   skinaddlog(format('ThreadId %1x',[dwThreadId])); 
//   skinaddlog(format('HookCallback %1x',[HookCallback])); 
end; 
 
procedure TSkinManage.InstallThread(aThreadID:integer); 
var obj:TSkinThread; 
     b: boolean; 
     i:integer; 
begin 
   b:=false; 
   for i:= 0 to threadlist.count-1 do begin 
      obj:= TSkinThread(threadlist[i]); 
      if obj.threadID=aThreadID then begin 
        b:=true; 
        break; 
      end; 
   end; 
   if b then exit; 
   obj:=TSkinThread.create; 
   obj.threadID:=aThreadID; 
   obj.hook :=SetWindowsHookEx( WH_CBT,SkinHookCBT2,0,aThreadID); 
   threadlist.add(obj); 
end; 
 
procedure TSkinManage.UnInstallThread(aThreadID:integer); 
var obj:TSkinThread; 
    i:integer; 
begin 
   for i:= 0 to threadlist.count-1 do begin 
      obj:= TSkinThread(threadlist[i]); 
      if obj.threadID=aThreadID then begin 
        UnhookWindowsHookEx( obj.hook); 
        threadlist.delete(i); 
        break; 
      end; 
   end; 
end; 
 
procedure TSkinManage.DeleteAllThreads; 
var obj:TSkinThread; 
    i:integer; 
begin 
   for i:= 0 to threadlist.count-1 do begin 
      obj:= TSkinThread(threadlist[i]); 
      UnhookWindowsHookEx( obj.Hook ); 
      obj.free; 
   end; 
   threadlist.clear; 
   threadlist.free; 
end; 
 
 
function Tskinmanage.nestedform(ahwnd:Thandle):boolean; 
var  style:longword; 
     s:string; 
     phwnd:Thandle; 
begin 
   result:=false; 
   Style := GetWindowLong( ahwnd, GWL_STYLE ); 
   if (style and ws_child)=0 then exit; 
   Style := GetWindowLong( ahwnd, GWL_EXSTYLE ); 
   if (style and ws_ex_mdichild)>0 then exit; 
   phwnd:=getparent(ahwnd); 
   s:=lowercase(getwindowclassname(phwnd)); 
   if s='mdiclient' then exit; 
   result:=true; 
end; 
 
procedure Tskinmanage.FindSkindata(var adata:pointer;ahwnd:Thandle); 
var s:string; 
 
  function FindOnlyThisForm:boolean; 
  var i:integer; 
      sd:Tskindata; 
      sf:Tform; 
  begin 
     result:=false; 
     for i:= 0 to dlist.count-1 do begin 
         sd:=Tskindata(dlist.items[i]); 
         sf:=Tform(sd.owner); 
         if (sd.skinformtype=sfOnlyThisForm) and (sf.handle=ahwnd) then begin 
             adata:=sd; 
             result:=true; 
         end; 
     end; 
  end; 
 
  function FindData(atype:TSkinFormType):boolean; 
  var i:integer; 
      sd:Tskindata; 
  begin 
     result:=false; 
     for i:= 0 to dlist.count-1 do begin 
         sd:=Tskindata(dlist.items[i]); 
         if (sd.skinformtype=atype) then begin 
             adata:=sd; 
             result:=true; 
         end; 
     end; 
  end; 
 
begin 
   if FindOnlyThisForm then exit; 
   s:=lowercase(getwindowclassname(ahwnd)); 
   if ((s='tmessageform') or (s='#32770')) and finddata(sfDialog) then exit; 
   if finddata(sfMainform) then exit; 
   if dlist.count>0 then adata:=dlist.items[0] 
   else adata:=nil; 
end; 
 
function TSkinManage.OnBeforeSkin(ahwnd:Thandle;aname:string):boolean; 
var b:boolean; 
    i:integer; 
    sd:Tskindata; 
    s:string; 
    dwstyle:Dword; 
begin 
   b:=true; 
   if maindata<>nil then begin 
     if not (xoPreview in TSkindata(maindata).Options) then begin 
        s:= lowercase(aname); 
        if (pos('preview',s)>0) then b:=false; 
     end; 
     dwstyle := GetWindowLong( ahwnd, GWL_STYLE ); 
     //file download dialog 
     if (aname='#32770') and ((dwstyle and DS_SETFOREGROUND)>0) then b:=false; 
     TSkindata(maindata).DoFormSkin(ahwnd,aname,b); 
   end; 
{   for i:= 0 to dlist.count-1 do begin 
       sd:=Tskindata(dlist.items[i]); 
       if (sd.skinformtype=sfMainform) then begin 
            sd.DoFormSkin(aname,b); 
            break; 
       end; 
   end;} 
   result:=b; 
end; 
 
procedure TSkinManage.ActiveForm(aform:Tform); 
var dwstyle:dword; 
    b:boolean; 
begin 
    dwstyle := GetWindowLong( aform.handle, GWL_STYLE ); 
    b:= (dwstyle and ws_child)>0;   //child 
    //if aform.formstyle=fsmdichild then b:=false;//mdichild 
    if not aform.Visible then b:=true; 
    if not b then addform(aform.handle); 
end; 
 
function TSkinManage.AddForm(aHwnd:THandle):boolean; 
var aform:TWinskinform; 
    atform:TForm; 
    r:Trect; 
    s:string; 
    aptr:pointer; 
    adata:Tskindata; 
    isskin:integer; 
    dw:dword; 
    b:boolean; 
begin 
   result:=false; 
   if not active then exit; 
 
   DeleteDeleted; 
 
   isskin:=sendmessage(ahwnd,CN_IsSkined,0,0); 
// {$IFDEF demo} 
//    atform:=findtform(ahwnd); 
//    if atform<>nil then 
//      setproperty(atform,'Caption',' '); 
// {$endif} 
 
   if isskin=1 then exit; 
 
   if findskinform(ahwnd)<>0 then exit; 
 
   atform:=findtform(ahwnd); 
   if (not skinchildform) and nestedform(ahwnd) then exit; 
 
//   b:= (s='#32770') {or (s='TMessageForm')}; 
   s:=getwindowclassname(ahwnd); 
   dw:=GetWindowLong(ahwnd,GWL_HINSTANCE); 
   if (atform=nil) and (dw<>myinstance) and (s<>'#32770') then exit; 
//   if (not b) and (atform=nil) and (not isdllform(ahwnd)) then exit; 
//   if not isdllform(ahwnd) then exit; 
//   TSkindata(maindata).DoDebug(s); 
 
   getwindowrect(ahwnd,r); 
   offsetrect(r,-r.left,-r.top); 
   dw:=GetWindowLong(ahwnd, GWL_EXSTYLE); 
   if (r.right*r.bottom=0) and ((dw and ws_ex_mdichild)=0) then exit; 
   if (atform<>nil) and (atform.tag=99) then exit; 
 
   if pos('TcxPopupEditPopupWindow',s)>0 then exit; 
   if pos('TTERenderWindow',s)>0 then exit; 
   if s='TApplication' then exit; 
//   if s='TQRStandardPreview' then exit; //quickreport preview form 
   if not OnBeforeSkin(ahwnd,s) then exit; 
 
   FindSkindata(aptr,ahwnd); 
   if aptr=nil then exit; 
 
   adata:=Tskindata(aptr); 
   if adata.empty then exit; 
 
   if atform<>nil then begin 
      aform:=Twinskinform.create(atform); 
      aform.hwnd:=ahwnd; 
      aform.mode:=mode; 
      aform.formclass:=s; 
      aform.InitTform(adata,atform); 
   end else begin 
      aform:=Twinskinform.create(nil); 
      aform.hwnd:=ahwnd; 
      aform.mode:=mode; 
      aform.formclass:=s; 
      aform.initDlg(adata); 
   end; 
 
   flist.add(aform); 
//   LockWindowUpdate(ahwnd); 
   postMessage(ahwnd, CN_NewForm, 0, 1000); 
   result:=true; 
end; 
 
{function TSkinManage.AddMDIForm(atform:Tform):boolean; 
var aform:TWinskinform; 
    r:Trect; 
    s:string; 
    aptr:pointer; 
    adata:Tskindata; 
    isskin:integer; 
    ahwnd:Thandle; 
begin 
   result:=false; 
   if not active then exit; 
   DeleteDeleted; 
   ahwnd:=atform.handle; 
   isskin:=sendmessage(ahwnd,CN_IsSkined,0,0); 
   if isskin=1 then exit; 
 
   if not OnBeforeSkin(s) then exit; 
 
   FindSkindata(aptr,ahwnd); 
   if aptr=nil then exit; 
 
   adata:=Tskindata(aptr); 
   if adata.empty then exit; 
 
   if atform<>nil then begin 
      aform:=Twinskinform.create(atform); 
      aform.hwnd:=ahwnd; 
      aform.InitTform(adata,atform); 
      flist.add(aform); 
      postMessage(ahwnd, CN_NewForm, 0, 1000); 
      result:=true; 
   end; 
end;    } 
 
function TSkinManage.DeleteForm(aHwnd:THandle):boolean; 
var i: integer; 
    sf :TWinSkinform; 
begin 
   if (state=skin_destory) then exit; 
   result:=false; 
   for i:=0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.hwnd=ahwnd then begin 
         if sf.FForm = nil then exit; 
         sf.Skinstate:=skin_Destory; 
         sf.unsubclass; 
         flist.delete(i); 
         sf.free; 
         sf:=nil; 
         result:=true; 
         break; 
      end; 
   end; 
end; 
 
procedure TSkinManage.DeleteForm2(aHwnd:THandle); 
var i: integer; 
    sf :TWinSkinform; 
begin 
   if (state=skin_destory) then exit; 
   for i:=0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.hwnd=ahwnd then begin 
         flist.delete(i); 
         break; 
      end; 
   end; 
end; 
 
procedure TSkinManage.DeleteDeleted; 
var i: integer; 
    sf :TWinSkinform; 
begin 
   if (state=skin_destory) then exit; 
   for i:=flist.count-1 downto 0 do begin 
      sf:=TWinSkinform(flist[i]); 
      if IsBadReadPtr(sf, InstanceSize) then begin 
         flist.delete(i); 
      end else if (sf.skinstate=skin_Deleted) and (sf.mode=mode) then begin 
         //sf.UnSubclass3; 
         flist.delete(i); 
         sf.free; 
      end; 
   end; 
end; 
 
procedure TSkinManage.DeleteAllForms; 
var i: integer; 
    sf :TWinSkinform; 
begin 
    active:=false; 
//    DeleteDeleted; 
    for i:=flist.count-1 downto 0 do begin 
        sf:=TWinSkinform(flist[i]); 
        if IsBadReadPtr(sf, InstanceSize) then continue; 
//??  remove dialog 
        if sf.mode<>mode then continue; 
        //sf.Skinstate:=skin_Destory; 
        flist.delete(i); 
        sf.unsubclass3; 
        sf.free; 
   end; 
end; 
 
procedure TSkinManage.DeleteSubForm(amode:integer); 
var i: integer; 
    sf :TWinSkinform; 
begin 
    for i:=flist.count-1 downto 0 do begin 
        sf:=TWinSkinform(flist[i]); 
        if IsBadReadPtr(sf, InstanceSize) then continue; 
        if sf.mode<>amode then continue; 
        //sf.Skinstate:=skin_Destory; 
        flist.delete(i); 
        sf.FForm.Free; 
        //sf.unsubclass3; 
        //sf.free; 
   end; 
end; 
 
procedure TSkinManage.DeleteForm3; 
var i: integer; 
    sf :TWinSkinform; 
begin 
   if (state=skin_destory) then exit; 
   for i:=flist.count-1 downto 0 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.skinstate=skin_deleted then begin 
         flist.delete(i); 
         sf.free; 
      end; 
   end; 
end; 
 
procedure TSkinManage.AddSkinData(adata: Pointer); 
begin 
   dlist.add(adata); 
   if (maindata=nil) and (TSkindata(adata).skinformtype=sfmainform) then 
    maindata:=adata; 
end; 
 
procedure TSkinManage.RemoveSkinData(adata: Pointer); 
var i:integer; 
begin 
   i:= dlist.indexof(adata); 
   if i<>-1 then begin 
     dlist[i]:=nil; 
     dlist.delete(i); 
   end; 
end; 
 
procedure TSkinManage.AssignData(adata: Pointer); 
var d:TSkinmanage; 
begin 
   if adata<>nil then begin 
      d:=TskinManage(adata); 
      flist:=d.Flist; 
      Mlist:=d.Mlist; 
      dlist:=d.Dlist; 
      threadlist:=d.Threadlist; 
      maindata:=d.MainData; 
      mmgr:=d; 
      state:=1; 
      active:=d.active; 
      //active:=false; 
      d.sublist.Add(self); 
   end else begin 
      flist:=nil; 
      Mlist:=nil; 
      dlist:=nil; 
      threadlist:=nil; 
      maindata:=nil; 
      active:=false; 
      state:=skin_destory; 
      if HookCallback<>0 then 
         UnhookWindowsHookEx( HookCallback ); 
      HookCallback:=0; 
   end; 
end; 
 
procedure TSkinManage.DeleteAllMenus; 
var i: integer; 
    sm :TWinSkinPopMenu; 
begin 
   for i:=0 to mlist.count-1 do begin 
      sm:=TWinSkinPopMenu(mlist[i]); 
      sm.free; 
   end; 
   mlist.clear; 
   mlist.free; 
   mlist:=nil; 
end; 
 
procedure TSkinManage.DeleteAllSub; 
var i: integer; 
    sm :TSkinmanage; 
begin 
   for i:=0 to sublist.count-1 do begin 
      sm:=TSkinManage(sublist[i]); 
      if not IsBadReadPtr(TSkinManage(sublist[i]), InstanceSize) then 
         sm.Assigndata(nil); 
//      sm.Assigndata(nil); 
      //sm.Free; 
   end; 
   sublist.clear; 
   sublist.free; 
   sublist:=nil; 
end; 
 
procedure TSkinManage.DeleteSub(p:Pointer); 
var i: integer; 
begin 
   for i:=0 to sublist.count-1 do begin 
      if sublist[i]=p then begin 
        sublist.delete(i); 
        break; 
      end; 
   end; 
end; 
 
procedure TSkinManage.SetPopMenu; 
var i: integer; 
    sm :TWinSkinPopMenu; 
begin 
//   i:= mlist.count; 
//   if i=0 then exit; 
   for i:=0 to mlist.count-1 do begin 
      sm:=TWinSkinPopMenu(mlist[i]); 
      sm.ownerdraw:=true; 
   end; 
end; 
 
procedure TSkinManage.SetHMenu(hmenu:Thandle); 
var i: integer; 
    sm :TWinSkinPopMenu; 
begin 
//   i:= mlist.count; 
//   if i=0 then exit; 
   for i:= mlist.count-1 downto 0 do begin 
      sm:=TWinSkinPopMenu(mlist[i]); 
      if sm.hmenu=0 then begin 
         sm.hmenu:=hmenu; 
         break; 
      end; 
   end; 
end; 
 
function  TSkinManage.FindSkinForm(aHwnd:THandle):dword; 
var i: integer; 
    sf :TWinSkinform; 
begin 
   result:=0; 
   for i:=0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.hwnd=ahwnd then begin 
         result:=dword(sf); 
         break; 
      end; 
   end; 
end; 
 
function TSkinManage.AddMenu(aHwnd:THandle):boolean; 
var amenu:TWinSkinPopMenu; 
    s:string; 
    adata:Tskindata; 
    aptr:pointer; 
    isskin:integer; 
begin 
   result:=false; 
   if not active then exit; 
   isskin:=sendmessage(ahwnd,CN_IsSkined,0,0); 
   if isskin=1 then exit; 
 
   if findskinMenu(ahwnd) then exit; 
 
   FindSkindata(aptr,ahwnd); 
   if aptr=nil then exit; 
 
   adata:=Tskindata(aptr); 
//   if (adata.empty) or (not(xcMainmenu in adata.SkinControls)) then exit; 
   if (adata.empty) then exit; 
   case menutype of 
     m_popup : if (not(xcPopupmenu in adata.SkinControls)) then exit; 
     m_menuitem : if (not(xcMainmenu in adata.SkinControls) 
          and not(xcMenuitem in adata.SkinControls)) then exit; 
     m_systemmenu: if (not(xcSystemmenu in adata.SkinControls)) then exit; 
   end; 
 
   amenu:=TWinSkinPopMenu.create; 
   amenu.InitSkin(ahwnd,adata,0); 
   Mlist.add(amenu); 
   if menuactive then amenu.ownerdraw:=true; 
end; 
 
function TSkinManage.DeleteMenu(aHwnd:THandle):boolean; 
var i: integer; 
    sm :TWinSkinPopMenu; 
begin 
   result:=false; 
//   if mlist=nil then exit; 
   if IsBadReadPtr(mlist, InstanceSize) then exit; 
   for i:=0 to mlist.count-1 do begin 
      sm:=TWinSkinPopMenu(mlist[i]); 
      if sm.hwnd=ahwnd then begin 
         sm.unsubclass; 
         mlist.delete(i); 
         sm.free; 
         result:=true; 
         break; 
      end; 
   end; 
   if mlist.count=0 then begin 
     menuactive:=false; 
         menutype:=0; 
   end; 
end; 
 
function  TSkinManage.FindSkinMenu(aHwnd:THandle):boolean; 
var i: integer; 
    sm :TWinSkinPopMenu; 
begin 
   result:=false; 
   for i:=0 to mlist.count-1 do begin 
      sm:=TWinSkinPopMenu(mlist[i]); 
      if sm.hwnd=ahwnd then begin 
         result:=true; 
         break; 
      end; 
   end; 
end; 
 
procedure TSkinManage.UpdateSkinMenu(amenu:Hmenu); 
var i: integer; 
    mh:Thandle; 
begin 
{   mh:=FindWindowex(0,0,'#32768',nil); 
   if (mh<>0) and (mh<>smenu.hwnd) then begin 
      smenu.InitSkin(mh,GSkinData,amenu); 
   end;} 
end; 
 
function  TSkinManage.GetMenuBg(amenu:Hmenu):Tbitmap; 
var i: integer; 
begin 
   result:=nil; 
   for I:= 0 to mlist.count-1 do 
      if TWinSkinPopMenu(mlist[i]).hmenu=amenu then begin 
         result:=TWinSkinPopMenu(mlist[i]).menubg; 
         break; 
      end; 
end; 
 
procedure  TSkinManage.FindPopupMenu(amenu:Hmenu); 
var i: integer; 
begin 
   for I:= 0 to PopupList.count-1 do 
      if TPopupMenu(PopupList[i]).handle=amenu then begin 
         menuactive:=true; 
         break; 
      end; 
end; 
 
procedure  TSkinManage.SetMDIMax(b:boolean); 
var i: integer; 
    sf:Twinskinform; 
    sd:TSkinData; 
begin 
   if mdimax=b then exit; 
   mdimax:=b; 
   sd:=SkinManager.maindata; 
 
   if (xoMDIChildBorder in sd.Options) then exit; 
 
   for I:= 0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.formstyle=sfsmdichild then  begin 
        if b then begin 
           if sf.crop then sf.Uncropwindow; 
           sf.EnableSysbtn(b); 
        end else begin 
          if sf.windowstate<>swsmin then begin 
            sf.windowstate:=swsnormal; 
            sf.cropwindow; 
            sf.EnableSysbtn(b); 
            if not sf.crop then sf.refresh; 
          end else sf.EnableSysbtn(true); 
        end; 
      end; 
   end; 
//   if b then skinaddlog('***** SetMdiMax True') 
//   else skinaddlog('***** SetMdiMax Flase'); 
end; 
 
procedure  TSkinManage.SetMDIMax2(b:boolean); 
var i: integer; 
    sf:Twinskinform; 
begin 
   if mdimax=b then exit; 
   mdimax:=b; 
   for I:= 0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.formstyle=sfsmdichild then  begin 
        if b then begin 
           if sf.crop then sf.Uncropwindow; 
           sf.EnableSysbtn(b); 
        end else begin 
          if sf.windowstate<>swsmin then begin 
            sf.windowstate:=swsnormal; 
            sf.cropwindow; 
            sf.EnableSysbtn(b); 
            if not sf.crop then sf.refresh; 
          end else sf.EnableSysbtn(true); 
        end; 
      end; 
   end; 
   if b then skinaddlog('***** SetMdiMax True') 
   else skinaddlog('***** SetMdiMax Flase'); 
end; 
 
procedure  TSkinManage.SetCaption(b:boolean); 
var i: integer; 
    sf:Twinskinform; 
    dwstyle:Dword; 
begin 
   for I:= 0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.formstyle=sfsmdichild then  begin 
        dwstyle := GetWindowLong( sf.hwnd, GWL_STYLE ); 
        dwstyle := dwstyle or WS_CAPTION; 
        SetWindowLong( sf.hwnd, GWL_STYLE, dwstyle ); 
      end; 
   end; 
end; 
 
function  TSkinManage.GetMDIChildNum:integer; 
var i: integer; 
    sf:Twinskinform; 
begin 
   result:=0; 
   for I:= 0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.formstyle=sfsmdichild then 
        inc(result); 
   end; 
end; 
 
{function EnumProp(ahwnd:HWND;prop:Pchar;data:Thandle):boolean;stdcall; 
var s:string; 
    p:dword; 
    buf: array[0..31] of Char; 
begin 
     //p:=GetProp(ahwnd,prop); 
//     s:=format('%4x',[data]); 
//     if pos('FF',s)=1 then exit; 
//     StrCopy(buf,prop); 
    result:=true; 
    if ATOM(prop) = dword(prop) then exit; 
 
    result:=true; 
    s:=format('%s',[prop]); 
    if pos('ControlOfs',s)=1 then begin 
//        b:=true; 
        result:=false; 
    end; 
end; } 
 
function TSkinManage.IsDllForm(ahwnd:Thandle):boolean; 
var b:boolean; 
    i:integer; 
 
   function EnumProp(ahwnd:HWND;prop:Pchar;data:Thandle):boolean;stdcall; 
   var s:string; 
       p:^integer; 
   begin 
     result:=true; 
     if ATOM(prop) = dword(prop) then exit; 
     s:=strpas(prop); 
     if pos('ControlOfs',s)=1 then begin 
        result:=false; 
     end; 
   end; 
begin 
  b:=true; 
  i:=0; 
  i:=EnumProps(ahwnd,@enumprop); 
  if i=0 then result:=false 
  else result:=true; 
end; 
 
 
function TSkinManage.FindTForm(ahwnd:Thandle):TForm; 
var i:integer; 
   aform:TForm; 
begin 
  aform:=nil; 
  for I := 0 to Screen.FormCount - 1 do  begin 
    if Screen.Forms[I].handle=ahwnd then  begin 
      aform := Screen.Forms[I]; 
      break; 
    end; 
  end; 
  if aform=nil then 
      aform:=Tform(FindControlx(ahwnd)); 
  result:=aform; 
//  Result := TForm(SendMessage(ahwnd, RM_GetObjectInstance, 0, 0)) ; 
end; 
 
procedure TSkinManage.SetAction(acode:integer;Interval:integer=250); 
var i:integer; 
    sm:Tskinmanage; 
begin 
   action:=acode; 
   timer.Interval:=interval; 
   if (state=skin_creating) then begin 
     if acode=skin_Active then active:=true 
     else if acode=skin_uninstall then active:=false; 
   end else begin 
      if mode=0 then begin 
         //other skinmanager 
         for i:=0 to sublist.count-1 do begin 
            sm:=TSkinManage(sublist[i]); 
            sm.UpdateData:=UpdateData; 
            if  acode=skin_Active  then begin 
               sm.active:=true ; 
               sm.SetAction(skin_Active,300) 
            end else if  acode=skin_change  then begin 
               //sm.SetAction(skin_change,300) 
            end else if  acode=skin_uninstall  then 
               sm.active:=false; 
         end; 
      end;    
      timer.enabled:=true; 
   end; 
end; 
 
function EnumWindow(ahwnd :HWND;lParam: LPARAM):boolean;stdcall; 
var s:string; 
    r:Trect; 
begin 
   result:=false; 
//   if (GetParent(ahwnd)= lparam) then begin 
      s:=getwindowclassname(ahwnd); 
      getwindowrect(ahwnd,r); 
//      skinaddlog(format('***enumWindow %1x,%s (%1d,%1d,%1d,%1d)', 
//             [ahwnd,s,r.left,r.top,r.right,r.bottom])); 
      result:=true; 
//   end; 
end; 
 
function EnumAddWindow(ahwnd :HWND;lParam: LPARAM):boolean;stdcall; 
var s:string; 
    r:Trect; 
begin 
   result:=true; 
   Skinmanager.addform(ahwnd); 
end; 
 
procedure TSkinManage.DeleteSysbtn; 
var i: integer; 
    sf :TWinSkinform; 
begin 
   for i:= 0 to flist.count-1 do begin 
      sf:=TWinSkinform(flist[i]); 
      if sf.fsd=updatedata then 
        sf.DeleteSysbtn; 
   end; 
end; 
 
function TSkinManage.initsb(ahwnd:Thandle):boolean; 
begin 
   result:=false; 
   if SBinstall and (@pinitsb<>nil) then 
       result := boolean(pinitsb(ahwnd)); 
end; 
 
function TSkinManage.Uninitsb(ahwnd:Thandle):boolean; 
begin 
   result:=false; 
   if SBinstall and (@pUninitsb<>nil) then 
       result := boolean(pUninitsb(ahwnd)); 
end; 
 
procedure TSkinManage.WndProc(var Msg: TMessage); 
var ahwnd:hwnd; 
    sf :TWinSkinform; 
begin 
    if (msg.Msg = CN_SkinNotify ) then begin 
        ahwnd:=msg.LParam; 
        if (msg.WParam=skin_update) then begin 
          sf := TWinSkinform(findskinform(ahwnd)); 
          if sf<>nil then begin 
             application.ProcessMessages(); 
             sleep(10); 
             sf.UnSubclass(); 
             sf.skinstate:=skin_Deleted; 
             deleteDeleted; 
             sleep(10); 
             application.ProcessMessages(); 
             AddForm(ahwnd); 
          end; 
        end; 
        msg.result:=0; 
    end  else 
    msg.Result := DefWindowProc(handle, msg.msg, msg.wParam, msg.lParam); 
end; 
 
procedure TSkinManage.OnTimer(Sender: TObject); 
var i: integer; 
    sf :TWinSkinform; 
    sd: TSkindata; 
    sm:Tskinmanage; 
    ahwnd:Thandle; 
begin 
   timer.enabled:=false; 
   if UpdateData=nil then exit; 
   sd := TSkindata(updateData); 
   if sd.SkinFormtype = sfOnlyThisForm then begin 
      case action of 
        skin_uninstall:begin 
          active:=false; 
          DeleteDeleted; 
          for i:= flist.count-1 downto 0 do begin 
             sf:=TWinSkinform(flist[i]); 
             if sf.fsd = sd then begin 
                 sf.unsubclass; 
                 sf.repaint(sf.hwnd); 
                 flist.delete(i); 
                 sf.free; 
                 break; 
             end; 
          end; 
        end; 
       skin_change:begin 
          DeleteDeleted; 
          for i:= 0 to flist.count-1 do begin 
             sf:=TWinSkinform(flist[i]); 
             if (sf.fsd = sd) then begin 
                sf.DeleteSysbtn; 
                sf.InitSkinData; 
                sf.skinchange; 
                break; 
             end; 
          end; 
        end; 
       skin_Active: begin 
         active:=true; 
         skinchildform:=true; 
//         EnumThreadWindows(GetCurrentThreadId,@EnumAddWindow,0); 
         for I := Screen.FormCount - 1 downto 0 do  begin 
              if Screen.Forms[I]=sd.Owner then begin 
                activeform(Screen.Forms[I]); 
                break; 
              end; 
         end; 
         skinchildform:=false; 
        end; 
       skin_deleted : deleteform3; 
      end;//endcase 
      sd.doskinchanged; 
      UpdateData:=nil; 
   end else begin 
   case action of 
     skin_Active: begin 
         active:=true; 
         wmsetdraw:=false; 
         skinchildform:=true; 
//         EnumThreadWindows(GetCurrentThreadId,@EnumAddWindow,0); 
         DeleteDeleted; 
         for I := Screen.FormCount - 1 downto 0 do  begin 
              ActiveForm(Screen.Forms[I]); 
         end; 
         skinchildform:=false; 
         if mode=0 then begin 
            for i:=0 to sublist.count-1 do begin 
               sm:=TSkinManage(sublist[i]); 
               sm.UpdateData:=UpdateData; 
               sm.active:=true ; 
               sm.SetAction(skin_Active,300) 
            end; 
         end; 
      end; 
      skin_uninstall:begin 
          active:=false; 
          DeleteDeleted; 
{          for i:= flist.count-1 downto 0 do begin 
             sf:=TWinSkinform(flist[i]); 
             sf.unsubclass; 
             sf.repaint(sf.hwnd); 
             flist.delete(i); 
             sf.free; 
          end;} 
          while flist.count>0 do begin 
             sf:=TWinSkinform(flist[0]); 
             sf.unsubclass; 
             sf.repaint(sf.hwnd); 
             flist.delete(0); 
             sf.free; 
          end; 
 
         if mode=0 then begin 
            for i:=0 to sublist.count-1 do begin 
               sm:=TSkinManage(sublist[i]); 
               sm.active:=false ; 
            end; 
         end; 
{          for i:= flist.count-1 downto 0 do begin 
             sf:=TWinSkinform(flist[i]); 
             sf.unsubclass; 
             sf.repaint(sf.hwnd); 
             flist.delete(i); 
             sf.free; 
          end;} 
      end; 
      skin_change:begin 
          DeleteDeleted; 
          for i:= 0 to flist.count-1 do begin 
             sf:=TWinSkinform(flist[i]); 
             if (sf.fsd = sd) {and (sf.mode=mode)} then begin 
               sf.DeleteSysbtn; 
               sf.InitSkinData; 
             end; 
          end; 
//          for i:= flist.count-1 downto 0 do begin 
          for i:= 0 to flist.count-1 do begin 
             sf:=TWinSkinform(flist[i]); 
             if (sf.fsd = sd) {and (sf.mode=mode)}then 
               sf.skinchange; 
          end; 
      end; 
      skin_deleted : deleteform3; 
      skin_update  : begin 
          ahwnd:=lpara; 
          sf := TWinSkinform(findskinform(ahwnd)); 
          if sf<>nil then begin 
             sf.UnSubclass(); 
             sf.skinstate:=skin_Deleted; 
             deleteDeleted; 
             AddForm(ahwnd); 
          end; 
          exit; 
      end; 
   end;//endcase 
   sd.doskinchanged; 
   UpdateData:=nil; 
   end; 
end; 
 
function LCIDToCodePage(ALcid: LCID): Cardinal; 
var 
  Buf: array[0..6] of AnsiChar; 
begin 
  GetLocaleInfo(ALcid, LOCALE_IDefaultAnsiCodePage, Buf, 6); 
  Result := StrToIntDef(Buf, GetACP); 
end; 
 
procedure InitMsg; 
var AtomText: array[0..31] of Char; 
begin 
  PropName := Format('ControlOfs%.8X%.8X', [HInstance, GetCurrentThreadID]); 
  RM_GetObjectInstance := RegisterWindowMessage(PChar(PropName)); 
  DefaultUserCodePage := CP_ACP; 
  myinstance:=HInstance; 
//  DefaultUserCodePage := 3; //CP_THREAD_ACP 
  ControlAtom := GlobalAddAtom( 
    StrFmt(AtomText, 'ControlOfs%.8X%.8X', [HInstance, GetCurrentThreadID])); 
end; 
 
Procedure Fini; 
var i:integer; 
begin 
  if skinmanager<>nil then 
      SkinManager.free; 
  SkinManager:=nil; 
end; 
 
initialization 
  Win32PlatformIsUnicode := (Win32Platform = VER_PLATFORM_WIN32_NT); 
  InitMsg; 
//  Win32PlatformIsUnicode := false; 
//  skinmanager := TSkinManage.create; 
//  skinmanager.installhook; 
finalization 
   fini; 
//  if skinmanager<>nil then 
//      SkinManager.free; 
//  SkinManager:=nil; 
end.