CnDockInfo.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. {*******************************************************}
  21. { }
  22. { 处理停靠信息 }
  23. { CnDockInfo 单元 }
  24. { }
  25. { 版权 (C) 2002,2003 鲁小班 }
  26. { }
  27. {*******************************************************}
  28. unit CnDockInfo;
  29. {* |<PRE>
  30. ================================================================================
  31. * 软件名称:不可视工具组件包停靠单元
  32. * 单元名称:处理停靠信息
  33. * 单元作者:CnPack开发组 周益波(鲁小班)
  34. * 备 注:本单元由原作者授权CnPack开发组移植,已保留原作者版权信息
  35. * 开发平台:
  36. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
  37. * 本 地 化:该单元中的字符串均符合本地化处理方式
  38. * 单元标识:$Id$
  39. * 修改记录:2007.07.13 V1.0
  40. * 移植单元
  41. ================================================================================
  42. |</PRE>}
  43. interface
  44. {$I CnPack.inc}
  45. uses
  46. Windows, Controls, Inifiles, Registry, Classes, Sysutils, Forms, Messages,
  47. CnDockFormControl, CnDockSupportClass, CnDockSupportProc;
  48. type
  49. TCnDockInfoTree = class;
  50. TDockFormStyle = (dsNormal, dsConjoin, dsTab, dsDockPanel);
  51. TCnDockInfoZone = class(TCnBaseZone)
  52. private
  53. FDockFormName: string; //停靠窗体的名字
  54. FParentName: string; //父窗体的名字
  55. FDockRect: TRect; //停靠窗体的大小
  56. FLastDockSiteName: string; //上一次停靠的窗体的名称
  57. FUnDockLeft: Integer; //上一次停靠的左边
  58. FUnDockTop: Integer; //上一次停靠的上边
  59. FLRDockWidth: Integer; //停靠时窗口的宽度
  60. FTBDockHeight: Integer; //停靠时窗口的高度
  61. FUnDockWidth: Integer; //浮动时窗口的宽度
  62. FUnDockHeight: Integer; //浮动时窗口的高度
  63. FVSPaneWidth: Integer; //面板的宽度
  64. FVisible: Boolean; //是否可见
  65. FBorderStyle: TBorderStyle; //窗体的BorderStyle属性
  66. FFormStyle: TFormStyle; //窗体的FormStyle属性
  67. FWindowState: TWindowState; //窗体的WindowState属性
  68. FCanDocked: Boolean; //是否可停靠
  69. FEachOtherDocked: Boolean; //是否可相互停靠
  70. FLeftDocked: Boolean; //是否可停靠在左边
  71. FTopDocked: Boolean; //是否可停靠在上边
  72. FRightDocked: Boolean; //是否可停靠在右边
  73. FBottomDocked: Boolean; //是否可停靠在下边
  74. FDockFormStyle: TDockFormStyle;//停靠类型
  75. FDockClientData: string; //停靠信息
  76. FDockControl: TWinControl; //窗体指针
  77. function GetChildControlCount: Integer; //获得子窗体的个数
  78. public
  79. procedure SetDockInfoFromControlToNode(Control: TControl); virtual;
  80. procedure SetDockInfoFromNodeToControl(Control: TControl); virtual;
  81. procedure SetDockInfoFromDockControlToNode(DockControl: TCnDockBaseControl); virtual;
  82. procedure SetDockInfoFromNodeToDockControl(DockControl: TCnDockBaseControl); virtual;
  83. ////////////////////////////////////////////////////////////////////
  84. property DockFormName: string read FDockFormName write FDockFormName;
  85. property ParentName: string read FParentName write FParentName;
  86. property DockRect: TRect read FDockRect write FDockRect;
  87. property LastDockSiteName: string read FLastDockSiteName write FLastDockSiteName;
  88. property UnDockLeft: Integer read FUnDockLeft write FUnDockLeft;
  89. property UnDockTop: Integer read FUnDockTop write FUnDockTop;
  90. property LRDockWidth: Integer read FLRDockWidth write FLRDockWidth;
  91. property TBDockHeight: Integer read FTBDockHeight write FTBDockHeight;
  92. property UnDockWidth: Integer read FUnDockWidth write FUnDockWidth;
  93. property UnDockHeight: Integer read FUnDockHeight write FUnDockHeight;
  94. property VSPaneWidth: Integer read FVSPaneWidth write FVSPaneWidth;
  95. property BorderStyle: TBorderStyle read FBorderStyle write FBorderStyle;
  96. property FormStyle: TFormStyle read FFormStyle write FFormStyle;
  97. property WindowState: TWindowState read FWindowState write FWindowState;
  98. property Visible: Boolean read FVisible write FVisible;
  99. property CanDocked: Boolean read FCanDocked write FCanDocked;
  100. property EachOtherDocked: Boolean read FEachOtherDocked write FEachOtherDocked;
  101. property LeftDocked: Boolean read FLeftDocked write FLeftDocked;
  102. property TopDocked: Boolean read FTopDocked write FTopDocked;
  103. property RightDocked: Boolean read FRightDocked write FRightDocked;
  104. property BottomDocked: Boolean read FBottomDocked write FBottomDocked;
  105. property DockFormStyle: TDockFormStyle read FDockFormStyle write FDockFormStyle;
  106. property DockClientData: string read FDockClientData write FDockClientData;
  107. property DockControl: TWinControl read FDockControl write FDockControl;
  108. end;
  109. TCnDockInfoStyle =
  110. ( isNone, //没有任何事情
  111. isReadFileInfo, //正在读文件
  112. isWriteFileInfo,//正在写文件
  113. isReadRegInfo, //正在读注册表
  114. isWriteRegInfo);//正在写注册表
  115. {存储停靠信息的树}
  116. TCnDockInfoTree = class(TCnBaseTree)
  117. private
  118. FDockInfoIni: TIniFile; //INI文件
  119. FDockInfoReg: TRegistry; //注册表类
  120. FRegName: string; //注册表的路径
  121. FCnDockInfoStyle: TCnDockInfoStyle;//正在处理的状态
  122. FDataStream: TMemoryStream; //流,用来存储和还原停靠信息
  123. function FindDockForm(FormName: string): TCustomForm;
  124. function CreateHostControl(ATreeZone: TCnDockInfoZone): TWinControl;
  125. // function FindDockHost(ControlName: string): TWinControl;
  126. protected
  127. procedure ScanTreeZone(TreeZone: TCnBaseZone); override; //当扫描到一个节点时,调用这个函数
  128. procedure CreateZoneAndAddInfoFromIni; virtual;//从INI文件中提取出停靠信息
  129. procedure CreateZoneAndAddInfoFromReg; virtual;//从注册表中提取出停靠信息
  130. procedure SetDockControlInfo(ATreeZone: TCnDockInfoZone); virtual;
  131. public
  132. constructor Create(TreeZone: TCnTreeZoneClass); override;
  133. destructor Destroy; override;
  134. procedure CreateZoneAndAddInfoFromApp(Control: TControl); virtual;//从应用程序中提取出停靠信息
  135. // procedure DoFloatAllForm; virtual; //使所有的窗体都成为浮动的
  136. procedure ReadInfoFromIni; //从INI文件中读数据到树中
  137. procedure ReadInfoFromReg(RegName: string); //从注册表中读数据到树中
  138. procedure WriteInfoToIni; //把树中的数据写到INI文件中
  139. procedure WriteInfoToReg(RegName: string); //把树中的数据写到注册表中
  140. property DockInfoIni: TIniFile read FDockInfoIni write FDockInfoIni;
  141. property DockInfoReg: TRegistry read FDockInfoReg write FDockInfoReg;
  142. end;
  143. implementation
  144. uses CnDockGlobal, CnVSNETDockStyle;
  145. {在应用程序中查找名字为FormName的窗体}
  146. function FindDockForm(FormName: string): TCustomForm;
  147. begin
  148. if Pos(gs_CnDockInfoSplitter, FormName) > 0 then Result := nil
  149. else
  150. begin
  151. Result := Cn_FindDockFormWithName(FormName);
  152. end;
  153. end;
  154. function FindDockPanel(ControlName: string): TWinControl;
  155. var Index: Word;
  156. DockServer: TCnDockServer;
  157. begin
  158. Result := nil;
  159. Index := Pos(gs_CnDockInfoSplitter, ControlName);
  160. if Index = 0 then Exit;
  161. Result := FindDockForm(Copy(ControlName, 1, Index - 1));
  162. if Result <> nil then
  163. begin
  164. DockServer := FindDockServer(Result);
  165. if DockServer <> nil then
  166. with DockServer do
  167. begin
  168. if Pos('TopDockPanel', ControlName) > Index then
  169. Result := TopDockPanel
  170. else if Pos('LeftDockPanel', ControlName) > Index then
  171. Result := LeftDockPanel
  172. else if Pos('BottomDockPanel', ControlName) > Index then
  173. Result := BottomDockPanel
  174. else if Pos('RightDockPanel', ControlName) > Index then
  175. Result := RightDockPanel;
  176. if (Result <> nil) and (Pos('PopupPanel', ControlName) > 20) then
  177. Result := TCnVSNETDockPanel(Result).VSChannel.VSPopupPanel;
  178. end;
  179. end;
  180. end;
  181. {查找名字为ControlName的WinControl}
  182. function FindDockHost(ControlName: string): TWinControl;
  183. begin
  184. Result := FindDockForm(ControlName);
  185. if Result = nil then
  186. Result := FindDockPanel(ControlName);
  187. end;
  188. { TCnDockInfoZone }
  189. function TCnDockInfoZone.GetChildControlCount: Integer;
  190. var AZone: TCnBaseZone;
  191. begin
  192. Result := 0;
  193. if ChildZone <> nil then
  194. begin
  195. Inc(Result);
  196. AZone := ChildZone;
  197. while AZone.NextSibling <> nil do
  198. begin
  199. AZone := AZone.NextSibling;
  200. if TCnDockInfoZone(AZone).DockControl <> nil then
  201. Inc(Result);
  202. end;
  203. end;
  204. end;
  205. procedure TCnDockInfoZone.SetDockInfoFromControlToNode(Control: TControl);
  206. begin
  207. DockRect := Control.BoundsRect;
  208. UnDockWidth := Control.UndockWidth;
  209. UnDockHeight := Control.UndockHeight;
  210. if Control is TCnVSPopupPanel then
  211. Control.Visible := False
  212. else
  213. Visible := Control.Visible;
  214. if Control is TForm then
  215. begin
  216. BorderStyle := TForm(Control).BorderStyle;
  217. FormStyle := TForm(Control).FormStyle;
  218. WindowState := TForm(Control).WindowState;
  219. LRDockWidth := Control.LRDockWidth;
  220. TBDockHeight := Control.TBDockHeight;
  221. end;
  222. end;
  223. procedure TCnDockInfoZone.SetDockInfoFromDockControlToNode(
  224. DockControl: TCnDockBaseControl);
  225. function GetLastDockSiteName(AControl: TControl): string;
  226. begin
  227. Result := gs_CannotFindWindow;
  228. if AControl <> nil then
  229. begin
  230. if AControl.Parent is TCnDockableForm then
  231. Result := AControl.Parent.Name
  232. else if AControl is TCnDockPanel then
  233. Result := AControl.Parent.Name + gs_CnDockInfoSplitter + AControl.Name;
  234. end;
  235. end;
  236. begin
  237. CanDocked := DockControl.EnableDock;
  238. EachOtherDocked := DockControl.EachOtherDock;
  239. LeftDocked := DockControl.LeftDock;
  240. TopDocked := DockControl.TopDock;
  241. RightDocked := DockControl.RightDock;
  242. BottomDocked := DockControl.BottomDock;
  243. if DockControl is TCnDockClient then
  244. begin
  245. VSPaneWidth := TCnDockClient(DockControl).VSPaneWidth;
  246. UnDockLeft := TCnDockClient(DockControl).UnDockLeft;
  247. UnDockTop := TCnDockClient(DockControl).UnDockTop;
  248. LastDockSiteName := GetLastDockSiteName(TCnDockClient(DockControl).LastDockSite);
  249. end
  250. else
  251. VSPaneWidth := 0;
  252. end;
  253. procedure TCnDockInfoZone.SetDockInfoFromNodeToControl(Control: TControl);
  254. var CnDockServer: TCnDockServer;
  255. procedure SetPopupPanelSize(PopupPanel: TCnVSPopupPanel);
  256. begin
  257. { case PopupPanel.VSChannel.Align of
  258. alLeft,
  259. alRight: Control.Width := DockRect.Right - DockRect.Left;
  260. alTop,
  261. alBottom:Control.Width := DockRect.Bottom - DockRect.Top;
  262. end;}
  263. end;
  264. procedure SetDockSiteSize(DockSite: TCnDockPanel);
  265. begin
  266. if DockSite.Align in [alTop, alBottom] then
  267. DockSite.CnDockManager.DockSiteSize := DockRect.Bottom - DockRect.Top
  268. else
  269. DockSite.CnDockManager.DockSiteSize := DockRect.Right - DockRect.Left;
  270. end;
  271. { procedure ResetVSChannelVisible;
  272. var i: Integer;
  273. begin
  274. for i := 0 to 3 do
  275. begin
  276. if CnDockServer.DockPanel[i] is TCnVSNETDockPanel then
  277. begin
  278. with TCnVSNETDockPanel(CnDockServer.DockPanel[i]) do
  279. begin
  280. VSChannel.Visible := VSChannel.BlockCount > 0;
  281. end;
  282. end;
  283. end;
  284. end;}
  285. //var DockClient: TCnDockClient;
  286. begin
  287. { DockClient := FindDockClient(Control);
  288. if DockClient <> nil then
  289. Control.Visible := False;}
  290. if (ParentName = '') or ((Control is TCnDockPanel) and
  291. (TCnDockPanel(Control).VisibleDockClientCount > 0)) then
  292. begin
  293. TWinControl(Control).DisableAlign;
  294. try
  295. if Control is TForm then
  296. begin
  297. TForm(Control).BorderStyle := BorderStyle;
  298. TForm(Control).FormStyle := FormStyle;
  299. if WindowState = wsNormal then
  300. Control.BoundsRect := DockRect;
  301. TForm(Control).WindowState := WindowState;
  302. end else
  303. begin
  304. if Control is TCnVSPopupPanel then
  305. SetPopupPanelSize(Control as TCnVSPopupPanel)
  306. else
  307. SetDockSiteSize(Control as TCnDockPanel);
  308. end;
  309. CnDockServer := FindDockServer(Control);
  310. if CnDockServer <> nil then
  311. begin
  312. CnDockServer.GetClientAlignControl(alTop);
  313. CnDockServer.GetClientAlignControl(alBottom);
  314. CnDockServer.GetClientAlignControl(alLeft);
  315. CnDockServer.GetClientAlignControl(alRight);
  316. // ResetVSChannelVisible;
  317. end;
  318. finally
  319. TWinControl(Control).EnableAlign;
  320. end;
  321. end;
  322. Control.Visible := Visible;
  323. Control.LRDockWidth := LRDockWidth;
  324. Control.TBDockHeight := TBDockHeight;
  325. Control.UndockHeight := UndockHeight;
  326. Control.UndockWidth := UndockWidth;
  327. end;
  328. procedure TCnDockInfoZone.SetDockInfoFromNodeToDockControl(
  329. DockControl: TCnDockBaseControl);
  330. function GetLastDockSite(AName: string): TWinControl;
  331. begin
  332. Result := FindDockPanel(AName);
  333. if Result = nil then
  334. begin
  335. Result := FindDockForm(AName);
  336. if Result is TCnDockableForm then
  337. Result := TCnDockableForm(Result).DockableControl;
  338. end;
  339. end;
  340. begin
  341. if (DockControl is TCnDockClient) then
  342. begin
  343. TCnDockClient(DockControl).UnDockLeft := UnDockLeft;
  344. TCnDockClient(DockControl).UnDockTop := UnDockTop;
  345. TCnDockClient(DockControl).LastDockSite := GetLastDockSite(LastDockSiteName);
  346. if Visible then
  347. begin
  348. TCnDockClient(DockControl).ParentVisible := False;
  349. TCnDockClient(DockControl).MakeShowEvent;
  350. end else TCnDockClient(DockControl).MakeHideEvent;
  351. TCnDockClient(DockControl).VSPaneWidth := VSPaneWidth;
  352. end;
  353. DockControl.EnableDock := CanDocked;
  354. DockControl.LeftDock := LeftDocked;
  355. DockControl.TopDock := TopDocked;
  356. DockControl.BottomDock := BottomDocked;
  357. DockControl.RightDock := RightDocked;
  358. end;
  359. { TCnDockInfoTree }
  360. constructor TCnDockInfoTree.Create(TreeZone: TCnTreeZoneClass);
  361. begin
  362. inherited Create(TreeZone);
  363. FDockInfoIni := nil;
  364. FCnDockInfoStyle := isNone;
  365. FDataStream := TMemoryStream.Create;
  366. end;
  367. procedure TCnDockInfoTree.CreateZoneAndAddInfoFromApp(Control: TControl);
  368. var i: Integer;
  369. TreeZone: TCnDockInfoZone;
  370. ADockBaseControl: TCnDockBaseControl;
  371. TmpDockPanel: TCnDockPanel;
  372. begin
  373. TreeZone := TCnDockInfoZone(AddChildZone(CurrTreeZone, nil));
  374. with TreeZone do
  375. begin
  376. ParentName := TCnDockInfoZone(CurrTreeZone).DockFormName;
  377. SetDockInfoFromControlToNode(Control);
  378. if Control is TCnDockPanel then
  379. DockFormName := TCnDockInfoZone(CurrTreeZone).DockFormName +
  380. gs_CnDockInfoSplitter + Control.Name
  381. else DockFormName := Control.Name;
  382. FDataStream.Clear;
  383. if Control is TCnTabDockHostForm then
  384. TCnTabDockHostForm(Control).PageControl.SaveToStream(FDataStream)
  385. else if Control is TCnConjoinDockHostForm then
  386. TCnConjoinDockHostForm(Control).Panel.DockManager.SaveToStream(FDataStream)
  387. else if Control is TCnDockPanel then
  388. TCnDockPanel(Control).DockManager.SaveToStream(FDataStream);
  389. DockClientData := Cn_StreamDataToString(FDataStream);
  390. ADockBaseControl := FindDockBaseControl(Control);
  391. if ADockBaseControl <> nil then
  392. begin
  393. SetDockInfoFromDockControlToNode(ADockBaseControl);
  394. if Control is TCnTabDockHostForm then
  395. DockFormStyle := dsTab
  396. else if Control is TCnConjoinDockHostForm then
  397. DockFormStyle := dsConjoin
  398. else DockFormStyle := dsNormal;
  399. if ADockBaseControl is TCnDockClient then
  400. begin
  401. if Control is TCnDockableForm then
  402. begin
  403. with TCnDockableForm(Control).DockableControl do
  404. begin
  405. for i := 0 to DockClientCount -1 do
  406. begin
  407. CurrTreeZone := TreeZone;
  408. CreateZoneAndAddInfoFromApp(DockClients[i]);
  409. CurrTreeZone := TreeZone.GetParentZone;
  410. end;
  411. end;
  412. end;
  413. end else
  414. begin
  415. for i := 0 to 3 do
  416. begin
  417. CurrTreeZone := TreeZone;
  418. TmpDockPanel := TCnDockServer(ADockBaseControl).DockPanel[i];
  419. CreateZoneAndAddInfoFromApp(TmpDockPanel);
  420. if TmpDockPanel is TCnVSNETDockPanel then
  421. CreateZoneAndAddInfoFromApp(TCnVSNETDockPanel(TmpDockPanel).VSChannel.VSPopupPanel);
  422. CurrTreeZone := TreeZone.GetParentZone;
  423. end;
  424. end;
  425. end;
  426. if Control is TCnDockPanel then
  427. begin
  428. DockFormStyle := dsDockPanel;
  429. if Control is TCnVSPopupPanel then
  430. begin
  431. with TCnVSPopupPanel(Control) do
  432. begin
  433. for i := 0 to DockClientCount - 1 do
  434. begin
  435. CurrTreeZone := TreeZone;
  436. CreateZoneAndAddInfoFromApp(TWinControl(DockClients[i]));
  437. CurrTreeZone := TreeZone.GetParentZone;
  438. end;
  439. end;
  440. end else
  441. with TCnDockPanel(Control) do
  442. begin
  443. for i := 0 to DockClientCount - 1 do
  444. begin
  445. CurrTreeZone := TreeZone;
  446. CreateZoneAndAddInfoFromApp(TWinControl(DockClients[i]));
  447. CurrTreeZone := TreeZone.GetParentZone;
  448. end;
  449. end;
  450. end;
  451. end;
  452. end;
  453. procedure TCnDockInfoTree.CreateZoneAndAddInfoFromIni;
  454. var Sections: TStringList;
  455. i: Integer;
  456. procedure CreateZoneAndAddInfo(Index: Integer);
  457. var i: Integer;
  458. TreeZone: TCnDockInfoZone;
  459. begin
  460. TreeZone := TCnDockInfoZone(AddChildZone(CurrTreeZone, nil));
  461. with TreeZone, FDockInfoIni do
  462. begin
  463. {读取INI文件中的数据到一个树节点}
  464. DockFormName := Sections[Index];
  465. ParentName := ReadString(DockFormName, 'ParentName', 'ERROR');
  466. DockRect := Rect(ReadInteger(DockFormName, 'DockLeft', 0),
  467. ReadInteger(DockFormName, 'DockTop', 0),
  468. ReadInteger(DockFormName, 'DockRight', 100),
  469. ReadInteger(DockFormName, 'DockBottom', 100));
  470. LastDockSiteName:= ReadString(DockFormName, 'LastDockSiteName', 'ERROR');
  471. UnDockLeft := ReadInteger(DockFormName, 'UnDockLeft', 100);
  472. UnDockTop := ReadInteger(DockFormName, 'UnDockTop', 100);
  473. LRDockWidth := ReadInteger(DockFormName, 'LRDockWidth', 100);
  474. TBDockHeight := ReadInteger(DockFormName, 'TBDockHeight', 100);
  475. UnDockWidth := ReadInteger(DockFormName, 'UndockWidth', 100);
  476. UnDockHeight := ReadInteger(DockFormName, 'UndockHeight', 100);
  477. VSPaneWidth := ReadInteger(DockFormName, 'VSPaneWidth', 100);
  478. Visible := ReadBool(DockFormName, 'Visible', True);
  479. BorderStyle := TBorderStyle(ReadInteger(DockFormName, 'BorderStyle', 0));
  480. FormStyle := TFormStyle(ReadInteger(DockFormName, 'FormStyle', 0));
  481. WindowState := TWindowState(ReadInteger(DockFormName, 'WindowState', 0));
  482. DockFormStyle := TDockFormStyle(ReadInteger(DockFormName, 'DockFormStyle', 0));
  483. CanDocked := ReadBool(DockFormName, 'CanDocked', True);
  484. EachOtherDocked := ReadBool(DockFormName, 'EachOtherDocked', True);
  485. LeftDocked := ReadBool(DockFormName, 'LeftDocked', LeftDocked);
  486. TopDocked := ReadBool(DockFormName, 'TopDocked', True);
  487. RightDocked := ReadBool(DockFormName, 'RightDocked', True);
  488. BottomDocked := ReadBool(DockFormName, 'BottomDocked', True);
  489. DockClientData:= ReadString(DockFormName, 'DockClientData', '');
  490. end;
  491. for i := Index - 1 downto 0 do
  492. begin
  493. if FDockInfoIni.ReadString(Sections[i], 'ParentName', 'ERROR') = Sections[Index] then
  494. begin
  495. CurrTreeZone := TreeZone;
  496. CreateZoneAndAddInfo(i);
  497. CurrTreeZone := TreeZone.GetParentZone;
  498. end;
  499. end;
  500. end;
  501. begin
  502. Sections := TStringList.Create;
  503. try
  504. FDockInfoIni.ReadSections(Sections);
  505. {遍历INI文件,把里面的信息取出来放在树中}
  506. FCnDockInfoStyle := isReadFileInfo;
  507. for i := Sections.Count - 1 downto 0 do
  508. begin
  509. if FDockInfoIni.ReadString(Sections[i], 'ParentName', 'ERROR') = '' then
  510. CreateZoneAndAddInfo(i);
  511. end;
  512. FCnDockInfoStyle := isNone;
  513. finally
  514. Sections.Free;
  515. end;
  516. end;
  517. procedure TCnDockInfoTree.CreateZoneAndAddInfoFromReg;
  518. var FormList: TStringList;
  519. procedure CreateZoneAndAddInfo(Index: Integer);
  520. var i: Integer;
  521. TreeZone: TCnDockInfoZone;
  522. begin
  523. FDockInfoReg.OpenKey(FRegName, False);
  524. if FDockInfoReg.KeyExists(FormList[Index]) then
  525. begin
  526. FDockInfoReg.OpenKey(FRegName + '\' + FormList[Index], False);
  527. TreeZone := TCnDockInfoZone(AddChildZone(CurrTreeZone, nil));
  528. with TreeZone, FDockInfoReg do
  529. begin
  530. {读取注册表中的数据到一个树节点}
  531. DockFormName := FormList[Index];
  532. ParentName := ReadString('ParentName');
  533. DockRect := Rect(ReadInteger('DockLeft'),
  534. ReadInteger('DockTop'),
  535. ReadInteger('DockRight'),
  536. ReadInteger('DockBottom'));
  537. LRDockWidth := ReadInteger('LRDockWidth');
  538. LastDockSiteName:= ReadString('LastDockSiteName');
  539. UnDockLeft := ReadInteger('UnDockLeft');
  540. UnDockTop := ReadInteger('UnDockTop');
  541. TBDockHeight := ReadInteger('TBDockHeight');
  542. UnDockWidth := ReadInteger('UnDockWidth');
  543. UnDockHeight := ReadInteger('UnDockHeight');
  544. VSPaneWidth := ReadInteger('VSPaneWidth');
  545. Visible := ReadBool('Visible');
  546. BorderStyle := TBorderStyle(ReadInteger('BorderStyle'));
  547. FormStyle := TFormStyle(ReadInteger('FormStyle'));
  548. WindowState := TWindowState(ReadInteger('WindowState'));
  549. DockFormStyle := TDockFormStyle(ReadInteger('DockFormStyle'));
  550. CanDocked := ReadBool('CanDocked');
  551. EachOtherDocked := ReadBool('EachOtherDocked');
  552. LeftDocked := ReadBool('LeftDocked');
  553. TopDocked := ReadBool('TopDocked');
  554. RightDocked := ReadBool('RightDocked');
  555. BottomDocked := ReadBool('BottomDocked');
  556. DockClientData:= ReadString('DockClientData');
  557. end;
  558. for i := Index - 1 downto 0 do
  559. begin
  560. FDockInfoReg.OpenKey(FRegName + '\' + FormList[i], False);
  561. if FDockInfoReg.ReadString('ParentName') = FormList[Index] then
  562. begin
  563. CurrTreeZone := TreeZone;
  564. CreateZoneAndAddInfo(i);
  565. CurrTreeZone := TreeZone.GetParentZone;
  566. end;
  567. end;
  568. end;
  569. end;
  570. var
  571. cp, cp1: PChar;
  572. i: Integer;
  573. begin
  574. FormList := TStringList.Create;
  575. try
  576. if FDockInfoReg.OpenKey(FRegName, False) then
  577. begin
  578. cp := PChar(FDockInfoReg.ReadString('FormNames'));
  579. cp1 := StrPos(cp, '\');
  580. while cp1 <> nil do
  581. begin
  582. cp1^ := #0;
  583. FormList.Add(string(cp));
  584. cp := cp1 + 1;
  585. cp1 := StrPos(cp, '\');
  586. end;
  587. FCnDockInfoStyle := isReadFileInfo;
  588. for i := FormList.Count - 1 downto 0 do
  589. begin
  590. FDockInfoReg.OpenKey(FRegName + '\' + FormList[i], False);
  591. if FDockInfoReg.ReadString('ParentName') = '' then
  592. CreateZoneAndAddInfo(i);
  593. end;
  594. FCnDockInfoStyle := isNone;
  595. end;
  596. finally
  597. FDockInfoReg.CloseKey;
  598. FormList.Free;
  599. end;
  600. end;
  601. destructor TCnDockInfoTree.Destroy;
  602. begin
  603. FDataStream.Free;
  604. inherited Destroy;
  605. end;
  606. procedure TCnDockInfoTree.ReadInfoFromIni;
  607. begin
  608. CreateZoneAndAddInfoFromIni;
  609. {使所有的停靠窗体成为浮动的}
  610. DoFloatAllForm;
  611. {处理完所有的消息}
  612. Application.ProcessMessages;
  613. {中序遍历树}
  614. FCnDockInfoStyle := isReadFileInfo;
  615. MiddleScanTree(TopTreeZone);
  616. FCnDockInfoStyle := isNone;
  617. end;
  618. procedure TCnDockInfoTree.ReadInfoFromReg(RegName: string);
  619. begin
  620. FRegName := RegName;
  621. CreateZoneAndAddInfoFromReg;
  622. {使所有的停靠窗体成为浮动的}
  623. DoFloatAllForm;
  624. {处理完所有的消息}
  625. Application.ProcessMessages;
  626. {中序遍历树}
  627. FCnDockInfoStyle := isReadRegInfo;
  628. MiddleScanTree(TopTreeZone);
  629. FCnDockInfoStyle := isNone;
  630. end;
  631. procedure TCnDockInfoTree.ScanTreeZone(TreeZone: TCnBaseZone);
  632. var i: Integer;
  633. begin
  634. if (FCnDockInfoStyle = isReadFileInfo) or (FCnDockInfoStyle = isReadRegInfo) then
  635. begin
  636. {从文件中读停靠信息}
  637. for i := 0 to TreeZone.GetChildCount - 1 do
  638. begin
  639. with TCnDockInfoZone(TreeZone.GetChildZone(i)) do
  640. DockControl := FindDockForm(DockFormName);
  641. end;
  642. SetDockControlInfo(TCnDockInfoZone(TreeZone));
  643. end else
  644. if FCnDockInfoStyle = isWriteFileInfo then
  645. begin
  646. {把停靠信息写到文件中}
  647. if TreeZone <> TopTreeZone then
  648. begin
  649. with TCnDockInfoZone(TreeZone), FDockInfoIni do
  650. begin
  651. WriteString(DockFormName,
  652. 'ParentName', ParentName);
  653. WriteInteger(DockFormName,
  654. 'DockLeft', DockRect.Left);
  655. WriteInteger(DockFormName,
  656. 'DockTop', DockRect.Top);
  657. WriteInteger(DockFormName,
  658. 'DockRight', DockRect.Right);
  659. WriteInteger(DockFormName,
  660. 'DockBottom', DockRect.Bottom);
  661. WriteString(DockFormName,
  662. 'LastDockSiteName', LastDockSiteName);
  663. WriteInteger(DockFormName,
  664. 'UnDockLeft', UnDockLeft);
  665. WriteInteger(DockFormName,
  666. 'UnDockTop', UnDockTop);
  667. WriteInteger(DockFormName,
  668. 'LRDockWidth', LRDockWidth);
  669. WriteInteger(DockFormName,
  670. 'TBDockHeight', TBDockHeight);
  671. WriteInteger(DockFormName,
  672. 'UnDockWidth', UnDockWidth);
  673. WriteInteger(DockFormName,
  674. 'UnDockHeight', UnDockHeight);
  675. WriteInteger(DockFormName,
  676. 'VSPaneWidth', VSPaneWidth);
  677. WriteBool(DockFormName,
  678. 'Visible', Visible);
  679. WriteInteger(DockFormName,
  680. 'BorderStyle', Integer(BorderStyle));
  681. WriteInteger(DockFormName,
  682. 'WindowState', Integer(WindowState));
  683. WriteInteger(DockFormName,
  684. 'FormStyle', Integer(FormStyle));
  685. WriteInteger(DockFormName,
  686. 'DockFormStyle', Integer(DockFormStyle));
  687. WriteBool(DockFormName,
  688. 'CanDocked', CanDocked);
  689. WriteBool(DockFormName,
  690. 'EachOtherDocked', EachOtherDocked);
  691. WriteBool(DockFormName,
  692. 'LeftDocked', LeftDocked);
  693. WriteBool(DockFormName,
  694. 'TopDocked', TopDocked);
  695. WriteBool(DockFormName,
  696. 'RightDocked', RightDocked);
  697. WriteBool(DockFormName,
  698. 'BottomDocked', BottomDocked);
  699. WriteString(DockFormName,
  700. 'DockClientData', DockClientData);
  701. end;
  702. end;
  703. end else if FCnDockInfoStyle = isWriteRegInfo then
  704. begin
  705. if TreeZone <> TopTreeZone then
  706. begin
  707. with TCnDockInfoZone(TreeZone), FDockInfoReg do
  708. begin
  709. OpenKey(FRegName, True);
  710. WriteString('FormNames', ReadString('FormNames') + DockFormName + '\');
  711. OpenKey(FRegName + '\' + DockFormName, True);
  712. WriteString('ParentName', ParentName);
  713. WriteInteger('DockLeft', DockRect.Left);
  714. WriteInteger('DockTop', DockRect.Top);
  715. WriteInteger('DockRight', DockRect.Right);
  716. WriteInteger('DockBottom', DockRect.Bottom);
  717. WriteString('LastDockSiteName', LastDockSiteName);
  718. WriteInteger('UnDockLeft', UnDockLeft);
  719. WriteInteger('UnDockTop', UnDockTop);
  720. WriteInteger('LRDockWidth', LRDockWidth);
  721. WriteInteger('TBDockHeight', TBDockHeight);
  722. WriteInteger('UnDockWidth', UnDockWidth);
  723. WriteInteger('UnDockHeight', UnDockHeight);
  724. WriteInteger('VSPaneWidth', VSPaneWidth);
  725. WriteBool('Visible', Visible);
  726. WriteInteger('BorderStyle', Integer(BorderStyle));
  727. WriteInteger('FormStyle', Integer(FormStyle));
  728. WriteInteger('WindowState', Integer(WindowState));
  729. WriteInteger('DockFormStyle', Integer(DockFormStyle));
  730. WriteBool('CanDocked', CanDocked);
  731. WriteBool('EachOtherDocked', EachOtherDocked);
  732. WriteBool('LeftDocked', LeftDocked);
  733. WriteBool('TopDocked', TopDocked);
  734. WriteBool('RightDocked', RightDocked);
  735. WriteBool('BottomDocked', BottomDocked);
  736. WriteString('DockClientData', DockClientData);
  737. CloseKey;
  738. end;
  739. end;
  740. end;
  741. inherited ScanTreeZone(TreeZone);
  742. end;
  743. {在应用程序中查找名字为FormName的窗体}
  744. function TCnDockInfoTree.FindDockForm(FormName: string): TCustomForm;
  745. begin
  746. if Pos(gs_CnDockInfoSplitter, FormName) > 0 then Result := nil
  747. else
  748. begin
  749. Result := Cn_FindDockFormWithName(FormName);
  750. end;
  751. end;
  752. {查找名字为ControlName的WinControl}
  753. (*function TCnDockInfoTree.FindDockHost(ControlName: string): TWinControl;
  754. var Index: Word;
  755. DockServer: TCnDockServer;
  756. begin
  757. Result := FindDockForm(ControlName);
  758. if Result = nil then
  759. begin
  760. Index := Pos(gs_CnDockInfoSplitter, ControlName);
  761. if Index = 0 then Exit;
  762. Result := FindDockForm(Copy(ControlName, 1, Index - 1));
  763. if Result <> nil then
  764. begin
  765. DockServer := FindDockServer(Result);
  766. if DockServer <> nil then
  767. with DockServer do
  768. begin
  769. if Pos('TopDockPanel', ControlName) > Index then
  770. Result := TopDockPanel
  771. else if Pos('LeftDockPanel', ControlName) > Index then
  772. Result := LeftDockPanel
  773. else if Pos('BottomDockPanel', ControlName) > Index then
  774. Result := BottomDockPanel
  775. else if Pos('RightDockPanel', ControlName) > Index then
  776. Result := RightDockPanel;
  777. if (Result <> nil) and (Pos('PopupPanel', ControlName) > 20) then
  778. Result := TCnVSNETDockPanel(Result).VSChannel.VSPopupPanel;
  779. end;
  780. end;
  781. end;
  782. end;*)
  783. {创建平铺或分页窗体}
  784. function TCnDockInfoTree.CreateHostControl(ATreeZone: TCnDockInfoZone): TWinControl;
  785. var Form: TForm;
  786. DockClient: TCnDockClient;
  787. begin
  788. Result := nil;
  789. case ATreeZone.DockFormStyle of
  790. dsConjoin:
  791. begin
  792. Form := TCnConjoinDockHostForm.Create(Application);
  793. DockClient := FindDockClient(TCnDockInfoZone(ATreeZone.ChildZone).DockControl);
  794. Result := DockClient.CreateConjoinPanelClass(Form).Parent;
  795. end;
  796. dsTab:
  797. begin
  798. Form := TCnTabDockHostForm.Create(Application);
  799. DockClient := FindDockClient(TCnDockInfoZone(ATreeZone.ChildZone).DockControl);
  800. Result := DockClient.CreateTabDockClass(Form).Parent;
  801. end;
  802. end;
  803. if Result <> nil then
  804. begin
  805. Result.Name := ATreeZone.DockFormName;
  806. end;
  807. end;
  808. procedure TCnDockInfoTree.SetDockControlInfo(ATreeZone: TCnDockInfoZone);
  809. var
  810. ADockBaseControl: TCnDockBaseControl;
  811. Host: TWinControl;
  812. begin
  813. with ATreeZone do
  814. begin
  815. if DockFormName = '' then Exit;
  816. Host := FindDockHost(DockFormName);
  817. if (Host = nil) and (ATreeZone.GetChildControlCount > 1) then
  818. Host := CreateHostControl(ATreeZone);
  819. if (Host <> nil) and (DockClientData <> '') then
  820. begin
  821. {请空TMemoryStream}
  822. FDataStream.Clear;
  823. {把字符串转换成流格式}
  824. Cn_StringToStreamData(FDataStream, DockClientData);
  825. {开始读}
  826. FDataStream.Position := 0;
  827. if Host is TCnTabDockHostForm then
  828. begin
  829. {如果是分页窗体,就调用她的LoadFromStream函数}
  830. with TCnTabDockHostForm(Host).PageControl do
  831. begin
  832. DisableAlign;
  833. try LoadFromStream(FDataStream);
  834. finally EnableAlign; end;
  835. end;
  836. end else if Host is TCnConjoinDockHostForm then
  837. begin
  838. {如果是平铺窗体,就调用她的DockManageer的LoadFromStream函数}
  839. with TCnConjoinDockHostForm(Host).Panel do
  840. begin
  841. DisableAlign;
  842. try DockManager.LoadFromStream(FDataStream);
  843. finally EnableAlign; end;
  844. end;
  845. end else if Host is TCnDockPanel then
  846. begin
  847. {如果是停靠服务器,就调用她的DockManageer的LoadFromStream函数}
  848. with TCnDockPanel(Host) do
  849. begin
  850. DisableAlign;
  851. try DockManager.LoadFromStream(FDataStream);
  852. finally EnableAlign; end;
  853. end;
  854. end;
  855. end;
  856. if Host <> nil then
  857. begin
  858. SetDockInfoFromNodeToControl(Host);
  859. ADockBaseControl := FindDockBaseControl(Host);
  860. if ADockBaseControl <> nil then
  861. SetDockInfoFromNodeToDockControl(ADockBaseControl);
  862. end;
  863. end;
  864. end;
  865. procedure TCnDockInfoTree.WriteInfoToIni;
  866. var Sections: TStringList;
  867. i: Integer;
  868. begin
  869. Sections := TStringList.Create;
  870. try
  871. FDockInfoIni.ReadSections(Sections);
  872. {首先把INI文件清空}
  873. for i := 0 to Sections.Count - 1 do
  874. FDockInfoIni.EraseSection(Sections[i]);
  875. finally
  876. Sections.Free;
  877. end;
  878. {中序遍历树}
  879. FCnDockInfoStyle := isWriteFileInfo;
  880. MiddleScanTree(TopTreeZone);
  881. FCnDockInfoStyle := isNone;
  882. end;
  883. procedure TCnDockInfoTree.WriteInfoToReg(RegName: string);
  884. begin
  885. try
  886. {删除路径名为RegName的注册表项}
  887. if FDockInfoReg.OpenKey(RegName, False) then
  888. FDockInfoReg.DeleteKey(RegName);
  889. {再次创建她}
  890. FDockInfoReg.CreateKey(RegName);
  891. FDockInfoReg.CloseKey;
  892. FRegName := RegName;
  893. {中序遍历她}
  894. FCnDockInfoStyle := isWriteRegInfo;
  895. MiddleScanTree(TopTreeZone);
  896. FCnDockInfoStyle := isNone;
  897. finally
  898. FDockInfoReg.CloseKey;
  899. end;
  900. end;
  901. end.