{******************************************************************************} { CnPack For Delphi/C++Builder } { 中国人自己的开放源码第三方开发包 } { (C)Copyright 2001-2018 CnPack 开发组 } { ------------------------------------ } { } { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 } { 改和重新发布这一程序。 } { } { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 } { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 } { } { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 } { 还没有,可访问我们的网站: } { } { 网站地址:http://www.cnpack.org } { 电子邮件:master@cnpack.org } { } {******************************************************************************} {*******************************************************} { } { 处理停靠信息 } { CnDockInfo 单元 } { } { 版权 (C) 2002,2003 鲁小班 } { } {*******************************************************} unit CnDockInfo; {* |
================================================================================ * 软件名称:不可视工具组件包停靠单元 * 单元名称:处理停靠信息 * 单元作者:CnPack开发组 周益波(鲁小班) * 备 注:本单元由原作者授权CnPack开发组移植,已保留原作者版权信息 * 开发平台: * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7 * 本 地 化:该单元中的字符串均符合本地化处理方式 * 单元标识:$Id$ * 修改记录:2007.07.13 V1.0 * 移植单元 ================================================================================ |} interface {$I CnPack.inc} uses Windows, Controls, Inifiles, Registry, Classes, Sysutils, Forms, Messages, CnDockFormControl, CnDockSupportClass, CnDockSupportProc; type TCnDockInfoTree = class; TDockFormStyle = (dsNormal, dsConjoin, dsTab, dsDockPanel); TCnDockInfoZone = class(TCnBaseZone) private FDockFormName: string; //停靠窗体的名字 FParentName: string; //父窗体的名字 FDockRect: TRect; //停靠窗体的大小 FLastDockSiteName: string; //上一次停靠的窗体的名称 FUnDockLeft: Integer; //上一次停靠的左边 FUnDockTop: Integer; //上一次停靠的上边 FLRDockWidth: Integer; //停靠时窗口的宽度 FTBDockHeight: Integer; //停靠时窗口的高度 FUnDockWidth: Integer; //浮动时窗口的宽度 FUnDockHeight: Integer; //浮动时窗口的高度 FVSPaneWidth: Integer; //面板的宽度 FVisible: Boolean; //是否可见 FBorderStyle: TBorderStyle; //窗体的BorderStyle属性 FFormStyle: TFormStyle; //窗体的FormStyle属性 FWindowState: TWindowState; //窗体的WindowState属性 FCanDocked: Boolean; //是否可停靠 FEachOtherDocked: Boolean; //是否可相互停靠 FLeftDocked: Boolean; //是否可停靠在左边 FTopDocked: Boolean; //是否可停靠在上边 FRightDocked: Boolean; //是否可停靠在右边 FBottomDocked: Boolean; //是否可停靠在下边 FDockFormStyle: TDockFormStyle;//停靠类型 FDockClientData: string; //停靠信息 FDockControl: TWinControl; //窗体指针 function GetChildControlCount: Integer; //获得子窗体的个数 public procedure SetDockInfoFromControlToNode(Control: TControl); virtual; procedure SetDockInfoFromNodeToControl(Control: TControl); virtual; procedure SetDockInfoFromDockControlToNode(DockControl: TCnDockBaseControl); virtual; procedure SetDockInfoFromNodeToDockControl(DockControl: TCnDockBaseControl); virtual; //////////////////////////////////////////////////////////////////// property DockFormName: string read FDockFormName write FDockFormName; property ParentName: string read FParentName write FParentName; property DockRect: TRect read FDockRect write FDockRect; property LastDockSiteName: string read FLastDockSiteName write FLastDockSiteName; property UnDockLeft: Integer read FUnDockLeft write FUnDockLeft; property UnDockTop: Integer read FUnDockTop write FUnDockTop; property LRDockWidth: Integer read FLRDockWidth write FLRDockWidth; property TBDockHeight: Integer read FTBDockHeight write FTBDockHeight; property UnDockWidth: Integer read FUnDockWidth write FUnDockWidth; property UnDockHeight: Integer read FUnDockHeight write FUnDockHeight; property VSPaneWidth: Integer read FVSPaneWidth write FVSPaneWidth; property BorderStyle: TBorderStyle read FBorderStyle write FBorderStyle; property FormStyle: TFormStyle read FFormStyle write FFormStyle; property WindowState: TWindowState read FWindowState write FWindowState; property Visible: Boolean read FVisible write FVisible; property CanDocked: Boolean read FCanDocked write FCanDocked; property EachOtherDocked: Boolean read FEachOtherDocked write FEachOtherDocked; property LeftDocked: Boolean read FLeftDocked write FLeftDocked; property TopDocked: Boolean read FTopDocked write FTopDocked; property RightDocked: Boolean read FRightDocked write FRightDocked; property BottomDocked: Boolean read FBottomDocked write FBottomDocked; property DockFormStyle: TDockFormStyle read FDockFormStyle write FDockFormStyle; property DockClientData: string read FDockClientData write FDockClientData; property DockControl: TWinControl read FDockControl write FDockControl; end; TCnDockInfoStyle = ( isNone, //没有任何事情 isReadFileInfo, //正在读文件 isWriteFileInfo,//正在写文件 isReadRegInfo, //正在读注册表 isWriteRegInfo);//正在写注册表 {存储停靠信息的树} TCnDockInfoTree = class(TCnBaseTree) private FDockInfoIni: TIniFile; //INI文件 FDockInfoReg: TRegistry; //注册表类 FRegName: string; //注册表的路径 FCnDockInfoStyle: TCnDockInfoStyle;//正在处理的状态 FDataStream: TMemoryStream; //流,用来存储和还原停靠信息 function FindDockForm(FormName: string): TCustomForm; function CreateHostControl(ATreeZone: TCnDockInfoZone): TWinControl; // function FindDockHost(ControlName: string): TWinControl; protected procedure ScanTreeZone(TreeZone: TCnBaseZone); override; //当扫描到一个节点时,调用这个函数 procedure CreateZoneAndAddInfoFromIni; virtual;//从INI文件中提取出停靠信息 procedure CreateZoneAndAddInfoFromReg; virtual;//从注册表中提取出停靠信息 procedure SetDockControlInfo(ATreeZone: TCnDockInfoZone); virtual; public constructor Create(TreeZone: TCnTreeZoneClass); override; destructor Destroy; override; procedure CreateZoneAndAddInfoFromApp(Control: TControl); virtual;//从应用程序中提取出停靠信息 // procedure DoFloatAllForm; virtual; //使所有的窗体都成为浮动的 procedure ReadInfoFromIni; //从INI文件中读数据到树中 procedure ReadInfoFromReg(RegName: string); //从注册表中读数据到树中 procedure WriteInfoToIni; //把树中的数据写到INI文件中 procedure WriteInfoToReg(RegName: string); //把树中的数据写到注册表中 property DockInfoIni: TIniFile read FDockInfoIni write FDockInfoIni; property DockInfoReg: TRegistry read FDockInfoReg write FDockInfoReg; end; implementation uses CnDockGlobal, CnVSNETDockStyle; {在应用程序中查找名字为FormName的窗体} function FindDockForm(FormName: string): TCustomForm; begin if Pos(gs_CnDockInfoSplitter, FormName) > 0 then Result := nil else begin Result := Cn_FindDockFormWithName(FormName); end; end; function FindDockPanel(ControlName: string): TWinControl; var Index: Word; DockServer: TCnDockServer; begin Result := nil; Index := Pos(gs_CnDockInfoSplitter, ControlName); if Index = 0 then Exit; Result := FindDockForm(Copy(ControlName, 1, Index - 1)); if Result <> nil then begin DockServer := FindDockServer(Result); if DockServer <> nil then with DockServer do begin if Pos('TopDockPanel', ControlName) > Index then Result := TopDockPanel else if Pos('LeftDockPanel', ControlName) > Index then Result := LeftDockPanel else if Pos('BottomDockPanel', ControlName) > Index then Result := BottomDockPanel else if Pos('RightDockPanel', ControlName) > Index then Result := RightDockPanel; if (Result <> nil) and (Pos('PopupPanel', ControlName) > 20) then Result := TCnVSNETDockPanel(Result).VSChannel.VSPopupPanel; end; end; end; {查找名字为ControlName的WinControl} function FindDockHost(ControlName: string): TWinControl; begin Result := FindDockForm(ControlName); if Result = nil then Result := FindDockPanel(ControlName); end; { TCnDockInfoZone } function TCnDockInfoZone.GetChildControlCount: Integer; var AZone: TCnBaseZone; begin Result := 0; if ChildZone <> nil then begin Inc(Result); AZone := ChildZone; while AZone.NextSibling <> nil do begin AZone := AZone.NextSibling; if TCnDockInfoZone(AZone).DockControl <> nil then Inc(Result); end; end; end; procedure TCnDockInfoZone.SetDockInfoFromControlToNode(Control: TControl); begin DockRect := Control.BoundsRect; UnDockWidth := Control.UndockWidth; UnDockHeight := Control.UndockHeight; if Control is TCnVSPopupPanel then Control.Visible := False else Visible := Control.Visible; if Control is TForm then begin BorderStyle := TForm(Control).BorderStyle; FormStyle := TForm(Control).FormStyle; WindowState := TForm(Control).WindowState; LRDockWidth := Control.LRDockWidth; TBDockHeight := Control.TBDockHeight; end; end; procedure TCnDockInfoZone.SetDockInfoFromDockControlToNode( DockControl: TCnDockBaseControl); function GetLastDockSiteName(AControl: TControl): string; begin Result := gs_CannotFindWindow; if AControl <> nil then begin if AControl.Parent is TCnDockableForm then Result := AControl.Parent.Name else if AControl is TCnDockPanel then Result := AControl.Parent.Name + gs_CnDockInfoSplitter + AControl.Name; end; end; begin CanDocked := DockControl.EnableDock; EachOtherDocked := DockControl.EachOtherDock; LeftDocked := DockControl.LeftDock; TopDocked := DockControl.TopDock; RightDocked := DockControl.RightDock; BottomDocked := DockControl.BottomDock; if DockControl is TCnDockClient then begin VSPaneWidth := TCnDockClient(DockControl).VSPaneWidth; UnDockLeft := TCnDockClient(DockControl).UnDockLeft; UnDockTop := TCnDockClient(DockControl).UnDockTop; LastDockSiteName := GetLastDockSiteName(TCnDockClient(DockControl).LastDockSite); end else VSPaneWidth := 0; end; procedure TCnDockInfoZone.SetDockInfoFromNodeToControl(Control: TControl); var CnDockServer: TCnDockServer; procedure SetPopupPanelSize(PopupPanel: TCnVSPopupPanel); begin { case PopupPanel.VSChannel.Align of alLeft, alRight: Control.Width := DockRect.Right - DockRect.Left; alTop, alBottom:Control.Width := DockRect.Bottom - DockRect.Top; end;} end; procedure SetDockSiteSize(DockSite: TCnDockPanel); begin if DockSite.Align in [alTop, alBottom] then DockSite.CnDockManager.DockSiteSize := DockRect.Bottom - DockRect.Top else DockSite.CnDockManager.DockSiteSize := DockRect.Right - DockRect.Left; end; { procedure ResetVSChannelVisible; var i: Integer; begin for i := 0 to 3 do begin if CnDockServer.DockPanel[i] is TCnVSNETDockPanel then begin with TCnVSNETDockPanel(CnDockServer.DockPanel[i]) do begin VSChannel.Visible := VSChannel.BlockCount > 0; end; end; end; end;} //var DockClient: TCnDockClient; begin { DockClient := FindDockClient(Control); if DockClient <> nil then Control.Visible := False;} if (ParentName = '') or ((Control is TCnDockPanel) and (TCnDockPanel(Control).VisibleDockClientCount > 0)) then begin TWinControl(Control).DisableAlign; try if Control is TForm then begin TForm(Control).BorderStyle := BorderStyle; TForm(Control).FormStyle := FormStyle; if WindowState = wsNormal then Control.BoundsRect := DockRect; TForm(Control).WindowState := WindowState; end else begin if Control is TCnVSPopupPanel then SetPopupPanelSize(Control as TCnVSPopupPanel) else SetDockSiteSize(Control as TCnDockPanel); end; CnDockServer := FindDockServer(Control); if CnDockServer <> nil then begin CnDockServer.GetClientAlignControl(alTop); CnDockServer.GetClientAlignControl(alBottom); CnDockServer.GetClientAlignControl(alLeft); CnDockServer.GetClientAlignControl(alRight); // ResetVSChannelVisible; end; finally TWinControl(Control).EnableAlign; end; end; Control.Visible := Visible; Control.LRDockWidth := LRDockWidth; Control.TBDockHeight := TBDockHeight; Control.UndockHeight := UndockHeight; Control.UndockWidth := UndockWidth; end; procedure TCnDockInfoZone.SetDockInfoFromNodeToDockControl( DockControl: TCnDockBaseControl); function GetLastDockSite(AName: string): TWinControl; begin Result := FindDockPanel(AName); if Result = nil then begin Result := FindDockForm(AName); if Result is TCnDockableForm then Result := TCnDockableForm(Result).DockableControl; end; end; begin if (DockControl is TCnDockClient) then begin TCnDockClient(DockControl).UnDockLeft := UnDockLeft; TCnDockClient(DockControl).UnDockTop := UnDockTop; TCnDockClient(DockControl).LastDockSite := GetLastDockSite(LastDockSiteName); if Visible then begin TCnDockClient(DockControl).ParentVisible := False; TCnDockClient(DockControl).MakeShowEvent; end else TCnDockClient(DockControl).MakeHideEvent; TCnDockClient(DockControl).VSPaneWidth := VSPaneWidth; end; DockControl.EnableDock := CanDocked; DockControl.LeftDock := LeftDocked; DockControl.TopDock := TopDocked; DockControl.BottomDock := BottomDocked; DockControl.RightDock := RightDocked; end; { TCnDockInfoTree } constructor TCnDockInfoTree.Create(TreeZone: TCnTreeZoneClass); begin inherited Create(TreeZone); FDockInfoIni := nil; FCnDockInfoStyle := isNone; FDataStream := TMemoryStream.Create; end; procedure TCnDockInfoTree.CreateZoneAndAddInfoFromApp(Control: TControl); var i: Integer; TreeZone: TCnDockInfoZone; ADockBaseControl: TCnDockBaseControl; TmpDockPanel: TCnDockPanel; begin TreeZone := TCnDockInfoZone(AddChildZone(CurrTreeZone, nil)); with TreeZone do begin ParentName := TCnDockInfoZone(CurrTreeZone).DockFormName; SetDockInfoFromControlToNode(Control); if Control is TCnDockPanel then DockFormName := TCnDockInfoZone(CurrTreeZone).DockFormName + gs_CnDockInfoSplitter + Control.Name else DockFormName := Control.Name; FDataStream.Clear; if Control is TCnTabDockHostForm then TCnTabDockHostForm(Control).PageControl.SaveToStream(FDataStream) else if Control is TCnConjoinDockHostForm then TCnConjoinDockHostForm(Control).Panel.DockManager.SaveToStream(FDataStream) else if Control is TCnDockPanel then TCnDockPanel(Control).DockManager.SaveToStream(FDataStream); DockClientData := Cn_StreamDataToString(FDataStream); ADockBaseControl := FindDockBaseControl(Control); if ADockBaseControl <> nil then begin SetDockInfoFromDockControlToNode(ADockBaseControl); if Control is TCnTabDockHostForm then DockFormStyle := dsTab else if Control is TCnConjoinDockHostForm then DockFormStyle := dsConjoin else DockFormStyle := dsNormal; if ADockBaseControl is TCnDockClient then begin if Control is TCnDockableForm then begin with TCnDockableForm(Control).DockableControl do begin for i := 0 to DockClientCount -1 do begin CurrTreeZone := TreeZone; CreateZoneAndAddInfoFromApp(DockClients[i]); CurrTreeZone := TreeZone.GetParentZone; end; end; end; end else begin for i := 0 to 3 do begin CurrTreeZone := TreeZone; TmpDockPanel := TCnDockServer(ADockBaseControl).DockPanel[i]; CreateZoneAndAddInfoFromApp(TmpDockPanel); if TmpDockPanel is TCnVSNETDockPanel then CreateZoneAndAddInfoFromApp(TCnVSNETDockPanel(TmpDockPanel).VSChannel.VSPopupPanel); CurrTreeZone := TreeZone.GetParentZone; end; end; end; if Control is TCnDockPanel then begin DockFormStyle := dsDockPanel; if Control is TCnVSPopupPanel then begin with TCnVSPopupPanel(Control) do begin for i := 0 to DockClientCount - 1 do begin CurrTreeZone := TreeZone; CreateZoneAndAddInfoFromApp(TWinControl(DockClients[i])); CurrTreeZone := TreeZone.GetParentZone; end; end; end else with TCnDockPanel(Control) do begin for i := 0 to DockClientCount - 1 do begin CurrTreeZone := TreeZone; CreateZoneAndAddInfoFromApp(TWinControl(DockClients[i])); CurrTreeZone := TreeZone.GetParentZone; end; end; end; end; end; procedure TCnDockInfoTree.CreateZoneAndAddInfoFromIni; var Sections: TStringList; i: Integer; procedure CreateZoneAndAddInfo(Index: Integer); var i: Integer; TreeZone: TCnDockInfoZone; begin TreeZone := TCnDockInfoZone(AddChildZone(CurrTreeZone, nil)); with TreeZone, FDockInfoIni do begin {读取INI文件中的数据到一个树节点} DockFormName := Sections[Index]; ParentName := ReadString(DockFormName, 'ParentName', 'ERROR'); DockRect := Rect(ReadInteger(DockFormName, 'DockLeft', 0), ReadInteger(DockFormName, 'DockTop', 0), ReadInteger(DockFormName, 'DockRight', 100), ReadInteger(DockFormName, 'DockBottom', 100)); LastDockSiteName:= ReadString(DockFormName, 'LastDockSiteName', 'ERROR'); UnDockLeft := ReadInteger(DockFormName, 'UnDockLeft', 100); UnDockTop := ReadInteger(DockFormName, 'UnDockTop', 100); LRDockWidth := ReadInteger(DockFormName, 'LRDockWidth', 100); TBDockHeight := ReadInteger(DockFormName, 'TBDockHeight', 100); UnDockWidth := ReadInteger(DockFormName, 'UndockWidth', 100); UnDockHeight := ReadInteger(DockFormName, 'UndockHeight', 100); VSPaneWidth := ReadInteger(DockFormName, 'VSPaneWidth', 100); Visible := ReadBool(DockFormName, 'Visible', True); BorderStyle := TBorderStyle(ReadInteger(DockFormName, 'BorderStyle', 0)); FormStyle := TFormStyle(ReadInteger(DockFormName, 'FormStyle', 0)); WindowState := TWindowState(ReadInteger(DockFormName, 'WindowState', 0)); DockFormStyle := TDockFormStyle(ReadInteger(DockFormName, 'DockFormStyle', 0)); CanDocked := ReadBool(DockFormName, 'CanDocked', True); EachOtherDocked := ReadBool(DockFormName, 'EachOtherDocked', True); LeftDocked := ReadBool(DockFormName, 'LeftDocked', LeftDocked); TopDocked := ReadBool(DockFormName, 'TopDocked', True); RightDocked := ReadBool(DockFormName, 'RightDocked', True); BottomDocked := ReadBool(DockFormName, 'BottomDocked', True); DockClientData:= ReadString(DockFormName, 'DockClientData', ''); end; for i := Index - 1 downto 0 do begin if FDockInfoIni.ReadString(Sections[i], 'ParentName', 'ERROR') = Sections[Index] then begin CurrTreeZone := TreeZone; CreateZoneAndAddInfo(i); CurrTreeZone := TreeZone.GetParentZone; end; end; end; begin Sections := TStringList.Create; try FDockInfoIni.ReadSections(Sections); {遍历INI文件,把里面的信息取出来放在树中} FCnDockInfoStyle := isReadFileInfo; for i := Sections.Count - 1 downto 0 do begin if FDockInfoIni.ReadString(Sections[i], 'ParentName', 'ERROR') = '' then CreateZoneAndAddInfo(i); end; FCnDockInfoStyle := isNone; finally Sections.Free; end; end; procedure TCnDockInfoTree.CreateZoneAndAddInfoFromReg; var FormList: TStringList; procedure CreateZoneAndAddInfo(Index: Integer); var i: Integer; TreeZone: TCnDockInfoZone; begin FDockInfoReg.OpenKey(FRegName, False); if FDockInfoReg.KeyExists(FormList[Index]) then begin FDockInfoReg.OpenKey(FRegName + '\' + FormList[Index], False); TreeZone := TCnDockInfoZone(AddChildZone(CurrTreeZone, nil)); with TreeZone, FDockInfoReg do begin {读取注册表中的数据到一个树节点} DockFormName := FormList[Index]; ParentName := ReadString('ParentName'); DockRect := Rect(ReadInteger('DockLeft'), ReadInteger('DockTop'), ReadInteger('DockRight'), ReadInteger('DockBottom')); LRDockWidth := ReadInteger('LRDockWidth'); LastDockSiteName:= ReadString('LastDockSiteName'); UnDockLeft := ReadInteger('UnDockLeft'); UnDockTop := ReadInteger('UnDockTop'); TBDockHeight := ReadInteger('TBDockHeight'); UnDockWidth := ReadInteger('UnDockWidth'); UnDockHeight := ReadInteger('UnDockHeight'); VSPaneWidth := ReadInteger('VSPaneWidth'); Visible := ReadBool('Visible'); BorderStyle := TBorderStyle(ReadInteger('BorderStyle')); FormStyle := TFormStyle(ReadInteger('FormStyle')); WindowState := TWindowState(ReadInteger('WindowState')); DockFormStyle := TDockFormStyle(ReadInteger('DockFormStyle')); CanDocked := ReadBool('CanDocked'); EachOtherDocked := ReadBool('EachOtherDocked'); LeftDocked := ReadBool('LeftDocked'); TopDocked := ReadBool('TopDocked'); RightDocked := ReadBool('RightDocked'); BottomDocked := ReadBool('BottomDocked'); DockClientData:= ReadString('DockClientData'); end; for i := Index - 1 downto 0 do begin FDockInfoReg.OpenKey(FRegName + '\' + FormList[i], False); if FDockInfoReg.ReadString('ParentName') = FormList[Index] then begin CurrTreeZone := TreeZone; CreateZoneAndAddInfo(i); CurrTreeZone := TreeZone.GetParentZone; end; end; end; end; var cp, cp1: PChar; i: Integer; begin FormList := TStringList.Create; try if FDockInfoReg.OpenKey(FRegName, False) then begin cp := PChar(FDockInfoReg.ReadString('FormNames')); cp1 := StrPos(cp, '\'); while cp1 <> nil do begin cp1^ := #0; FormList.Add(string(cp)); cp := cp1 + 1; cp1 := StrPos(cp, '\'); end; FCnDockInfoStyle := isReadFileInfo; for i := FormList.Count - 1 downto 0 do begin FDockInfoReg.OpenKey(FRegName + '\' + FormList[i], False); if FDockInfoReg.ReadString('ParentName') = '' then CreateZoneAndAddInfo(i); end; FCnDockInfoStyle := isNone; end; finally FDockInfoReg.CloseKey; FormList.Free; end; end; destructor TCnDockInfoTree.Destroy; begin FDataStream.Free; inherited Destroy; end; procedure TCnDockInfoTree.ReadInfoFromIni; begin CreateZoneAndAddInfoFromIni; {使所有的停靠窗体成为浮动的} DoFloatAllForm; {处理完所有的消息} Application.ProcessMessages; {中序遍历树} FCnDockInfoStyle := isReadFileInfo; MiddleScanTree(TopTreeZone); FCnDockInfoStyle := isNone; end; procedure TCnDockInfoTree.ReadInfoFromReg(RegName: string); begin FRegName := RegName; CreateZoneAndAddInfoFromReg; {使所有的停靠窗体成为浮动的} DoFloatAllForm; {处理完所有的消息} Application.ProcessMessages; {中序遍历树} FCnDockInfoStyle := isReadRegInfo; MiddleScanTree(TopTreeZone); FCnDockInfoStyle := isNone; end; procedure TCnDockInfoTree.ScanTreeZone(TreeZone: TCnBaseZone); var i: Integer; begin if (FCnDockInfoStyle = isReadFileInfo) or (FCnDockInfoStyle = isReadRegInfo) then begin {从文件中读停靠信息} for i := 0 to TreeZone.GetChildCount - 1 do begin with TCnDockInfoZone(TreeZone.GetChildZone(i)) do DockControl := FindDockForm(DockFormName); end; SetDockControlInfo(TCnDockInfoZone(TreeZone)); end else if FCnDockInfoStyle = isWriteFileInfo then begin {把停靠信息写到文件中} if TreeZone <> TopTreeZone then begin with TCnDockInfoZone(TreeZone), FDockInfoIni do begin WriteString(DockFormName, 'ParentName', ParentName); WriteInteger(DockFormName, 'DockLeft', DockRect.Left); WriteInteger(DockFormName, 'DockTop', DockRect.Top); WriteInteger(DockFormName, 'DockRight', DockRect.Right); WriteInteger(DockFormName, 'DockBottom', DockRect.Bottom); WriteString(DockFormName, 'LastDockSiteName', LastDockSiteName); WriteInteger(DockFormName, 'UnDockLeft', UnDockLeft); WriteInteger(DockFormName, 'UnDockTop', UnDockTop); WriteInteger(DockFormName, 'LRDockWidth', LRDockWidth); WriteInteger(DockFormName, 'TBDockHeight', TBDockHeight); WriteInteger(DockFormName, 'UnDockWidth', UnDockWidth); WriteInteger(DockFormName, 'UnDockHeight', UnDockHeight); WriteInteger(DockFormName, 'VSPaneWidth', VSPaneWidth); WriteBool(DockFormName, 'Visible', Visible); WriteInteger(DockFormName, 'BorderStyle', Integer(BorderStyle)); WriteInteger(DockFormName, 'WindowState', Integer(WindowState)); WriteInteger(DockFormName, 'FormStyle', Integer(FormStyle)); WriteInteger(DockFormName, 'DockFormStyle', Integer(DockFormStyle)); WriteBool(DockFormName, 'CanDocked', CanDocked); WriteBool(DockFormName, 'EachOtherDocked', EachOtherDocked); WriteBool(DockFormName, 'LeftDocked', LeftDocked); WriteBool(DockFormName, 'TopDocked', TopDocked); WriteBool(DockFormName, 'RightDocked', RightDocked); WriteBool(DockFormName, 'BottomDocked', BottomDocked); WriteString(DockFormName, 'DockClientData', DockClientData); end; end; end else if FCnDockInfoStyle = isWriteRegInfo then begin if TreeZone <> TopTreeZone then begin with TCnDockInfoZone(TreeZone), FDockInfoReg do begin OpenKey(FRegName, True); WriteString('FormNames', ReadString('FormNames') + DockFormName + '\'); OpenKey(FRegName + '\' + DockFormName, True); WriteString('ParentName', ParentName); WriteInteger('DockLeft', DockRect.Left); WriteInteger('DockTop', DockRect.Top); WriteInteger('DockRight', DockRect.Right); WriteInteger('DockBottom', DockRect.Bottom); WriteString('LastDockSiteName', LastDockSiteName); WriteInteger('UnDockLeft', UnDockLeft); WriteInteger('UnDockTop', UnDockTop); WriteInteger('LRDockWidth', LRDockWidth); WriteInteger('TBDockHeight', TBDockHeight); WriteInteger('UnDockWidth', UnDockWidth); WriteInteger('UnDockHeight', UnDockHeight); WriteInteger('VSPaneWidth', VSPaneWidth); WriteBool('Visible', Visible); WriteInteger('BorderStyle', Integer(BorderStyle)); WriteInteger('FormStyle', Integer(FormStyle)); WriteInteger('WindowState', Integer(WindowState)); WriteInteger('DockFormStyle', Integer(DockFormStyle)); WriteBool('CanDocked', CanDocked); WriteBool('EachOtherDocked', EachOtherDocked); WriteBool('LeftDocked', LeftDocked); WriteBool('TopDocked', TopDocked); WriteBool('RightDocked', RightDocked); WriteBool('BottomDocked', BottomDocked); WriteString('DockClientData', DockClientData); CloseKey; end; end; end; inherited ScanTreeZone(TreeZone); end; {在应用程序中查找名字为FormName的窗体} function TCnDockInfoTree.FindDockForm(FormName: string): TCustomForm; begin if Pos(gs_CnDockInfoSplitter, FormName) > 0 then Result := nil else begin Result := Cn_FindDockFormWithName(FormName); end; end; {查找名字为ControlName的WinControl} (*function TCnDockInfoTree.FindDockHost(ControlName: string): TWinControl; var Index: Word; DockServer: TCnDockServer; begin Result := FindDockForm(ControlName); if Result = nil then begin Index := Pos(gs_CnDockInfoSplitter, ControlName); if Index = 0 then Exit; Result := FindDockForm(Copy(ControlName, 1, Index - 1)); if Result <> nil then begin DockServer := FindDockServer(Result); if DockServer <> nil then with DockServer do begin if Pos('TopDockPanel', ControlName) > Index then Result := TopDockPanel else if Pos('LeftDockPanel', ControlName) > Index then Result := LeftDockPanel else if Pos('BottomDockPanel', ControlName) > Index then Result := BottomDockPanel else if Pos('RightDockPanel', ControlName) > Index then Result := RightDockPanel; if (Result <> nil) and (Pos('PopupPanel', ControlName) > 20) then Result := TCnVSNETDockPanel(Result).VSChannel.VSPopupPanel; end; end; end; end;*) {创建平铺或分页窗体} function TCnDockInfoTree.CreateHostControl(ATreeZone: TCnDockInfoZone): TWinControl; var Form: TForm; DockClient: TCnDockClient; begin Result := nil; case ATreeZone.DockFormStyle of dsConjoin: begin Form := TCnConjoinDockHostForm.Create(Application); DockClient := FindDockClient(TCnDockInfoZone(ATreeZone.ChildZone).DockControl); Result := DockClient.CreateConjoinPanelClass(Form).Parent; end; dsTab: begin Form := TCnTabDockHostForm.Create(Application); DockClient := FindDockClient(TCnDockInfoZone(ATreeZone.ChildZone).DockControl); Result := DockClient.CreateTabDockClass(Form).Parent; end; end; if Result <> nil then begin Result.Name := ATreeZone.DockFormName; end; end; procedure TCnDockInfoTree.SetDockControlInfo(ATreeZone: TCnDockInfoZone); var ADockBaseControl: TCnDockBaseControl; Host: TWinControl; begin with ATreeZone do begin if DockFormName = '' then Exit; Host := FindDockHost(DockFormName); if (Host = nil) and (ATreeZone.GetChildControlCount > 1) then Host := CreateHostControl(ATreeZone); if (Host <> nil) and (DockClientData <> '') then begin {请空TMemoryStream} FDataStream.Clear; {把字符串转换成流格式} Cn_StringToStreamData(FDataStream, DockClientData); {开始读} FDataStream.Position := 0; if Host is TCnTabDockHostForm then begin {如果是分页窗体,就调用她的LoadFromStream函数} with TCnTabDockHostForm(Host).PageControl do begin DisableAlign; try LoadFromStream(FDataStream); finally EnableAlign; end; end; end else if Host is TCnConjoinDockHostForm then begin {如果是平铺窗体,就调用她的DockManageer的LoadFromStream函数} with TCnConjoinDockHostForm(Host).Panel do begin DisableAlign; try DockManager.LoadFromStream(FDataStream); finally EnableAlign; end; end; end else if Host is TCnDockPanel then begin {如果是停靠服务器,就调用她的DockManageer的LoadFromStream函数} with TCnDockPanel(Host) do begin DisableAlign; try DockManager.LoadFromStream(FDataStream); finally EnableAlign; end; end; end; end; if Host <> nil then begin SetDockInfoFromNodeToControl(Host); ADockBaseControl := FindDockBaseControl(Host); if ADockBaseControl <> nil then SetDockInfoFromNodeToDockControl(ADockBaseControl); end; end; end; procedure TCnDockInfoTree.WriteInfoToIni; var Sections: TStringList; i: Integer; begin Sections := TStringList.Create; try FDockInfoIni.ReadSections(Sections); {首先把INI文件清空} for i := 0 to Sections.Count - 1 do FDockInfoIni.EraseSection(Sections[i]); finally Sections.Free; end; {中序遍历树} FCnDockInfoStyle := isWriteFileInfo; MiddleScanTree(TopTreeZone); FCnDockInfoStyle := isNone; end; procedure TCnDockInfoTree.WriteInfoToReg(RegName: string); begin try {删除路径名为RegName的注册表项} if FDockInfoReg.OpenKey(RegName, False) then FDockInfoReg.DeleteKey(RegName); {再次创建她} FDockInfoReg.CreateKey(RegName); FDockInfoReg.CloseKey; FRegName := RegName; {中序遍历她} FCnDockInfoStyle := isWriteRegInfo; MiddleScanTree(TopTreeZone); FCnDockInfoStyle := isNone; finally FDockInfoReg.CloseKey; end; end; end.