CnVIDDockStyle.pas 156 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702
  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. { 具有类似Visual InterDev的停靠风格 }
  23. { lbVIDDockStyle 单元 }
  24. { }
  25. { 版权 (C) 2002,2003 鲁小班 }
  26. { }
  27. {*******************************************************}
  28. {WM_SETTINGCHANGE: 当设置桌面属性的外观后,Windows会给每一个应用程序发送
  29. WM_SETTINGCHANGE消息,这时候可以截获这个消息来设置
  30. TlbVIDConjoinServerOption中的属性。}
  31. {WM_SYSCOLORCHANGE: 当设置桌面属性的颜色外观后,Windows会给每一个应用程序发送
  32. WM_SYSCOLORCHANGE消息,这时候可以截获这个消息来设置
  33. TlbVIDConjoinServerOption中的属性的颜色部分。}
  34. unit CnVIDDockStyle;
  35. {* |<PRE>
  36. ================================================================================
  37. * 软件名称:不可视工具组件包停靠单元
  38. * 单元名称:类似于Visual InterDev的停靠风格的单元
  39. * 单元作者:CnPack开发组 周益波(鲁小班)
  40. * 备 注:本单元由原作者授权CnPack开发组移植,已保留原作者版权信息
  41. * 开发平台:
  42. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
  43. * 本 地 化:该单元中的字符串均符合本地化处理方式
  44. * 单元标识:$Id$
  45. * 修改记录:2007.07.13 V1.0
  46. * 移植单元
  47. ================================================================================
  48. |</PRE>}
  49. interface
  50. {$I CnPack.inc}
  51. uses
  52. Windows, Classes, Controls, Math, Messages, Graphics, ComCtrls, Extctrls,
  53. ImgList, Forms, SysUtils, Dialogs, CnDockFormControl, CnDockSupportControl,
  54. CnDockTree, CnConsts, CnCompConsts;
  55. const
  56. VIDDefaultGrabbersSize = 18;
  57. VIDDefaultSplitterWidth = 4;
  58. type
  59. { VID平铺服务器的选项类 }
  60. TCnVIDConjoinServerOption = class(TCnBasicConjoinServerOption)
  61. private
  62. FTextEllipsis: Boolean;
  63. FTextAlignment: TAlignment;
  64. FInactiveTitleEndColor: TColor;
  65. FInactiveTitleStartColor: TColor;
  66. FActiveTitleEndColor: TColor;
  67. FActiveTitleStartColor: TColor;
  68. FSystemInfo: Boolean;
  69. FActiveFont: TFont;
  70. FInactiveFont: TFont;
  71. procedure SetActiveTitleEndColor(const Value: TColor);
  72. procedure SetActiveTitleStartColor(const Value: TColor);
  73. procedure SetInactiveTitleEndColor(const Value: TColor);
  74. procedure SetInactiveTitleStartColor(const Value: TColor);
  75. procedure SetTextAlignment(const Value: TAlignment);
  76. procedure SetTextEllipsis(const Value: Boolean);
  77. procedure SetSystemInfo(const Value: Boolean);
  78. procedure SetActiveFont(const Value: TFont);
  79. procedure SetInactiveFont(const Value: TFont);
  80. protected
  81. // 重新设置DockStyle的选项
  82. procedure ResetDockControlOption; override;
  83. procedure SetDefaultSystemCaptionInfo; virtual;
  84. public
  85. constructor Create(ADockStyle: TCnBasicDockStyle); override;
  86. destructor Destroy; override;
  87. procedure Assign(Source: TPersistent); override;
  88. procedure SetActiveTitleEndColor_WithoutChangeSystemInfo(const Value: TColor);
  89. procedure SetActiveTitleStartColor_WithoutChangeSystemInfo(const Value: TColor);
  90. procedure SetInactiveTitleEndColor_WithoutChangeSystemInfo(const Value: TColor);
  91. procedure SetInactiveTitleStartColor_WithoutChangeSystemInfo(const Value: TColor);
  92. procedure SetTextAlignment_WithoutChangeSystemInfo(const Value: TAlignment);
  93. procedure SetTextEllipsis_WithoutChangeSystemInfo(const Value: Boolean);
  94. procedure SetActiveFont_WithoutChangeSystemInfo(const Value: TFont);
  95. procedure SetInactiveFont_WithoutChangeSystemInfo(const Value: TFont);
  96. published
  97. { 当页面获得焦点的时候的字体颜色 }
  98. property ActiveFont: TFont read FActiveFont write SetActiveFont;
  99. { 当页面失去焦点的时候的字体颜色 }
  100. property InactiveFont: TFont read FInactiveFont write SetInactiveFont;
  101. { Caption的对齐方式 }
  102. property TextAlignment: TAlignment read FTextAlignment
  103. write SetTextAlignment;
  104. { 当客户窗体获得焦点的时候标题栏的开始部分颜色 }
  105. property ActiveTitleStartColor: TColor read FActiveTitleStartColor
  106. write SetActiveTitleStartColor;
  107. { 当客户窗体获得焦点的时候标题栏的结束部分颜色 }
  108. property ActiveTitleEndColor: TColor read FActiveTitleEndColor
  109. write SetActiveTitleEndColor;
  110. { 当客户窗体失去焦点的时候标题栏的开始部分颜色 }
  111. property InactiveTitleStartColor: TColor read FInactiveTitleStartColor
  112. write SetInactiveTitleStartColor;
  113. { 当客户窗体失去焦点的时候标题栏的结束部分颜色 }
  114. property InactiveTitleEndColor: TColor read FInactiveTitleEndColor
  115. write SetInactiveTitleEndColor;
  116. { 标题栏上的文字是否有省略号 }
  117. property TextEllipsis: Boolean read FTextEllipsis write SetTextEllipsis;
  118. { 是否和系统信息是一样的 }
  119. property SystemInfo: Boolean read FSystemInfo write SetSystemInfo;
  120. end;
  121. { VID分页服务器的选项类 }
  122. TCnVIDTabServerOption = class(TCnBasicTabServerOption)
  123. private
  124. FActiveFont: TFont;
  125. FActiveSheetColor: TColor;
  126. FHotTrackColor: TColor;
  127. FInactiveFont: TFont;
  128. FInactiveSheetColor: TColor;
  129. FShowTabImages: Boolean;
  130. function GetActiveFont: TFont;
  131. function GetActiveSheetColor: TColor;
  132. function GetHotTrackColor: TColor;
  133. function GetInactiveFont: TFont;
  134. function GetInactiveSheetColor: TColor;
  135. function GetShowTabImages: Boolean;
  136. procedure SetActiveFont(const Value: TFont);
  137. procedure SetActiveSheetColor(const Value: TColor);
  138. procedure SetHotTrackColor(const Value: TColor);
  139. procedure SetInactiveFont(const Value: TFont);
  140. procedure SetInactiveSheetColor(const Value: TColor);
  141. procedure SetShowTabImages(const Value: Boolean);
  142. protected
  143. // 重新设置DockStyle的选项
  144. procedure ResetDockControlOption; override;
  145. { 重新设置TCnTabPageControl的属性 }
  146. procedure ResetTabPageControl(APage: TCnTabPageControl); override;
  147. public
  148. constructor Create(ADockStyle: TCnBasicDockStyle); override;
  149. destructor Destroy; override;
  150. procedure Assign(Source: TPersistent); override;
  151. procedure SetTabPosition(const Value: TTabPosition); override;
  152. published
  153. { 当页面获得焦点的时候的颜色 }
  154. property ActiveSheetColor: TColor read GetActiveSheetColor write SetActiveSheetColor;
  155. { 当页面失去焦点的时候的颜色 }
  156. property InactiveSheetColor: TColor read GetInactiveSheetColor write SetInactiveSheetColor;
  157. { 当页面获得焦点的时候的字体颜色 }
  158. property ActiveFont: TFont read GetActiveFont write SetActiveFont;
  159. { 当页面失去焦点的时候的字体颜色 }
  160. property InactiveFont: TFont read GetInactiveFont write SetInactiveFont;
  161. { 高亮显示的颜色 }
  162. property HotTrackColor: TColor read GetHotTrackColor write SetHotTrackColor;
  163. { 是否显示图片 }
  164. property ShowTabImages: Boolean read GetShowTabImages write SetShowTabImages;
  165. end;
  166. { 当TCnVIDConjoinServerOption的SystemInfo属性改变的时候触发这个事件 }
  167. TSystemInfoChange = procedure(Value: Boolean) of object;
  168. TCnVIDDockStyle = class(TCnAdvDockStyle)
  169. private
  170. FSystemInfoChange: TSystemInfoChange;
  171. protected
  172. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  173. function DockClientWindowProc(DockClient: TCnDockClient; var Message: TMessage): Boolean; override;
  174. procedure ParentFormWindowProc(var Message: TMessage); override;
  175. procedure FormDockDrop(DockClient: TCnDockClient;
  176. Source: TCnDragDockObject; X, Y: Integer); override;
  177. procedure FormGetSiteInfo(Source: TCnDragDockObject; DockClient: TCnDockClient;
  178. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  179. var CanDock: Boolean); override;
  180. procedure FormDockOver(DockClient: TCnDockClient; Source: TCnDragDockObject; X, Y: Integer;
  181. State: TDragState; var Accept: Boolean); override;
  182. procedure FormStartDock(DockClient: TCnDockClient;
  183. var Source: TCnDragDockObject); override;
  184. procedure FormGetDockEdge(DockClient: TCnDockClient; Source: TCnDragDockObject;
  185. MousePos: TPoint; var DropAlign: TAlign); override;
  186. { ------------------------------------------------------------------------ }
  187. procedure CreateConjoinServerOption(var Option: TCnBasicConjoinServerOption); override;
  188. procedure CreateTabServerOption(var Option: TCnBasicTabServerOption); override;
  189. { ------------------------------------------------------------------------ }
  190. procedure AssignConjoinServerOption(APanel: TCnCustomDockPanel); override;
  191. procedure AssignTabServerOption(APage: TCnTabPageControl); override;
  192. { ------------------------------------------------------------------------ }
  193. procedure DoSystemInfoChange(Value: Boolean);
  194. public
  195. constructor Create(AOwner: TComponent); override;
  196. destructor Destroy; override;
  197. // class function GetControlName: string; override;
  198. function GetControlName: string; override;
  199. procedure SetDockBaseControl(IsCreate: Boolean;
  200. DockBaseControl: TCnDockBaseControl); override;
  201. published
  202. property SystemInfoChange: TSystemInfoChange read FSystemInfoChange
  203. write FSystemInfoChange;
  204. property ConjoinServerOption;
  205. property TabServerOption;
  206. { ------------------------------------------------------------------------ }
  207. end;
  208. TCnVIDDockSplitter = class(TCnDockSplitter);
  209. TCnVIDDockPanel = class(TCnAdvDockPanel)
  210. protected
  211. procedure CustomGetSiteInfo(Source: TCnDragDockObject;
  212. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  213. var CanDock: Boolean); override;
  214. procedure CustomStartDock(var Source: TCnDragDockObject); override;
  215. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  216. procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer;
  217. State: TDragState; var Accept: Boolean); override;
  218. procedure CustomGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint;
  219. var DropAlign: TAlign); override;
  220. function CreateDockManager: IDockManager; override;
  221. public
  222. constructor Create(AOwner: TComponent); override;
  223. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  224. end;
  225. TCnVIDConjoinPanel = class(TCnAdvConjoinPanel)
  226. protected
  227. procedure CustomGetSiteInfo(Source: TCnDragDockObject;
  228. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  229. var CanDock: Boolean); override;
  230. procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer;
  231. State: TDragState; var Accept: Boolean); override;
  232. procedure CustomGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign); override;
  233. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  234. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  235. function CreateDockManager: IDockManager; override;
  236. public
  237. procedure UpdateCaption(Exclude: TControl); override;
  238. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  239. end;
  240. TCnVIDDockZone = class(TCnAdvDockZone)
  241. protected
  242. function GetSplitterLimit(IsMin: Boolean): Integer; override;
  243. public
  244. destructor Destroy; override;
  245. procedure Insert(DockSize: Integer; Hide: Boolean); override;
  246. procedure Remove(DockSize: Integer; Hide: Boolean); override;
  247. end;
  248. TCnVIDDockTree = class(TCnAdvDockTree)
  249. private
  250. FDropOnZone: TCnDockZone;
  251. FLockDropDockSizeCount: Integer;
  252. // 标题栏文字离左边界的距离
  253. FCaptionLeftOffset: Integer;
  254. // 标题栏文字离右边界的距离
  255. FCaptionRightOffset: Integer;
  256. procedure LockDropDockSize;
  257. procedure UnlockDropDockSize;
  258. procedure SetCaptionLeftOffset(const Value: Integer);
  259. procedure SetCaptionRightOffset(const Value: Integer);
  260. protected
  261. { 当停靠来的控件是TCnConjoinPanel的时候,先把TCnConjoinPanel中的停靠信息
  262. 存储在Stream流中,然后再把这些信息取出来重新构造DockTree的结构,使其符合原来的结构 }
  263. procedure InsertControlFromConjoinHost(Control: TControl;
  264. InsertAt: TAlign; DropCtl: TControl); virtual;
  265. { 忽略掉没有用的信息 }
  266. procedure IgnoreZoneInfor(Stream: TMemoryStream); virtual;
  267. { 调整Control控件的大小 }
  268. procedure AdjustDockRect(Control: TControl; var ARect: TRect); override;
  269. procedure WindowProc(var Message: TMessage); override;
  270. procedure SplitterMouseUp; override;
  271. function GetTopGrabbersHTFlag(const MousePos: TPoint;
  272. out HTFlag: Integer; Zone: TCnDockZone): TCnDockZone; override;
  273. function GetGrabbersPosition: TGrabbersPosition; override;
  274. procedure GetSiteInfo(Client: TControl;
  275. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean); override;
  276. procedure InsertControl(Control: TControl; InsertAt: TAlign;
  277. DropCtl: TControl); override;
  278. procedure InsertSibling(NewZone, SiblingZone: TCnDockZone;
  279. InsertLast, Update: Boolean); override;
  280. procedure InsertNewParent(NewZone, SiblingZone: TCnDockZone;
  281. ParentOrientation: TDockOrientation; InsertLast, Update: Boolean); override;
  282. procedure DrawDockGrabber(Control: TControl; const ARect: TRect); override;
  283. procedure DrawSplitterRect(const ARect: TRect); override;
  284. { 重画把手的边缘 }
  285. procedure PaintDockGrabberRect(Canvas: TCanvas; Control: TControl;
  286. const ARect: TRect); virtual;
  287. { 重画关闭按钮 }
  288. procedure DrawCloseButton(Canvas: TCanvas; Zone: TCnDockZone;
  289. Left, Top: Integer); virtual;
  290. procedure ResetBounds(Force: Boolean); override;
  291. procedure SetActiveControl(const Value: TControl); override;
  292. procedure DrawDockSiteRect; override;
  293. procedure PositionDockRect(Client, DropCtl: TControl; DropAlign: TAlign;
  294. var DockRect: TRect); override;
  295. function GetDockEdge(DockRect: TRect; MousePos: TPoint;
  296. var DropAlign: TAlign; Control: TControl): TControl; override;
  297. procedure RemoveZone(Zone: TCnDockZone; Hide: Boolean = True); override;
  298. procedure GetCaptionRect(var Rect: TRect); override;
  299. property CaptionLeftOffset: Integer read FCaptionLeftOffset write SetCaptionLeftOffset;
  300. property CaptionRightOffset: Integer read FCaptionRightOffset write SetCaptionRightOffset;
  301. public
  302. constructor Create(DockSite: TWinControl;
  303. CnDockZoneClass: TCnDockZoneClass); override;
  304. destructor Destroy; override;
  305. end;
  306. TCnVIDTabPageControl = class;
  307. TCnVIDDockTabSheet = class(TCnDockTabSheet)
  308. private
  309. FTabWidth: Integer;
  310. FShowTabWidth: Integer;
  311. FIsSourceDockClient: Boolean;
  312. procedure SetTabWidth(const Value: Integer);
  313. procedure WMSETTEXT(var Message: TMessage); message WM_SETTEXT;
  314. procedure SetSheetSort(CaptionStr: string);
  315. protected
  316. procedure SetPageControl(APageControl: TCnDockPageControl); override;
  317. property TabWidth: Integer read FTabWidth write SetTabWidth;
  318. property ShowTabWidth: Integer read FShowTabWidth;
  319. procedure Loaded; override;
  320. procedure UpdateTabShowing; override;
  321. public
  322. constructor Create(AOwner: TComponent); override;
  323. destructor Destroy; override;
  324. published
  325. property BorderWidth;
  326. property Caption;
  327. property DragMode;
  328. property Enabled;
  329. property Font;
  330. property Height stored False;
  331. property Highlighted;
  332. property ImageIndex;
  333. property Left stored False;
  334. property Constraints;
  335. property PageIndex;
  336. property ParentFont;
  337. property ParentShowHint;
  338. property PopupMenu;
  339. property ShowHint;
  340. property TabVisible;
  341. property Top stored False;
  342. property Visible stored False;
  343. property Width stored False;
  344. property OnContextPopup;
  345. property OnDragDrop;
  346. property OnDragOver;
  347. property OnEndDrag;
  348. property OnEnter;
  349. property OnExit;
  350. property OnHide;
  351. property OnMouseDown;
  352. property OnMouseMove;
  353. property OnMouseUp;
  354. property OnResize;
  355. property OnShow;
  356. property OnStartDrag;
  357. end;
  358. TCnTabPanel = class(TCustomControl)
  359. private
  360. FPage: TCnVIDTabPageControl;
  361. FActiveSheetColor: TColor; //获得焦点的页面的背景颜色
  362. FHotTrackColor: TColor; //热点的颜色
  363. FActiveFont, //获得焦点的页面的字体
  364. FInactiveFont: TFont; //失去焦点的页面的字体
  365. FTabLeftOffset: Integer; //页面左边距
  366. FTabRightOffset: Integer; //页面右边距
  367. FTabTopOffset: Integer; //页面上边距
  368. FTabBottomOffset: Integer; //页面下边距
  369. FCaptionLeftOffset: Integer; //标题左边距
  370. FCaptionRightOffset: Integer; //标题右边距
  371. FCaptionTopOffset: Integer; //标题上边距
  372. FTabSplitterWidth: Integer; //页面间距
  373. FTabHeight: Integer; //页面高度
  374. FSortList: TList; //按照Tab中的文字的长度排列循序的列表
  375. FSelectSheet: TCnVIDDockTabSheet;//当前被选中的TabSheet
  376. FTempPages: TList; //存储临时Tab的列表
  377. FSelectHotIndex: Integer; //当前被选中的高亮显示的Tab的索引
  378. FShowTabImages: Boolean; //是否显示Tab中的图象
  379. procedure SetPage(const Value: TCnVIDTabPageControl);
  380. function GetTotalTabWidth: Integer;
  381. procedure SetTotalTabWidth(const Value: Integer);
  382. function GetMinTabWidth: TCnDockTabSheet;
  383. function GetMaxTabWidth: TCnDockTabSheet;
  384. procedure SetTabBottomOffset(const Value: Integer);
  385. procedure SetTabLeftOffset(const Value: Integer);
  386. procedure SetTabRightOffset(const Value: Integer);
  387. procedure SetTabTopOffset(const Value: Integer);
  388. procedure SetCaptionLeftOffset(const Value: Integer);
  389. procedure SetCaptionRightOffset(const Value: Integer);
  390. procedure SetCaptionTopOffset(const Value: Integer);
  391. procedure SetTabSplitterWidth(const Value: Integer);
  392. function GetSorts(Index: Integer): TCnVIDDockTabSheet;
  393. function GetPanelHeight: Integer;
  394. function GetPanelWidth: Integer;
  395. procedure SetPanelHeight(const Value: Integer);
  396. function FindSheetWithPos(cX, cY, cTopOffset, cBottomOffset: Integer): Integer;
  397. function GetDockClientFromPageIndex(Index: Integer): TControl;
  398. procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  399. procedure SetShowTabImages(const Value: Boolean);
  400. procedure SetTabHeight(const Value: Integer);
  401. protected
  402. procedure Paint; override;
  403. procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  404. X, Y: Integer); override;
  405. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  406. procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  407. X, Y: Integer); override;
  408. function GetPageIndexFromMousePos(X, Y: Integer): Integer; virtual;
  409. procedure SetShowTabWidth;
  410. property TotalTabWidth: Integer read GetTotalTabWidth write SetTotalTabWidth;
  411. property MinTabWidth: TCnDockTabSheet read GetMinTabWidth;
  412. property MaxTabWidth: TCnDockTabSheet read GetMaxTabWidth;
  413. property TabLeftOffset: Integer read FTabLeftOffset write SetTabLeftOffset default 5;
  414. property TabRightOffset: Integer read FTabRightOffset write SetTabRightOffset default 5;
  415. property TabTopOffset: Integer read FTabTopOffset write SetTabTopOffset default 2;
  416. property TabBottomOffset: Integer read FTabBottomOffset write SetTabBottomOffset default 3;
  417. property TabSplitterWidth: Integer read FTabSplitterWidth write SetTabSplitterWidth default 2;
  418. property CaptionTopOffset: Integer read FCaptionTopOffset write SetCaptionTopOffset default 0;
  419. property CaptionLeftOffset: Integer read FCaptionLeftOffset write SetCaptionLeftOffset default 5;
  420. property CaptionRightOffset: Integer read FCaptionRightOffset write SetCaptionRightOffset default 5;
  421. property Sorts[Index: Integer]: TCnVIDDockTabSheet read GetSorts;
  422. property PanelHeight: Integer read GetPanelHeight write SetPanelHeight;
  423. property PanelWidth: Integer read GetPanelWidth;
  424. property TabHeight: Integer read FTabHeight write SetTabHeight;
  425. public
  426. constructor Create(AOwner: TComponent); override;
  427. destructor Destroy; override;
  428. procedure Resize; override;
  429. procedure DeleteSorts(Sheet: TCnVIDDockTabSheet);
  430. property Page: TCnVIDTabPageControl read FPage write SetPage;
  431. property SelectSheet: TCnVIDDockTabSheet read FSelectSheet write FSelectSheet;
  432. property ShowTabImages: Boolean read FShowTabImages write SetShowTabImages;
  433. end;
  434. TCnTabPanelClass = class of TCnTabPanel;
  435. TCnVIDTabPageControl = class(TCnAdvTabPageControl)
  436. private
  437. FCnTabPanelClass: TCnTabPanelClass;
  438. FPanel: TCnTabPanel;
  439. FTempSheet: TCnVIDDockTabSheet;
  440. FTabImageList: TCustomImageList;
  441. procedure SetActiveSheetColor(const Value: TColor);
  442. procedure SetInactiveSheetColor(const Value: TColor);
  443. procedure SetTabBottomOffset(const Value: Integer);
  444. procedure SetTabLeftOffset(const Value: Integer);
  445. procedure SetTabRightOffset(const Value: Integer);
  446. procedure SetTabTopOffset(const Value: Integer);
  447. procedure SetActiveFont(const Value: TFont);
  448. procedure SetInactiveFont(const Value: TFont);
  449. procedure SetHotTrackColor(const Value: TColor);
  450. function GetTabBottomOffset: Integer;
  451. function GetTabLeftOffset: Integer;
  452. function GetTabRightOffset: Integer;
  453. function GetTabTopOffset: Integer;
  454. function GetInactiveSheetColor: TColor;
  455. function GetActiveSheetColor: TColor;
  456. function GetActiveFont: TFont;
  457. function GetInactiveFont: TFont;
  458. function GetVisibleTheetCount: Integer;
  459. function GetHotTrackColor: TColor;
  460. function GetShowTabImages: Boolean;
  461. procedure SetShowTabImages(const Value: Boolean);
  462. function GetPage(Index: Integer): TCnVIDDockTabSheet;
  463. function GetActiveVIDPage: TCnVIDDockTabSheet;
  464. procedure SetActiveVIDPage(const Value: TCnVIDDockTabSheet);
  465. protected
  466. procedure AdjustClientRect(var Rect: TRect); override;
  467. procedure CreatePanel; virtual;
  468. procedure Change; override;
  469. procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer; State: TDragState;
  470. var Accept: Boolean); override;
  471. procedure CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl; var InfluenceRect: TRect;
  472. MousePos: TPoint; var CanDock: Boolean); override;
  473. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  474. procedure CustomGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign); override;
  475. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  476. procedure DrawTab(TabIndex: Integer; const Rect: TRect; Active: Boolean); override;
  477. procedure CreateParams(var Params: TCreateParams); override;
  478. function GetDockClientFromMousePos(MousePos: TPoint): TControl; override;
  479. procedure Paint; override;
  480. procedure SetActivePage(Page: TCnDockTabSheet); override;
  481. procedure SetTabHeight(Value: Smallint); override;
  482. procedure SetTabPosition(Value: TTabPosition); override;
  483. procedure CreateWnd; override;
  484. procedure Loaded; override;
  485. procedure SetHotTrack(Value: Boolean); override;
  486. procedure SetImages(Value: TCustomImageList); override;
  487. property CnTabPanelClass: TCnTabPanelClass read FCnTabPanelClass write FCnTabPanelClass;
  488. public
  489. constructor Create(AOwner: TComponent); override;
  490. procedure AfterConstruction; override;
  491. property ActiveVIDPage: TCnVIDDockTabSheet read GetActiveVIDPage write SetActiveVIDPage;
  492. destructor Destroy; override;
  493. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  494. procedure UpdateCaption(Exclude: TControl); override;
  495. procedure Resize; override;
  496. property Pages[Index: Integer]: TCnVIDDockTabSheet read GetPage;
  497. property Panel: TCnTabPanel read FPanel;
  498. property TempSheet: TCnVIDDockTabSheet read FTempSheet write FTempSheet;
  499. property VisibleTheetCount: Integer read GetVisibleTheetCount;
  500. published
  501. { 当页面获得焦点的时候的颜色 }
  502. property ActiveSheetColor: TColor read GetActiveSheetColor write SetActiveSheetColor;
  503. { 当页面失去焦点的时候的颜色 }
  504. property InactiveSheetColor: TColor read GetInactiveSheetColor write SetInactiveSheetColor;
  505. property TabLeftOffset: Integer read GetTabLeftOffset write SetTabLeftOffset default 5;
  506. property TabRightOffset: Integer read GetTabRightOffset write SetTabRightOffset default 5;
  507. property TabTopOffset: Integer read GetTabTopOffset write SetTabTopOffset default 2;
  508. property TabBottomOffset: Integer read GetTabBottomOffset write SetTabBottomOffset default 3;
  509. property ActiveFont: TFont read GetActiveFont write SetActiveFont;
  510. property InactiveFont: TFont read GetInactiveFont write SetInactiveFont;
  511. property HotTrackColor: TColor read GetHotTrackColor write SetHotTrackColor;
  512. property ShowTabImages: Boolean read GetShowTabImages write SetShowTabImages;
  513. property ActivePage;
  514. property Align;
  515. property Anchors;
  516. property BiDiMode;
  517. property Constraints;
  518. property DockSite;
  519. property DragCursor;
  520. property DragKind;
  521. property DragMode;
  522. property Enabled;
  523. property Font;
  524. property HotTrack;
  525. property Images;
  526. property MultiLine;
  527. property OwnerDraw;
  528. property ParentBiDiMode;
  529. property ParentFont;
  530. property ParentShowHint;
  531. property PopupMenu;
  532. property RaggedRight;
  533. property ScrollOpposite;
  534. property ShowHint;
  535. property Style;
  536. property TabHeight;
  537. property TabIndex;
  538. property TabOrder;
  539. property TabPosition;
  540. property TabStop;
  541. property TabWidth;
  542. property Visible;
  543. property OnChange;
  544. property OnChanging;
  545. property OnContextPopup;
  546. property OnDockDrop;
  547. property OnDockOver;
  548. property OnDragDrop;
  549. property OnDragOver;
  550. property OnDrawTab;
  551. property OnEndDock;
  552. property OnEndDrag;
  553. property OnEnter;
  554. property OnExit;
  555. property OnGetImageIndex;
  556. property OnGetSiteInfo;
  557. property OnMouseDown;
  558. property OnMouseMove;
  559. property OnMouseUp;
  560. property OnResize;
  561. property OnStartDock;
  562. property OnStartDrag;
  563. property OnUnDock;
  564. end;
  565. TCnVIDDragDockObject = class(TCnDragDockObject)
  566. private
  567. FOldDropAlign: TAlign; //前一次停靠位置
  568. FCurrState, //当前的DockOver的State;
  569. FOldState: TDragState; //前一次DockOver的State;
  570. FOldTarget: Pointer; //前一次停靠服务器
  571. FSourceDockClientList: TList;
  572. FDropTabControl: TCnVIDTabPageControl;
  573. // FOldDropTabControl: TCnVIDTabPageControl;
  574. FIsTabDockOver: Boolean;
  575. FErase: Boolean;
  576. function GetSourceDockClient(Index: Integer): TControl;
  577. function GetSourceDockClientCount: Integer;
  578. procedure SetOldState(const Value: TDragState);
  579. procedure SetCurrState(const Value: TDragState);
  580. protected
  581. procedure GetBrush_PenSize_DrawRect(
  582. var ABrush: TBrush; var PenSize: Integer; var DrawRect: TRect; Erase: Boolean); override;
  583. procedure MouseMsg(var Msg: TMessage); override;
  584. procedure DefaultDockImage(Erase: Boolean); override;
  585. function CanLeave(NewTarget: TWinControl): Boolean; override;
  586. public
  587. constructor Create(AControl: TControl); override;
  588. destructor Destroy; override;
  589. function DragFindWindow(const Pos: TPoint): HWND; override;
  590. function GetDropCtl: TControl; override;
  591. property SourceDockClients[Index: Integer]: TControl read GetSourceDockClient;
  592. property SourceDockClientCount: Integer read GetSourceDockClientCount;
  593. property CurrState: TDragState read FCurrState write SetCurrState;
  594. property OldState: TDragState read FOldState write SetOldState;
  595. end;
  596. procedure PaintGradientBackground(Canvas: TCanvas; ARect: TRect;
  597. StartColor, EndColor: TColor);
  598. { 当在TCnVIDTabPageControl上进行停靠预览的时候,这个函数用来实现这个功能 }
  599. procedure SetTabControlPreview(VIDSource: TCnVIDDragDockObject;
  600. TabControl: TCnVIDTabPageControl;
  601. State: TDragState; DropAlign: TAlign);
  602. implementation
  603. uses
  604. CnDockSupportProc, CnDockGlobal;
  605. type
  606. TCnTempWinControl = class(TWinControl);
  607. var gi_DockRect: TRect;
  608. procedure PaintGradientBackground(Canvas: TCanvas; ARect: TRect;
  609. StartColor, EndColor: TColor);
  610. {Paints the caption bar's background color(s)}
  611. const
  612. D = 256; //will divide the gradient into 256 colors
  613. var
  614. X, C1, C2, R1, G1, B1, W: Integer;
  615. DR, DG, DB, DH: Real;
  616. procedure InitRGBValues(C1, C2: Integer);
  617. {Sets the initial values for each color}
  618. begin
  619. R1:= GetRValue(C1); //store the red value of FCaptionStartColor
  620. G1:= GetGValue(C1); //store the green value of FCaptionStartColor
  621. B1:= GetBValue(C1); //store the blue value of FCaptionStartColor
  622. DR:= (GetRValue(C2) - R1 {+1}) / D; //store the red increment
  623. DG:= (GetGValue(C2) - G1 {+1}) / D; //store the green increment
  624. DB:= (GetBValue(C2) - B1 {+1}) / D; //store the blue increment
  625. end;
  626. begin
  627. With Canvas do begin
  628. Lock; //suspend painting of the canvas
  629. try
  630. Brush.Style := bsSolid; //set the brush style to paint solid strokes
  631. if StartColor <> EndColor then begin //colors differ
  632. C1 := StartColor;//ColorToRgb(FCaptionStartColor); //get RGB value of Start Color
  633. C2 := EndColor;//ColorToRgb(FCaptionEndColor); //get RGB value of End Color
  634. InitRGBValues(C1, C2); //get the initial values for the variables
  635. // If HorizontalGrabber then //caption bar is horizontal
  636. DH := (ARect.Right - ARect.Left) / D; //get width of each small rect
  637. for X := 0 to 255 do begin //paint 256 small rects
  638. Brush.Color := RGB(R1 + Round(DR*X), G1 + Round(DG*X),
  639. B1 + Round(DB*X)); //get brush color for this rect
  640. With ARect do
  641. begin
  642. // If HorizontalGrabber then begin //caption bar is horizontal
  643. //add five to the width of each to prevent rounding problems
  644. If Right <= Left + Round((X+1)*DH){ + 5} then //at the right edge
  645. W := Right //set the width to the right edge--won't over-paint
  646. else //not at the right edge
  647. W := Left + Round((X+1)*DH) {+ 5}; //set normal width
  648. FillRect(Rect(Left + Round(X*DH), Top, W, Bottom)) //paint rect
  649. end;
  650. end;
  651. end
  652. else begin //the start and end colors are identical--just paint normally
  653. Brush.Color := StartColor; //set the brush's color
  654. FillRect(ARect); //paint the rect
  655. end;
  656. finally
  657. Unlock; //resume painting of the canvas
  658. end;
  659. end;
  660. end;
  661. procedure AssignList(FromList, ToList: TList);
  662. var i: Integer;
  663. begin
  664. ToList.Clear;
  665. for i := 0 to FromList.Count - 1 do
  666. ToList.Add(FromList[i]);
  667. end;
  668. {计算停靠的区域}
  669. function ComputeVIDDockingRect(Target, Control: TControl; var DockRect: TRect; MousePos: TPoint): TAlign;
  670. var
  671. DockTopRect,
  672. DockLeftRect,
  673. DockBottomRect,
  674. DockRightRect,
  675. DockCenterRect,
  676. DockTabRect: TRect;
  677. begin
  678. Result := alNone;
  679. //划分停靠区域
  680. if Target = nil then Exit;
  681. with Target do
  682. begin
  683. DockLeftRect.TopLeft := Point(0, 0);
  684. DockLeftRect.BottomRight := Point(ClientWidth div 5, ClientHeight);
  685. DockTopRect.TopLeft := Point(ClientWidth div 5, 0);
  686. DockTopRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5);
  687. DockRightRect.TopLeft := Point(ClientWidth div 5 * 4, 0);
  688. DockRightRect.BottomRight := Point(ClientWidth, ClientHeight);
  689. if Target is TCnDockCustomTabControl then
  690. begin
  691. DockBottomRect.TopLeft := Point(ClientWidth div 5, ClientWidth div 5 * 4);
  692. DockBottomRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight -Cn_GetSysCaptionHeight);
  693. end else
  694. begin
  695. DockBottomRect.TopLeft := Point(0, ClientHeight div 5 * 4);
  696. DockBottomRect.BottomRight := Point(ClientWidth, ClientHeight);
  697. end;
  698. DockCenterRect.TopLeft := Point(0, -Cn_GetSysCaptionHeight);
  699. DockCenterRect.BottomRight := Point(ClientWidth, 0);
  700. if Target is TCnDockCustomTabControl then
  701. begin
  702. DockTabRect.TopLeft := Point(0, ClientHeight - Cn_GetSysCaptionHeight);
  703. DockTabRect.BottomRight := Point(ClientWidth, ClientHeight);
  704. end else DockTabRect := Rect(0, 0, 0, 0);
  705. //发现鼠标在哪个停靠区域
  706. if PtInRect(DockCenterRect, MousePos) or
  707. PtInRect(DockTabRect, MousePos) then
  708. begin
  709. Result := alClient;
  710. DockRect := DockCenterRect;
  711. // DockRect.TopLeft := Point(0, 0);
  712. DockRect.BottomRight := Point(ClientWidth, ClientHeight);
  713. end else
  714. if PtInRect(DockLeftRect, MousePos) then
  715. begin
  716. Result := alLeft;
  717. DockRect := DockLeftRect;
  718. DockRect.Right := Min(ClientWidth div 2, Control.ClientWidth);
  719. end else if PtInRect(DockTopRect, MousePos) then
  720. begin
  721. Result := alTop;
  722. DockRect := DockTopRect;
  723. DockRect.Left := 0;
  724. DockRect.Right := ClientWidth;
  725. DockRect.Bottom := Min(ClientHeight div 2, Control.ClientHeight);
  726. end else if PtInRect(DockRightRect, MousePos) then
  727. begin
  728. Result := alRight;
  729. DockRect := DockRightRect;
  730. DockRect.Left := Max(ClientWidth div 2, ClientWidth - Control.ClientWidth);
  731. end else if PtInRect(DockBottomRect, MousePos) then
  732. begin
  733. Result := alBottom;
  734. DockRect := DockBottomRect;
  735. DockRect.Top := Max(ClientHeight div 2, ClientHeight - Control.ClientHeight);
  736. end;
  737. if Result = alNone then Exit;
  738. //DockRect是屏幕坐标
  739. DockRect.TopLeft := ClientToScreen(DockRect.TopLeft);
  740. DockRect.BottomRight := ClientToScreen(DockRect.BottomRight);
  741. end;
  742. end;
  743. { 当在TCnVIDTabPageControl上进行停靠预览的时候,这个函数用来实现这个功能 }
  744. procedure SetTabControlPreview(VIDSource: TCnVIDDragDockObject;
  745. TabControl: TCnVIDTabPageControl;
  746. State: TDragState; DropAlign: TAlign);
  747. var i: Integer;
  748. Index: Integer;
  749. begin
  750. if TabControl <> nil then
  751. begin
  752. if (DropAlign = alClient) then
  753. begin
  754. { 如果停靠位置为alClient时,就进行预览操作 }
  755. if (TabControl.FTempSheet = nil) then
  756. begin
  757. { TabControl.FTempSheet等于nil,就说明TabControl不是处于预览状态,
  758. 就需要根据VIDSource.Control中的停靠客户来创建TabControl的TabSheet }
  759. for i := VIDSource.SourceDockClientCount - 1 downto 0 do
  760. begin
  761. { 一共创建VIDSource.SourceDockClientCount个TabSheet }
  762. TabControl.FTempSheet := TCnVIDDockTabSheet.Create(TabControl);
  763. TabControl.FTempSheet.PageControl := TabControl;
  764. { 只是创建一个空的TabSheet,里面不放任何东西,但是需要改变TabSheet的Caption属性 }
  765. TabControl.FTempSheet.Caption := TCnTempWinControl(VIDSource.SourceDockClients[i]).Caption;
  766. Index := TabControl.FTabImageList.AddIcon(TForm(VIDSource.SourceDockClients[i]).Icon);
  767. if Index <> -1 then
  768. TabControl.FTempSheet.ImageIndex := Index;
  769. { FIsSourceDockClient这个属性用来指示这个TabSheet是否是预览界面时使用的,
  770. 看下面的语句,当State = dsDragLeave的时候,就需要释放这些用来预览的TabSheet,
  771. 这时候就是通过TabSheet的FIsSourceDockClient属性来判断的。 }
  772. TabControl.FTempSheet.FIsSourceDockClient := True;
  773. end;
  774. { 设置TabControl的ActivePage和Panel的SelectSheet,
  775. SelectSheet是当鼠标按下的时候,鼠标位置所处的那个TabSheet }
  776. TabControl.ActivePage := TabControl.FTempSheet;
  777. TabControl.Panel.SelectSheet := TabControl.FTempSheet;
  778. { Panel.FTempPages是用来保存在鼠标按下之前的PageSheet,
  779. 具体的实现部分见TCnTabPanel的FindSheetWithPos函数 }
  780. {$IFDEF COMPILER6_UP}
  781. TabControl.Panel.FTempPages.Assign(TabControl.PageSheets);
  782. {$ELSE}
  783. AssignList(TabControl.PageSheets, TabControl.Panel.FTempPages);
  784. {$ENDIF}
  785. TabControl.ActivePage.Invalidate;
  786. // SendMessage(TabControl.ParentForm.Handle, WM_NCPAINT, 0, 0);
  787. end;
  788. end;
  789. // if State = dsDragLeave then
  790. // State := dsDragLeave;
  791. if ((State = dsDragLeave) or (VIDSource.DropAlign <> alClient)) and (TabControl.FTempSheet <> nil) then
  792. begin
  793. { 当State = dsDragLeave的时候,并且TabControl.FTempSheet <> nil(说明有预览操作),
  794. 就把一些用来预览的TabSheet删除掉 }
  795. for i := TabControl.PageCount - 1 downto 0 do
  796. begin
  797. if TCnVIDDockTabSheet(TabControl.Pages[i]).FIsSourceDockClient then
  798. begin
  799. { 首先找到TabControl.Pages[i]在TabControl.Panel.FTempPages中的位置 }
  800. Index := TabControl.Panel.FTempPages.IndexOf(TabControl.Pages[i]);
  801. { 然后删除掉这个指针 }
  802. if Index >= 0 then
  803. begin
  804. TabControl.Panel.FTempPages.Delete(Index);
  805. if TabControl.FTabImageList.Count > Index then
  806. TabControl.FTabImageList.Delete(Index);
  807. end;
  808. { 删除TabControl.Pages[i] }
  809. TabControl.Pages[i].Free;
  810. end;
  811. end;
  812. { TabControl.FTempSheet赋值为nil,说明已经没有预览操作 }
  813. TabControl.FTempSheet := nil;
  814. // for i := 0 to TWinControl(TabControl.ActivePage.Controls[0]).ControlCount - 1 do
  815. // TWinControl(TabControl.ActivePage.Controls[0]).Controls[i].Invalidate;
  816. end;
  817. { 可以改变TabControl.ParentForm的标题,和TabControl.ActivePage的标题一样 }
  818. TabControl.ParentForm.Caption := TabControl.ActivePage.Caption;
  819. { 需要重画这个标题 }
  820. if TabControl.ParentForm.HostDockSite is TCnCustomDockPanel then
  821. TabControl.ParentForm.HostDockSite.Invalidate;
  822. end;
  823. end;
  824. { TCnVIDDockStyle }
  825. procedure TCnVIDDockStyle.FormDockOver(DockClient: TCnDockClient; Source: TCnDragDockObject; X, Y: Integer;
  826. State: TDragState; var Accept: Boolean);
  827. var
  828. ARect: TRect;
  829. begin
  830. with DockClient do
  831. begin
  832. { 首先得到Accept的值 }
  833. Accept := EnableDock and EachOtherDock and
  834. IsDockable(ParentForm, Source.Control, Source.DropOnControl, Source.DropAlign);
  835. if State = dsDragMove then
  836. begin
  837. { 然后计算停靠位置和预览矩形的大小 }
  838. Source.DropAlign := ComputeVIDDockingRect(ParentForm, Source.Control, ARect, Point(X, Y));
  839. if Accept and (Source.DropAlign <> alNone) then
  840. begin
  841. if Source.DropAlign = alClient then
  842. { 如果Source.DropAlign = alClient,就要减去矩形的Top一个窗体高度的大小 }
  843. Inc(ARect.Top, Cn_GetSysCaptionHeightAndBorderWidth + 1);
  844. { 给Source.DockRect赋值为ARect }
  845. Source.DockRect := ARect;
  846. end;
  847. { 给gi_DockRect赋值,这个gi_DockRect有可能会在别的地方使用到 }
  848. gi_DockRect := ARect;
  849. end else if State = dsDragLeave then
  850. Source.DropAlign := alNone;
  851. if Source is TCnVIDDragDockObject then
  852. begin
  853. TCnVIDDragDockObject(Source).OldState := TCnVIDDragDockObject(Source).CurrState;
  854. TCnVIDDragDockObject(Source).CurrState := State;
  855. end;
  856. end;
  857. end;
  858. procedure TCnVIDDockStyle.FormGetSiteInfo(Source: TCnDragDockObject; DockClient: TCnDockClient;
  859. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  860. var CanDock: Boolean);
  861. const
  862. DefExpandoRect = 20;
  863. var
  864. CH_BW: Integer;
  865. ARect: TRect;
  866. begin
  867. with DockClient do
  868. begin
  869. { 获得CanDock的值 }
  870. CanDock := IsDockable(ParentForm, Client, Source.DropOnControl, Source.DropAlign);
  871. if CanDock then
  872. begin
  873. {获得停靠控件的矩形区域}
  874. GetWindowRect(ParentForm.Handle, InfluenceRect);
  875. if ParentForm.HostDockSite is TCnCustomDockPanel then
  876. { 需要减去GrabberSize(把手的高度) }
  877. Dec(InfluenceRect.Top, TCnCustomDockPanel(ParentForm.HostDockSite).CnDockManager.GrabberSize);
  878. if PtInRect(InfluenceRect, MousePos) then
  879. begin
  880. ARect := InfluenceRect;
  881. InflateRect(ARect, -DefExpandoRect, -DefExpandoRect);
  882. {获得标题栏的高度和边框的宽度}
  883. CH_BW := Cn_GetSysCaptionHeightAndBorderWidth;
  884. Inc(ARect.Top, CH_BW + 1);
  885. if PtInRect(ARect, MousePos) then
  886. begin
  887. { 如果鼠标位置在InfluenceRect中,但是不是在InfluenceRect的边缘,
  888. 就告诉系统不能停靠 }
  889. InfluenceRect := Rect(0, 0, 0, 0);
  890. CanDock := False;
  891. end;
  892. end;
  893. end;
  894. end;
  895. end;
  896. constructor TCnVIDDockStyle.Create(AOwner: TComponent);
  897. begin
  898. inherited Create(AOwner);
  899. CnDockPanelClass := TCnVIDDockPanel;
  900. CnDockSplitterClass := TCnVIDDockSplitter;
  901. CnConjoinPanelClass := TCnVIDConjoinPanel;
  902. CnTabDockClass := TCnVIDTabPageControl;
  903. CnDockPanelTreeClass := TCnVIDDockTree;
  904. CnDockPanelZoneClass := TCnVIDDockZone;
  905. CnConjoinPanelTreeClass := TCnVIDDockTree;
  906. CnConjoinPanelZoneClass := TCnVIDDockZone;
  907. CnConjoinServerOptionClass := TCnVIDConjoinServerOption;
  908. CnTabServerOptionClass := TCnVIDTabServerOption;
  909. end;
  910. procedure TCnVIDDockStyle.FormDockDrop(DockClient: TCnDockClient;
  911. Source: TCnDragDockObject; X, Y: Integer);
  912. var
  913. ARect,DRect: TRect;
  914. DockType: TAlign;
  915. Host: TCnDockableForm;
  916. APanelDock: TWinControl;
  917. VIDSource: TCnVIDDragDockObject;
  918. i: Integer;
  919. begin
  920. if Source is TCnVIDDragDockObject then
  921. begin
  922. TCnVIDDragDockObject(Source).CurrState := dsDragEnter;
  923. TCnVIDDragDockObject(Source).OldState := dsDragEnter;
  924. end;
  925. if IsDockable(DockClient.ParentForm, Source.Control, Source.DropOnControl, Source.DropAlign) then
  926. begin
  927. Host := nil;
  928. { 锁住Windows桌面 }
  929. if not IsLoading then
  930. Cn_LockWindow(nil);
  931. try
  932. with DockClient do
  933. begin
  934. // 调用ComputeVIDDockingRect函数知道停靠的类型
  935. DockType := ComputeVIDDockingRect(DockClient.ParentForm, Source.Control, ARect, Point(X, Y));
  936. if (ParentForm.HostDockSite is TCnDockPanel) then
  937. begin
  938. // 如果停靠服务器是TDockPanel,就停靠在TDockServer的DockPanel上。
  939. if DockType = alClient then
  940. begin
  941. // 如果停靠类型是alClient
  942. if Source.Control is TCnTabDockHostForm then
  943. begin
  944. // 如果停靠客户是TCnTabDockHostForm,
  945. // 就先把Parent停靠到TCnTabDockHostForm中,
  946. // 再把TCnTabDockHostForm停靠到TCnDockPanel中。
  947. APanelDock := ParentForm.HostDockSite;
  948. ARect := ParentForm.BoundsRect;
  949. ParentForm.ManualDock(TCnTabDockHostForm(Source.Control).PageControl, nil, alClient);
  950. TCnTabDockHostForm(Source.Control).PageControl.ActivePage.PageIndex := 0;
  951. Source.Control.BoundsRect := ARect;
  952. Source.Control.ManualDock(APanelDock, nil, alClient);
  953. if ParentForm.FormStyle = fsStayOnTop then
  954. TForm(Source.Control).FormStyle := fsStayOnTop;
  955. end else
  956. begin
  957. // 否则就创建TCnTabDockHostForm,
  958. // 把把Parent停靠到TCnTabDockHostForm中,
  959. // 再把TCnTabDockHostForm停靠到TCnDockPanel中。
  960. APanelDock := ParentForm.HostDockSite;
  961. DRect.TopLeft := ParentForm.HostDockSite.ClientToScreen(Point(0, 0));
  962. Host := CreateTabHostAndDockControl(ParentForm, Source.Control);
  963. SetDockSite(ParentForm, False);
  964. SetDockSite(TWinControl(Source.Control), False);
  965. Host.Top := DRect.Top;
  966. Host.Left := DRect.Left;
  967. Host.Visible := True;
  968. Host.ManualDock(APanelDock, nil, alClient);
  969. end;
  970. end
  971. else
  972. begin
  973. // 如果停靠类型不是alClient,
  974. // 就把停靠窗体停靠到TCnDockPanel.
  975. DRect := ParentForm.HostDockSite.BoundsRect;
  976. Source.Control.ManualDock(ParentForm.HostDockSite, nil, DockType);
  977. ParentForm.HostDockSite.BoundsRect := DRect;
  978. SetDockSite(TWinControl(Source.Control), False);
  979. end;
  980. Exit;
  981. end;
  982. // 创建分页的服务窗体
  983. if DockType = alClient then
  984. begin
  985. if Source.Control is TCnTabDockHostForm then
  986. begin
  987. // 如果停靠客户是TCnTabDockHostForm,
  988. // 就先把Parent停靠到TCnTabDockHostForm中,
  989. // 再把TCnTabDockHostForm停靠到TCnDockPanel中。
  990. APanelDock := ParentForm.HostDockSite;
  991. ARect := ParentForm.BoundsRect;
  992. ParentForm.ManualDock(TCnTabDockHostForm(Source.Control).PageControl, nil, alClient);
  993. TCnTabDockHostForm(Source.Control).PageControl.ActivePage.PageIndex := 0;
  994. Source.Control.BoundsRect := ARect;
  995. Source.Control.ManualDock(APanelDock, nil, alClient);
  996. if ParentForm.FormStyle = fsStayOnTop then
  997. TForm(Source.Control).FormStyle := fsStayOnTop;
  998. Exit;
  999. end else
  1000. begin
  1001. if Source is TCnVIDDragDockObject then
  1002. begin
  1003. VIDSource := TCnVIDDragDockObject(Source);
  1004. DoFloatForm(Source.Control);
  1005. FreeAllDockableForm;
  1006. for i := 0 to VIDSource.SourceDockClientCount - 1 do
  1007. begin
  1008. VIDSource.Control := VIDSource.SourceDockClients[i];
  1009. if Host = nil then
  1010. Host := DockClient.CreateTabHostAndDockControl(DockClient.ParentForm, Source.Control)
  1011. else Source.Control.ManualDock(TCnTabDockHostForm(Host).PageControl, nil, alClient);
  1012. end;
  1013. Host.Visible := True;
  1014. // CnGlobalDockPresident.DragObject.Control := nil;
  1015. end;
  1016. end;
  1017. end
  1018. else if DockType <> alNone then
  1019. begin
  1020. // 创建平铺的服务窗体
  1021. Host := CreateConjoinHostAndDockControl(ParentForm, Source.Control, DockType);
  1022. SetDockSite(ParentForm, False);
  1023. SetDockSite(TWinControl(Source.Control), False);
  1024. Host.Visible := True;
  1025. end;
  1026. if Host <> nil then
  1027. begin
  1028. Host.LRDockWidth := Source.Control.LRDockWidth;
  1029. Host.TBDockHeight := Source.Control.TBDockHeight;
  1030. end;
  1031. end;
  1032. finally
  1033. { 解锁Windows桌面 }
  1034. if not IsLoading then
  1035. Cn_UnLockWindow;
  1036. end;
  1037. end;
  1038. end;
  1039. procedure TCnVIDDockStyle.SetDockBaseControl(IsCreate: Boolean;
  1040. DockBaseControl: TCnDockBaseControl);
  1041. var ADockClient: TCnDockClient;
  1042. begin
  1043. if DockBaseControl is TCnDockClient then
  1044. begin
  1045. ADockClient := TCnDockClient(DockBaseControl);
  1046. if IsCreate then
  1047. ADockClient.DirectDrag := False;
  1048. end;
  1049. end;
  1050. procedure TCnVIDDockStyle.FormStartDock(DockClient: TCnDockClient;
  1051. var Source: TCnDragDockObject);
  1052. begin
  1053. inherited FormStartDock(DockClient, Source);
  1054. { 创建一个TCnVIDDragDockObject返回给系统 }
  1055. Source := TCnVIDDragDockObject.Create(DockClient.ParentForm);
  1056. end;
  1057. procedure TCnVIDDockStyle.FormGetDockEdge(DockClient: TCnDockClient;
  1058. Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign);
  1059. var ARect: TRect;
  1060. begin
  1061. { 获得停靠的位置 }
  1062. DropAlign := ComputeVIDDockingRect(DockClient.ParentForm, Source.Control, ARect, MousePos);
  1063. end;
  1064. function TCnVIDDockStyle.DockClientWindowProc(DockClient: TCnDockClient;
  1065. var Message: TMessage): Boolean;
  1066. begin
  1067. Result := inherited DockClientWindowProc(DockClient, Message);
  1068. end;
  1069. procedure TCnVIDDockStyle.CreateConjoinServerOption(
  1070. var Option: TCnBasicConjoinServerOption);
  1071. begin
  1072. Option := TCnVIDConjoinServerOption.Create(Self);
  1073. end;
  1074. procedure TCnVIDDockStyle.CreateTabServerOption(
  1075. var Option: TCnBasicTabServerOption);
  1076. begin
  1077. Option := TCnVIDTabServerOption.Create(Self);
  1078. end;
  1079. procedure TCnVIDDockStyle.AssignConjoinServerOption(
  1080. APanel: TCnCustomDockPanel);
  1081. begin
  1082. inherited AssignConjoinServerOption(APanel);
  1083. end;
  1084. procedure TCnVIDDockStyle.AssignTabServerOption(APage: TCnTabPageControl);
  1085. var TmpPage: TCnVIDTabPageControl;
  1086. TmpOption: TCnVIDTabServerOption;
  1087. begin
  1088. inherited AssignTabServerOption(APage);
  1089. if (APage is TCnVIDTabPageControl) and (TabServerOption is TCnVIDTabServerOption) then
  1090. begin
  1091. TmpPage := APage as TCnVIDTabPageControl;
  1092. TmpOption := TabServerOption as TCnVIDTabServerOption;
  1093. TmpPage.ActiveFont.Assign(TmpOption.ActiveFont);
  1094. TmpPage.ActiveSheetColor := TmpOption.ActiveSheetColor;
  1095. TmpPage.InactiveFont.Assign(TmpOption.InactiveFont);
  1096. TmpPage.InactiveSheetColor := TmpOption.InactiveSheetColor;
  1097. TmpPage.HotTrackColor := TmpOption.HotTrackColor;
  1098. TmpPage.ShowTabImages := TmpOption.ShowTabImages;
  1099. end;
  1100. end;
  1101. procedure TCnVIDDockStyle.ParentFormWindowProc(var Message: TMessage);
  1102. begin
  1103. inherited ParentFormWindowProc(Message);
  1104. if (Message.Msg = WM_SETTINGCHANGE) or (Message.Msg = WM_SYSCOLORCHANGE) then
  1105. begin
  1106. ParentForm.Caption := '';
  1107. { 如果是WM_SETTINGCHANGE或者WM_SYSCOLORCHANGE消息,也就是当设置桌面属性的外观后。
  1108. 就重新设置ConjoinServerOption的属性 }
  1109. if (ConjoinServerOption is TCnVIDConjoinServerOption) then
  1110. begin
  1111. if TCnVIDConjoinServerOption(ConjoinServerOption).SystemInfo then
  1112. TCnVIDConjoinServerOption(ConjoinServerOption).SetDefaultSystemCaptionInfo;
  1113. end;
  1114. end;
  1115. end;
  1116. destructor TCnVIDDockStyle.Destroy;
  1117. begin
  1118. inherited;
  1119. end;
  1120. procedure TCnVIDDockStyle.DoSystemInfoChange(Value: Boolean);
  1121. begin
  1122. if Assigned(FSystemInfoChange) then
  1123. FSystemInfoChange(Value);
  1124. end;
  1125. procedure TCnVIDDockStyle.GetComponentInfo(var AName, Author, Email,
  1126. Comment: string);
  1127. begin
  1128. AName := SCnVIDDockStyleName;
  1129. Author := SCnPack_LuXiaoban;
  1130. Email := SCnPack_LuXiaobanEmail;
  1131. Comment := SCnVIDDockStyleComment;
  1132. end;
  1133. { TCnVIDDockPanel }
  1134. constructor TCnVIDDockPanel.Create(AOwner: TComponent);
  1135. begin
  1136. inherited Create(AOwner);
  1137. end;
  1138. function TCnVIDDockPanel.CreateDockManager: IDockManager;
  1139. var Option: TCnVIDConjoinServerOption;
  1140. begin
  1141. Result := inherited CreateDockManager;
  1142. if (DockServer <> nil) and (Result <> nil) then
  1143. begin
  1144. Option := TCnVIDConjoinServerOption(DockServer.DockStyle.ConjoinServerOption);
  1145. (Result as ICnDockManager).GrabberSize := Option.GrabbersSize;
  1146. end;
  1147. end;
  1148. procedure TCnVIDDockPanel.CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer);
  1149. //var
  1150. // VIDSource: TCnVIDDragDockObject;
  1151. begin
  1152. { if Source is TCnVIDDragDockObject then
  1153. begin
  1154. VIDSource := TCnVIDDragDockObject(Source);
  1155. SetTabControlPreview(VIDSource, VIDSource.FDropTabControl, dsDragLeave, VIDSource.DropAlign);
  1156. end;}
  1157. if Source.Control is TCnDockableForm then
  1158. { 显示DockPanel }
  1159. ShowDockPanel(True, Source.Control);
  1160. if not ((Source.Control.HostDockSite <> nil) and
  1161. (Source.DropOnControl = Source.Control.HostDockSite.Parent) and
  1162. (Source.DropAlign = alClient)) then
  1163. begin
  1164. inherited CustomDockDrop(Source, X, Y);
  1165. { 因为是平铺风格,所以要设置ActiveControl为当前Source的Control }
  1166. CnDockManager.ActiveControl := Source.Control;
  1167. { 设置Source.Control为获得焦点,这一步一定需要设置,
  1168. 不然程序可能会把Source.Control中的控件的内容清空 }
  1169. if (Source.Control is TWinControl) and TWinControl(Source.Control).CanFocus then
  1170. TWinControl(Source.Control).SetFocus;
  1171. end;
  1172. end;
  1173. procedure TCnVIDDockPanel.CustomDockOver(Source: TCnDragDockObject; X,
  1174. Y: Integer; State: TDragState; var Accept: Boolean);
  1175. var DropAlign: TAlign;
  1176. // VIDSource: TCnVIDDragDockObject;
  1177. // DropCtl: TControl;
  1178. begin
  1179. { 首先调用父类的CustomDockOver }
  1180. inherited CustomDockOver(Source, X, Y, State, Accept);
  1181. if Accept and (Source is TCnVIDDragDockObject) then
  1182. begin
  1183. (* VIDSource := TCnVIDDragDockObject(Source);
  1184. DropCtl := VIDSource.GetDropCtl;
  1185. if (DropCtl <> VIDSource.DropOnControl) or
  1186. (VIDSource.FOldDropTabControl <> VIDSource.FDropTabControl) then
  1187. SetTabControlPreview(VIDSource, VIDSource.FOldDropTabControl, dsDragLeave, VIDSource.DropAlign);
  1188. { 调用SetTabControlPreview函数用来显示预览界面 }
  1189. SetTabControlPreview(VIDSource, VIDSource.FDropTabControl, State, VIDSource.DropAlign);
  1190. if State = dsDragLeave then
  1191. { 离开的时候要设置FDropTabControl为空 }
  1192. VIDSource.FDropTabControl := nil;
  1193. VIDSource.FOldDropTabControl := VIDSource.FDropTabControl;*)
  1194. if State = dsDragMove then
  1195. begin
  1196. DropAlign := Source.DropAlign;
  1197. { 调用CnDockManager的GetDockEdge来得到停靠的位置 }
  1198. CnDockManager.GetDockEdge(Source.DockRect, Source.DragPos, DropAlign, Source.Control);
  1199. end;// else if (State = dsDragLeave) then
  1200. // if (Source.DropAlign = alClient) and (Source.DropOnControl = nil) then
  1201. // Source.DropAlign := alNone;
  1202. end;
  1203. end;
  1204. procedure TCnVIDDockPanel.CustomGetDockEdge(Source: TCnDragDockObject;
  1205. MousePos: TPoint; var DropAlign: TAlign);
  1206. begin
  1207. // inherited CustomGetDockEdge(Source, MousePos, DropAlign);
  1208. end;
  1209. procedure TCnVIDDockPanel.CustomGetSiteInfo(Source: TCnDragDockObject;
  1210. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  1211. var CanDock: Boolean);
  1212. begin
  1213. { 如果VisibleDockClientCount = 0,也就是说停靠服务器中的TCnVIDDockPanel还没有显示出来,
  1214. 就调用默认的CustomGetSiteInfo,否者就要调用CnDockManager.GetSiteInfo来获得InfluenceRect }
  1215. if VisibleDockClientCount = 0 then
  1216. inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock)
  1217. else
  1218. begin
  1219. CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
  1220. if CanDock then
  1221. CnDockManager.GetSiteInfo(Client, InfluenceRect, MousePos, CanDock);
  1222. end;
  1223. end;
  1224. procedure TCnVIDDockPanel.CustomStartDock(var Source: TCnDragDockObject);
  1225. begin
  1226. Source := TCnVIDDragDockObject.Create(Self);
  1227. end;
  1228. procedure TCnVIDDockPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
  1229. begin
  1230. inherited;
  1231. end;
  1232. { TCnVIDDockTree }
  1233. constructor TCnVIDDockTree.Create(DockSite: TWinControl;
  1234. CnDockZoneClass: TCnDockZoneClass);
  1235. begin
  1236. inherited Create(DockSite, CnDockZoneClass);
  1237. FDropOnZone := nil;
  1238. GrabberSize := 18;
  1239. ButtonHeight := 11;
  1240. ButtonWidth := 13;
  1241. LeftOffset := 2;
  1242. RightOffset := 2;
  1243. TopOffset := 4;
  1244. BottomOffset := 3;
  1245. ButtonSplitter := 2;
  1246. BorderWidth := 0;
  1247. MinSize := 20; //节点的最小值为20
  1248. CaptionLeftOffset := 0;
  1249. CaptionRightOffset := 0;
  1250. end;
  1251. destructor TCnVIDDockTree.Destroy;
  1252. begin
  1253. inherited Destroy;
  1254. end;
  1255. function TCnVIDDockTree.GetGrabbersPosition: TGrabbersPosition;
  1256. begin
  1257. { 在这里默认的把手位置都是gpTop }
  1258. Result := gpTop;
  1259. end;
  1260. function TCnVIDDockTree.GetTopGrabbersHTFlag(const MousePos: TPoint;
  1261. out HTFlag: Integer; Zone: TCnDockZone): TCnDockZone;
  1262. begin
  1263. if (MousePos.Y >= Zone.Top) and (MousePos.Y <= Zone.Top + GrabberSize) and
  1264. (MousePos.X >= Zone.Left) and (MousePos.X <= Zone.Left + Zone.Width) then
  1265. begin
  1266. Result := Zone;
  1267. with Zone.ChildControl do
  1268. begin
  1269. if PtInRect(Rect(
  1270. Left + Width - ButtonWidth - RightOffset,
  1271. Top - GrabberSize + TopOffset,
  1272. Left + Width - RightOffset,
  1273. Top - GrabberSize + TopOffset + ButtonHeight), MousePos) then
  1274. HTFlag := HTCLOSE
  1275. else HTFlag := HTCAPTION;
  1276. end;
  1277. end else Result := nil;
  1278. end;
  1279. procedure TCnVIDDockTree.InsertControl(Control: TControl; InsertAt: TAlign;
  1280. DropCtl: TControl);
  1281. { 根据Client,DropCtl和InsertAt来创建一个TCnTabDockHostForm窗体,
  1282. 并且把Client和DropCtl停靠到它的PageControl中 }
  1283. function CreateDockPageControl(Client: TControl): TCnTabDockHostForm;
  1284. var
  1285. Zone: TCnDockZone; //根据DropCtl查找到的节点
  1286. TempCtl: TControl; //用来存储原来的DropCtl,因为DropCtl有可能会被改变
  1287. TempPanel: TCnConjoinPanel; //存储TempCtl的HostDockSite
  1288. DockClient: TCnDockClient; //在DropCtl中的DockClient
  1289. APoint: TPoint;
  1290. begin
  1291. Result := nil;
  1292. Zone := FindControlZone(DropCtl);
  1293. DockClient := FindDockClient(DropCtl);
  1294. if (DockClient <> nil) and (Zone <> nil) then
  1295. begin
  1296. TempCtl := DropCtl;
  1297. { 下面的语句用来给DropCtl和InsertAt赋值 }
  1298. if Zone.ParentZone.Orientation = doHorizontal then
  1299. begin
  1300. if (Zone.PrevSibling = nil) then
  1301. begin
  1302. if Zone.NextSibling <> nil then
  1303. DropCtl := Zone.NextSibling.ChildControl;
  1304. InsertAt := alTop;
  1305. end else
  1306. begin
  1307. DropCtl := Zone.PrevSibling.ChildControl;
  1308. InsertAt := alBottom;
  1309. end;
  1310. end else if Zone.ParentZone.Orientation = doVertical then
  1311. begin
  1312. if (Zone.PrevSibling = nil) then
  1313. begin
  1314. if Zone.NextSibling <> nil then
  1315. DropCtl := Zone.NextSibling.ChildControl;
  1316. InsertAt := alLeft;
  1317. end else //if Zone.NextSibling = nil then
  1318. begin
  1319. DropCtl := Zone.PrevSibling.ChildControl;
  1320. InsertAt := alRight;
  1321. end;
  1322. end;
  1323. { 考虑到在调用完DockClient的CreateTabHostAndDockControl函数后TempCtl.HostDockSite可能会改变
  1324. 所以先把它保存下来,供以后使用 }
  1325. if TempCtl.HostDockSite is TCnConjoinPanel then
  1326. TempPanel := TCnConjoinPanel(TempCtl.HostDockSite)
  1327. else TempPanel := nil;
  1328. { 调用DockClient的CreateTabHostAndDockControl函数,根据TempCtl和Client创建TCnTabDockHostForm }
  1329. Result := DockClient.CreateTabHostAndDockControl(TempCtl, Client);
  1330. if TempPanel <> nil then
  1331. { 这条语句是用在TCnDockableForm的DoClose中的,用来判断UnDockControl是否是将要又被停靠进TempPanel,
  1332. 如果是的话,就不把TempPanel.ParentForm释放掉,否者就有可能被释放掉,具体代码请参看TCnDockableForm的DoClose函数 }
  1333. TempPanel.ParentForm.UnDockControl := Result;
  1334. { 设置TempCtl和Control的DockSite属性为False }
  1335. SetDockSite(TWinControl(TempCtl), False);
  1336. SetDockSite(TWinControl(Client), False);
  1337. { 重新设置Result的位置 }
  1338. if DockSite.Align = alBottom then
  1339. APoint := Point(0, -TempCtl.TBDockHeight)
  1340. else if DockSite.Align = alRight then
  1341. APoint := Point(-TempCtl.LRDockWidth, 0)
  1342. else APoint := Point(0, 0);
  1343. APoint := DockSite.ClientToScreen(APoint);
  1344. Result.Left := APoint.x;
  1345. Result.Top := APoint.y;
  1346. Result.UndockWidth := TempCtl.UndockWidth;
  1347. Result.UndockHeight := TempCtl.UndockHeight;
  1348. Result.LRDockWidth := TempCtl.LRDockWidth;
  1349. Result.TBDockHeight := TempCtl.TBDockHeight + GrabberSize;
  1350. { 显示TCnTabDockHostForm }
  1351. Result.Visible := True;
  1352. end;
  1353. end;
  1354. var i: Integer;
  1355. Host: TCnTabDockHostForm;
  1356. ChildCount: Integer;
  1357. VIDSource: TCnVIDDragDockObject;
  1358. TempControl: TControl;
  1359. ARect: TRect;
  1360. AZone: TCnDockZone;
  1361. begin
  1362. { 锁住Windows桌面 }
  1363. if not IsLoading then
  1364. Cn_LockWindow(nil);
  1365. try
  1366. VIDSource := nil;
  1367. if (Control is TCnDockableForm){ and (DockSite is TCnConjoinPanel) }then
  1368. begin
  1369. { 如果将要停靠进来的Control是TCnDockableForm,也就是说Control是一个停靠服务器 }
  1370. if InsertAt in [alClient] then
  1371. begin
  1372. { 如果停靠类型是alClient,就说明要把Control和DropCtl停靠到一个TCnVIDTabPageControl中去,
  1373. 然后把TCnVIDTabPageControl的ParentForm--也就是TCnTabDockHostForm停靠到DockSite中 }
  1374. if DropCtl is TCnTabDockHostForm then
  1375. begin
  1376. // IsLoading := True;
  1377. { 如果DropCtl本身就是一个TCnTabDockHostForm,那只要把Control中的所有停靠客户依次停靠到DropCtl的PageControl中去 }
  1378. try
  1379. VIDSource := TCnVIDDragDockObject.Create(Control);
  1380. DoFloatForm(Control);
  1381. FreeAllDockableForm;
  1382. for i := VIDSource.SourceDockClientCount - 1 downto 0 do
  1383. begin
  1384. TempControl := VIDSource.SourceDockClients[i];
  1385. TempControl.ManualDock(TCnTabDockHostForm(DropCtl).PageControl);
  1386. if TempControl is TForm then
  1387. begin
  1388. TForm(TempControl).ActiveControl := nil;
  1389. SetDockSite(TForm(TempControl), False);
  1390. end;
  1391. end;
  1392. finally
  1393. // IsLoading := False;
  1394. // ReshowAllVisibleWindow;
  1395. VIDSource.Free;
  1396. CnGlobalDockPresident.DragObject.Control := nil;
  1397. end;
  1398. end else
  1399. begin
  1400. if (DockSite is TCnCustomDockPanel) and (DockSite.VisibleDockClientCount > 1) and (DropCtl <> nil) then
  1401. begin
  1402. // IsLoading := True;
  1403. try
  1404. VIDSource := TCnVIDDragDockObject.Create(Control);
  1405. DoFloatForm(Control);
  1406. FreeAllDockableForm;
  1407. { 否者,就首先创建一个TCnDockableForm用来作为Control的DockClients[0]和DropCtl的服务器Host }
  1408. Host := CreateDockPageControl(VIDSource.SourceDockClients[0]);//TCnDockableForm(Control).DockableControl.DockClients[0]);
  1409. if Host <> nil then
  1410. begin
  1411. { 然后再把Control中的所有停靠客户依次停靠到DropCtl的PageControl中去 }
  1412. for i := VIDSource.SourceDockClientCount - 1 downto 1 do
  1413. begin
  1414. TempControl := VIDSource.SourceDockClients[i];
  1415. TempControl.ManualDock(Host.PageControl);
  1416. if TempControl is TForm then
  1417. begin
  1418. TForm(TempControl).ActiveControl := nil;
  1419. SetDockSite(TForm(TempControl), False);
  1420. end;
  1421. end;
  1422. { 最后把Host停靠到DockSite中,注意:这时候DropCtl和InsertAt已经改变了 }
  1423. Host.ManualDock(DockSite, nil, InsertAt);
  1424. end;
  1425. finally
  1426. // IsLoading := False;
  1427. // ReshowAllVisibleWindow;
  1428. VIDSource.Free;
  1429. CnGlobalDockPresident.DragObject.Control := nil;
  1430. end;
  1431. end else
  1432. { 否者调用原来的虚拟函数 }
  1433. inherited InsertControl(Control, InsertAt, DropCtl);
  1434. end;
  1435. end else if Control is TCnConjoinDockHostForm then
  1436. begin
  1437. { 否则如果Control是一个平铺服务器,就要进行特殊的处理,
  1438. 调用InsertControlFromConjoinHost函数,把Control中的停靠信息还原到DockSite中 }
  1439. TCnTempWinControl(TCnDockableForm(Control).DockableControl).DockManager.ResetBounds(True);
  1440. InsertControlFromConjoinHost(Control, InsertAt, DropCtl);
  1441. end else
  1442. { 否者调用原来的虚拟函数 }
  1443. inherited InsertControl(Control, InsertAt, DropCtl);
  1444. end else
  1445. begin
  1446. { 否者,也就是说Control是一个普通的窗体 }
  1447. if InsertAt in [alLeft, alTop] then
  1448. { 对DockSize进行必要的调整 }
  1449. DropDockSize := DropDockSize + SplitterWidth div 2;
  1450. if InsertAt in [alClient] then
  1451. begin
  1452. { 如果停靠类型是alClient,就说明要把Control和DropCtl停靠到一个TCnVIDTabPageControl中去,
  1453. 然后把TCnVIDTabPageControl的ParentForm--也就是TCnTabDockHostForm停靠到DockSite中 }
  1454. if DropCtl is TCnTabDockHostForm then
  1455. begin
  1456. { 如果DropCtl本身就是一个TCnTabDockHostForm,那只要简单的把Control停靠到DropCtl的PageControl中去 }
  1457. Control.ManualDock(TCnTabDockHostForm(DropCtl).PageControl, nil, alClient);
  1458. end
  1459. else if TopZone.ChildZones <> nil then
  1460. begin
  1461. { 否者如果DockSite本身有停靠客户 }
  1462. ChildCount := TopZone.ChildCount;
  1463. if DropCtl <> nil then
  1464. begin
  1465. ARect := DropCtl.BoundsRect;
  1466. AZone := FindControlZone(DropCtl);
  1467. // 当这个节点紧靠DockSite的右边或者下边的时候,不用给它加偏移量SplitterWidth
  1468. if DropCtl.DockOrientation = doHorizontal then
  1469. begin
  1470. if ((AZone <> nil) and (AZone.ZoneLimit <> DockSite.Height)) then
  1471. ARect.Bottom := ARect.Bottom + SplitterWidth;
  1472. end else
  1473. begin
  1474. if ((AZone <> nil) and (AZone.ZoneLimit <> DockSite.Width)) then
  1475. ARect.Right := ARect.Right + SplitterWidth;
  1476. end;
  1477. DockRect := ARect;
  1478. end
  1479. else DockRect := Rect(0, 0, TopZone.Width, TopZone.Height);
  1480. { 创建一个叫做Host的窗体作为Control和DropCtl的服务器 }
  1481. Host := CreateDockPageControl(Control);
  1482. if Host <> nil then
  1483. begin
  1484. if (ChildCount >= 2) or (DockSite is TCnDockPanel) then
  1485. begin
  1486. { 如果DockSite的客户大于一个,就把Host停靠到DockSite中 }
  1487. if InsertAt in [alLeft, alRight] then
  1488. DropDockSize := DockRect.Right - DockRect.Left
  1489. else DropDockSize := DockRect.Bottom - DockRect.Top + GrabberSize;
  1490. // 锁住DropDockSize
  1491. LockDropDockSize;
  1492. Host.ManualDock(DockSite, DropCtl, InsertAt);
  1493. // 解锁DropDockSize
  1494. UnlockDropDockSize;
  1495. end else
  1496. begin
  1497. { 否者只是简单的设置Host的位置大小 }
  1498. Host.BoundsRect := DockSite.Parent.BoundsRect;
  1499. end;
  1500. end;
  1501. end
  1502. else inherited InsertControl(Control, InsertAt, DropCtl);
  1503. end else
  1504. { 否者调用原来的虚拟函数 }
  1505. inherited InsertControl(Control, InsertAt, DropCtl);
  1506. { 这条语句是用来给DockRect赋值,这是因为有可能InsertControl会调用好几次,
  1507. 下次调用InsertControl的时候可能会使用到DockRect }
  1508. DockRect := gi_DockRect;
  1509. end;
  1510. ForEachAt(nil, UpdateZone);
  1511. finally
  1512. { 解锁Windows桌面 }
  1513. if not IsLoading then
  1514. Cn_UnLockWindow;
  1515. end;
  1516. end;
  1517. procedure TCnVIDDockTree.InsertControlFromConjoinHost(Control: TControl;
  1518. InsertAt: TAlign; DropCtl: TControl);
  1519. const
  1520. { Delphi6.0 }
  1521. {$IFDEF COMPILER6_UP}
  1522. OrientArray: array[TAlign] of TDockOrientation = (doNoOrient, doHorizontal,
  1523. doHorizontal, doVertical, doVertical, doNoOrient, doNoOrient); { alCustom }
  1524. MakeLast: array[TAlign] of Boolean = (False, False, True, False, True, False, False); { alCustom }
  1525. ReverseAt: array[TAlign] of TAlign = (alClient, alBottom, alTop, alRight, alLeft, alNone, alCustom); { alCustom }
  1526. {$ELSE}
  1527. { Delphi5.0 OR LAST}
  1528. OrientArray: array[TAlign] of TDockOrientation = (doNoOrient, doHorizontal,
  1529. doHorizontal, doVertical, doVertical, doNoOrient);
  1530. MakeLast: array[TAlign] of Boolean = (False, False, True, False, True, False);
  1531. ReverseAt: array[TAlign] of TAlign = (alClient, alBottom, alTop, alRight, alLeft, alNone);
  1532. {$ENDIF}
  1533. var
  1534. Stream: TMemoryStream;
  1535. TopOrientation, //Control中的TopZone的Orientation属性
  1536. InsertOrientation, //要插入的方向
  1537. CurrentOrientation: TDockOrientation; //当前的方向
  1538. ZoneLimit: Integer;
  1539. Level, LastLevel, I: Integer;
  1540. Zone, NextZone: TCnDockZone;
  1541. DropCtlZone, LastZone: TCnDockZone;
  1542. OffsetXYLimitArr: array[TDockOrientation] of Integer; //偏移量
  1543. ControlXYLimitArr: array[TDockOrientation] of Integer; //控件的宽度和高度
  1544. { 读出控件的名称 }
  1545. { procedure ReadControlName(var ControlName: string);
  1546. var
  1547. Size: Integer;
  1548. begin
  1549. ControlName := '';
  1550. Stream.Read(Size, SizeOf(Size));
  1551. if Size > 0 then
  1552. begin
  1553. SetLength(ControlName, Size);
  1554. Stream.Read(Pointer(ControlName)^, Size);
  1555. end;
  1556. end;}
  1557. { 读出Zone并且按要求设置它在DockTree中的位置 }
  1558. procedure ReadZone(SetZone: Boolean);
  1559. var I: Integer;
  1560. begin
  1561. { 读Control中DockTree的Zone }
  1562. with Stream do
  1563. begin
  1564. { 读出Level值,这个值代表了Zone的层次,如果是0就是TopZone,
  1565. 如果是1就是TopZone的子女,依次类推 }
  1566. Read(Level, SizeOf(Level));
  1567. if Level = TreeStreamEndFlag then Exit;
  1568. { 创建Zone }
  1569. Zone := CnDockZoneClass.Create(Self);
  1570. { 读出Zone的Orientation属性 }
  1571. CustomLoadZone(Stream, Zone);
  1572. { 读出Zone的ZoneLimit属性,这个值不能直接赋值给Zone,还需要加上偏移量 }
  1573. ZoneLimit := Zone.ZoneLimit;
  1574. end;
  1575. if SetZone then
  1576. begin
  1577. { 如果SetZone等于True,也就是说要设置Zone在DockTree中的关系 }
  1578. if Level = LastLevel then
  1579. begin
  1580. { 如果Level和LastLevel相等,也就是说Zone和LastZone是兄弟关系,就把Zone
  1581. 加为LastZone的兄弟。}
  1582. Zone.NextSibling := LastZone.NextSibling;
  1583. if LastZone.NextSibling <> nil then
  1584. LastZone.NextSibling.PrevSibling := Zone;
  1585. LastZone.NextSibling := Zone;
  1586. Zone.PrevSibling := LastZone;
  1587. Zone.ParentZone := LastZone.ParentZone;
  1588. end
  1589. else if Level > LastLevel then
  1590. begin
  1591. { 如果Level大于LastLevel,也就是说Zone是LastZone的子女,就把Zone
  1592. 加为LastZone的子女。}
  1593. LastZone.ChildZones := Zone;
  1594. Zone.ParentZone := LastZone;
  1595. InsertOrientation := LastZone.Orientation;
  1596. end
  1597. else if Level < LastLevel then
  1598. begin
  1599. { 如果Level小于LastLevel,就找到和Zone等级相等的NextZone,并且把Zone
  1600. 加为NextZone的兄弟。}
  1601. NextZone := LastZone;
  1602. for I := 1 to LastLevel - Level do
  1603. NextZone := NextZone.ParentZone;
  1604. Zone.NextSibling := NextZone.NextSibling;
  1605. if NextZone.NextSibling <> nil then
  1606. NextZone.NextSibling.PrevSibling := Zone;
  1607. NextZone.NextSibling := Zone;
  1608. Zone.PrevSibling := NextZone;
  1609. Zone.ParentZone := NextZone.ParentZone;
  1610. InsertOrientation := Zone.ParentZone.Orientation;
  1611. end;
  1612. { Zone的ZoneLimit要加上偏移量 }
  1613. Zone.ZoneLimit := OffsetXYLimitArr[InsertOrientation] + ZoneLimit;
  1614. end;
  1615. { 把当前的值赋值给Last,进行下一次循环 }
  1616. LastLevel := Level;
  1617. LastZone := Zone;
  1618. end;
  1619. begin
  1620. { 控件的长宽 }
  1621. ControlXYLimitArr[doNoOrient] := 0;
  1622. ControlXYLimitArr[doHorizontal] := DockRect.Bottom - DockRect.Top ;//}Control.Height;// - GrabberSize;
  1623. ControlXYLimitArr[doVertical] := DockRect.Right - DockRect.Left;//}Control.Width;// - BorderWidth;
  1624. { 创建并且存储停靠信息到流中 }
  1625. Stream := TMemoryStream.Create;
  1626. if Control is TCnConjoinDockHostForm then
  1627. TCnConjoinDockHostForm(Control).Panel.CnDockManager.SaveToStream(Stream);
  1628. Stream.Position := 0;
  1629. { 开始更新 }
  1630. BeginUpdate;
  1631. try
  1632. { 读版本 }
  1633. Stream.Read(I, SizeOf(I));
  1634. { TopZone中的TopXYLimit(四字节)和Level(四字节)没有用处,被忽略掉 }
  1635. Stream.Position := Stream.Position + 8;
  1636. { 读出停靠窗体的停靠方向 }
  1637. Stream.Read(TopOrientation, SizeOf(TopOrientation));
  1638. { 读出停靠窗体的Limit }
  1639. Stream.Read(ZoneLimit, SizeOf(ZoneLimit));
  1640. IgnoreZoneInfor(Stream);
  1641. if (DropCtl = nil) and (TopZone.ChildCount = 1) then
  1642. { 如果TopZone只有一个子女,就把这个子女赋值给DropCtl }
  1643. DropCtl := TopZone.ChildZones.ChildControl;
  1644. { 查找到DropCtl属于哪一个Zone }
  1645. DropCtlZone := FindControlZone(DropCtl);
  1646. { 默认的插入方向是右边 }
  1647. if InsertAt in [alClient, alNone] then InsertAt := alRight;
  1648. InsertOrientation := OrientArray[InsertAt];
  1649. if TopZone.ChildCount = 0 then
  1650. begin
  1651. { DockSite中还没有控件(可视的),插入方向和Top的方向就设置成和Control中的TopZone一样 }
  1652. TopZone.Orientation := TopOrientation;
  1653. InsertOrientation := TopOrientation;
  1654. end
  1655. else if TopZone.ChildCount = 1 then
  1656. begin
  1657. // 如果树只有一个子女,并且第二个正在被添加进去,
  1658. // 所以方向和位置必须被设置
  1659. TopZone.Orientation := InsertOrientation;
  1660. case InsertOrientation of
  1661. doHorizontal:
  1662. begin
  1663. TopZone.ZoneLimit := TopZone.ChildZones.Width;
  1664. TopXYLimit := TopZone.ChildZones.Height;
  1665. end;
  1666. doVertical:
  1667. begin
  1668. TopZone.ZoneLimit := TopZone.ChildZones.Height;
  1669. TopXYLimit := TopZone.ChildZones.Width;
  1670. end;
  1671. end;
  1672. end;
  1673. { 设置当前的DropCtlZone的方向 }
  1674. if DropCtlZone <> nil then
  1675. CurrentOrientation := DropCtlZone.ParentZone.Orientation
  1676. else
  1677. CurrentOrientation := TopZone.Orientation;
  1678. { 设置DockSize的大小 }
  1679. if InsertOrientation = doHorizontal then
  1680. DropDockSize := DockRect.Bottom - DockRect.Top
  1681. else if InsertOrientation = doVertical then
  1682. DropDockSize := DockRect.Right - DockRect.Left
  1683. else DropDockSize := 0;
  1684. { 设置偏移量 }
  1685. OffsetXYLimitArr[doNoOrient] := 0;
  1686. if DropCtlZone <> nil then
  1687. begin
  1688. { 首先计算水平偏移量 }
  1689. OffsetXYLimitArr[doHorizontal] := DropCtlZone.TopLeft[doHorizontal] +
  1690. Integer(MakeLast[InsertAt]) * (DropCtlZone.HeightWidth[doHorizontal] - ControlXYLimitArr[doHorizontal]);
  1691. { 如果停靠操作是在水平分割条附近,就重新计算水平偏移量 }
  1692. if (FDropOnZone <> nil) and (InsertOrientation = doHorizontal) then
  1693. OffsetXYLimitArr[doHorizontal] := FDropOnZone.ZoneLimit - Round((FDropOnZone.ZoneLimit -
  1694. FDropOnZone.ParentZone.ChildZones.LimitBegin) * (DropDockSize + BorderWidth) / (FDropOnZone.ParentZone.Height));
  1695. { 然后计算垂直偏移量 }
  1696. OffsetXYLimitArr[doVertical] := DropCtlZone.TopLeft[doVertical] +
  1697. Integer(MakeLast[InsertAt]) * (DropCtlZone.HeightWidth[doVertical] - ControlXYLimitArr[doVertical]);
  1698. { 如果停靠操作是在垂直分割条附近,就重新计算垂直偏移量 }
  1699. if (FDropOnZone <> nil) and (InsertOrientation = doVertical) then
  1700. OffsetXYLimitArr[doVertical] := FDropOnZone.ZoneLimit - Round((FDropOnZone.ZoneLimit -
  1701. FDropOnZone.ParentZone.ChildZones.LimitBegin) * (DropDockSize + BorderWidth) / (FDropOnZone.ParentZone.Width));
  1702. end else
  1703. begin
  1704. { 这一项可能没有用处,因为DropCtlZone在这里一直为nil }
  1705. if TopZone.VisibleChildCount = 0 then
  1706. // if TopZone.ChildZones = nil then
  1707. begin
  1708. OffsetXYLimitArr[doHorizontal] := 0;
  1709. OffsetXYLimitArr[doVertical] := 0;
  1710. end else
  1711. begin
  1712. OffsetXYLimitArr[doHorizontal] := Integer(MakeLast[InsertAt]) * ControlXYLimitArr[doHorizontal];
  1713. // InsertAt := ReverseAt[InsertAt];
  1714. OffsetXYLimitArr[doVertical] := Integer(MakeLast[InsertAt]) * ControlXYLimitArr[doVertical];
  1715. end;
  1716. end;
  1717. if TopOrientation <> InsertOrientation then
  1718. begin
  1719. { TopOrientation和InsertOrientation的方向不同,
  1720. 就要先创建一个LastZone作为Control中的Zone父亲 }
  1721. LastZone := CnDockZoneClass.Create(Self);
  1722. if InsertOrientation <> CurrentOrientation then
  1723. { InsertOrientation和CurrentOrientation的方向不同,
  1724. 就要创建一个Zone作为LastZone和DropCtlZone的父亲 }
  1725. InsertNewParent(LastZone, DropCtlZone, InsertOrientation, MakeLast[InsertAt], True)
  1726. else
  1727. { 否者就只是简单的使LastZone和DropCtlZone成为兄弟关系 }
  1728. InsertSibling(LastZone, DropCtlZone, MakeLast[InsertAt], True);
  1729. { 调整LastZone的ZoneLimit属性 }
  1730. // LastZone.ZoneLimit := OffsetXYLimitArr[InsertOrientation] + ControlXYLimitArr[InsertOrientation];
  1731. { LastZone的Orientation属性和Control中的TopZone的方向相等 }
  1732. LastZone.Orientation := TopOrientation;
  1733. { LastZone是在根节点 }
  1734. LastLevel := 0;
  1735. end else
  1736. begin
  1737. LastLevel := 1;
  1738. if TopZone.ChildCount > 0 then
  1739. begin
  1740. ReadZone(False);
  1741. if InsertOrientation <> CurrentOrientation then
  1742. InsertNewParent(LastZone, DropCtlZone, InsertOrientation, MakeLast[InsertAt], True)
  1743. else InsertSibling(LastZone, DropCtlZone, MakeLast[InsertAt], True);
  1744. LastZone.ZoneLimit := ZoneLimit + OffsetXYLimitArr[InsertOrientation];
  1745. end else
  1746. begin
  1747. LastLevel := 0;
  1748. LastZone := TopZone;
  1749. end;
  1750. { 设置DropCtlZone的ZoneLimit属性 }
  1751. { if DropCtlZone <> nil then
  1752. begin
  1753. if TopZone.ChildCount = 1 then
  1754. DropCtlZone.ZoneLimit := TopXYLimit - OffsetXYLimitArr[InsertOrientation]
  1755. else
  1756. begin
  1757. if InsertAt in [alRight, alBottom] then
  1758. DropCtlZone.ZoneLimit := OffsetXYLimitArr[InsertOrientation]
  1759. else DropCtlZone.ZoneLimit := DropCtlZone.LimitBegin +
  1760. ControlXYLimitArr[InsertOrientation];
  1761. end;
  1762. end;}
  1763. end;
  1764. { 重新调整OffsetXYLimitArr数组的值 }
  1765. OffsetXYLimitArr[doHorizontal] := LastZone.TopLeft[doHorizontal];
  1766. OffsetXYLimitArr[doVertical] := LastZone.TopLeft[doVertical];
  1767. // Stream.Position := 0;
  1768. { 读数据 }
  1769. while True do
  1770. begin
  1771. ReadZone(True);
  1772. { 如果已经到达了Stream的结尾,就退出这次循环 }
  1773. if Level = TreeStreamEndFlag then
  1774. break;
  1775. end;
  1776. finally
  1777. Stream.Free;
  1778. EndUpdate;
  1779. end;
  1780. { 进行一些必要的设置 }
  1781. SetNewBounds(nil);
  1782. end;
  1783. procedure TCnVIDDockTree.DrawDockGrabber(Control: TControl; const ARect: TRect);
  1784. var Option: TCnVIDConjoinServerOption;
  1785. procedure DrawGrabberLine(Left, Top, Right, Bottom: Integer);
  1786. begin
  1787. with Canvas do
  1788. begin
  1789. Pen.Color := clBtnHighlight;
  1790. MoveTo(Right, Top);
  1791. LineTo(Left, Top);
  1792. LineTo(Left, Bottom);
  1793. Pen.Color := clBtnShadow;
  1794. LineTo(Right, Bottom);
  1795. LineTo(Right, Top-1);
  1796. end;
  1797. end;
  1798. var DrawRect: TRect;
  1799. uFormat: UINT;
  1800. ActiveControl: TControl;
  1801. const
  1802. TextAlignment: array[TAlignment] of UINT = (DT_LEFT, DT_RIGHT, DT_CENTER);
  1803. begin
  1804. with ARect do
  1805. if GrabbersPosition = gpLeft then
  1806. begin
  1807. end
  1808. else if GrabbersPosition = gpTop then
  1809. begin
  1810. if DockSite is TCnDockPanel then
  1811. Option := TCnVIDConjoinServerOption(TCnDockPanel(DockSite).DockServer.DockStyle.ConjoinServerOption)
  1812. else if DockSite is TCnConjoinPanel then
  1813. Option := TCnVIDConjoinServerOption(TCnConjoinDockHostForm(TCnConjoinPanel(DockSite).ParentForm).DockClient.DockStyle.ConjoinServerOption)
  1814. else
  1815. Option := nil;
  1816. { 首先调用PaintGradientBackground函数来画标题栏的背景色 }
  1817. ActiveControl := GetActiveControl;
  1818. DrawRect := ARect;
  1819. Inc(DrawRect.Top, 2);
  1820. DrawRect.Bottom := DrawRect.Top + GrabberSize - 3;
  1821. if Option <> nil then
  1822. begin
  1823. if ActiveControl = Control then
  1824. PaintGradientBackground(Canvas, DrawRect, Option.ActiveTitleStartColor, Option.ActiveTitleEndColor)
  1825. else
  1826. PaintGradientBackground(Canvas, DrawRect, Option.InactiveTitleStartColor, Option.InactiveTitleEndColor);
  1827. end;
  1828. PaintDockGrabberRect(Canvas, Control, DrawRect);
  1829. { 设置Canvas的字体和画刷的属性 }
  1830. if ActiveControl = Control then
  1831. Canvas.Font.Assign(Option.ActiveFont)
  1832. else Canvas.Font.Assign(Option.InactiveFont);
  1833. Canvas.Brush.Style := bsClear;
  1834. DrawRect := ARect;
  1835. GetCaptionRect(DrawRect);
  1836. uFormat := DT_SINGLELINE or (UINT(Option.TextEllipsis) * DT_END_ELLIPSIS) or TextAlignment[Option.TextAlignment];
  1837. DrawText(Canvas.Handle, PChar(TForm(Control).Caption), -1, DrawRect, uFormat);
  1838. DrawCloseButton(Canvas, FindControlZone(Control), Right-RightOffset-ButtonWidth, Top+TopOffset);
  1839. end
  1840. else if GrabbersPosition = gpBottom then
  1841. begin
  1842. end
  1843. else if GrabbersPosition = gpRight then
  1844. begin
  1845. end;
  1846. end;
  1847. procedure TCnVIDDockTree.ResetBounds(Force: Boolean);
  1848. var
  1849. R: TRect;
  1850. begin
  1851. { 当用户改变DockSite的大小的时候,程序会自动调用这个函数 }
  1852. if not (csLoading in DockSite.ComponentState) and
  1853. (TopZone <> nil) and (DockSite.DockClientCount > 0) then
  1854. begin
  1855. R := DockSite.ClientRect;
  1856. if DockSite is TCnConjoinPanel then
  1857. begin
  1858. { 最好不要使R.Right = R.Left,R.Bottom = R.Top }
  1859. if (R.Right = R.Left) then
  1860. Inc(R.Right, DockSite.Parent.UndockWidth);
  1861. if R.Bottom = R.Top then
  1862. Inc(R.Bottom, DockSite.Parent.UndockHeight);
  1863. end;
  1864. if Force or (not CompareMem(@R, @OldRect, SizeOf(TRect))) then
  1865. begin
  1866. case TopZone.Orientation of
  1867. doHorizontal:
  1868. begin
  1869. if R.Right - R.Left > 0 then
  1870. TopZone.ZoneLimit := R.Right - R.Left;
  1871. if R.Bottom - R.Top > 0 then
  1872. TopXYLimit := R.Bottom - R.Top;
  1873. end;
  1874. doVertical:
  1875. begin
  1876. if R.Bottom - R.Top > 0 then
  1877. TopZone.ZoneLimit := R.Bottom - R.Top;
  1878. if R.Right - R.Left > 0 then
  1879. TopXYLimit := R.Right - R.Left;
  1880. end;
  1881. end;
  1882. if DockSite.DockClientCount > 0 then
  1883. begin
  1884. { 首先确保这个函数不是在装载停靠信息的时候调用的 }
  1885. if not IsLoading then
  1886. begin
  1887. { 然后计算水平方向的缩放比例 }
  1888. if (R.Bottom - R.Top > 0 ) and (OldRect.Bottom - OldRect.Top > 0) then
  1889. ScaleBy := (R.Bottom - R.Top) / (OldRect.Bottom - OldRect.Top)
  1890. else ScaleBy := 1;
  1891. ShiftScaleOrient := doHorizontal;
  1892. { 调用ForEachAt对整个树调整 }
  1893. if (UpdateCount = 0) and (ScaleBy <> 1) then
  1894. ForEachAt(nil, ScaleZone, tskForward);
  1895. { 计算垂直方向的缩放比例 }
  1896. if (R.Right - R.Left > 0) and (OldRect.Right - OldRect.Left > 0) then
  1897. ScaleBy := (R.Right - R.Left) / (OldRect.Right - OldRect.Left)
  1898. else ScaleBy := 1;
  1899. ShiftScaleOrient := doVertical;
  1900. { 调用ForEachAt对整个树调整 }
  1901. if (UpdateCount = 0) and (ScaleBy <> 1) then
  1902. ForEachAt(nil, ScaleZone, tskForward);
  1903. end;
  1904. SetNewBounds(nil);
  1905. if UpdateCount = 0 then ForEachAt(nil, UpdateZone, tskForward);
  1906. { OldRect在下一次调用的时候会用到 }
  1907. OldRect := R;
  1908. end;
  1909. end;
  1910. end;
  1911. end;
  1912. procedure TCnVIDDockTree.DrawSplitterRect(const ARect: TRect);
  1913. begin
  1914. inherited;
  1915. { 不做什么事情 }
  1916. end;
  1917. procedure TCnVIDDockTree.SetActiveControl(const Value: TControl);
  1918. begin
  1919. if GetActiveControl <> Value then
  1920. begin
  1921. inherited SetActiveControl(Value);
  1922. DockSite.Invalidate;
  1923. end;
  1924. end;
  1925. procedure TCnVIDDockTree.WindowProc(var Message: TMessage);
  1926. var AAlign: TAlign;
  1927. begin
  1928. if Message.Msg = CM_DOCKCLIENT then
  1929. begin
  1930. { 用来获得DockSize的大小 }
  1931. AAlign := TCMDockClient(Message).DockSource.DropAlign;
  1932. TCMDockClient(Message).DockSource.DockRect := gi_DockRect;
  1933. GetDockEdge(gi_DockRect, TCMDockClient(Message).DockSource.DragPos, AAlign, TCMDockClient(Message).DockSource.Control);
  1934. end;
  1935. inherited WindowProc(Message);
  1936. end;
  1937. procedure TCnVIDDockTree.SplitterMouseUp;
  1938. var OldLimit: Integer;
  1939. Zone: TCnDockZone;
  1940. begin
  1941. Mouse.Capture := 0;
  1942. DrawSizeSplitter;
  1943. ReleaseDC(SizingWnd, SizingDC);
  1944. OldLimit := SizingZone.ZoneLimit;
  1945. { 只有是和SizingZone.ParentZone.Orientation相同的Orientation才能够在遍历中执行 }
  1946. ShiftScaleOrient := SizingZone.ParentZone.Orientation;
  1947. if SizingZone.ParentZone.Orientation = doHorizontal then
  1948. SizingZone.ZoneLimit := SizePos.y + (SplitterWidth div 2)
  1949. else
  1950. SizingZone.ZoneLimit := SizePos.x + (SplitterWidth div 2);
  1951. ParentLimit := SizingZone.LimitBegin;
  1952. if OldLimit - ParentLimit > 0 then
  1953. ScaleBy := (SizingZone.ZoneLimit - ParentLimit) / (OldLimit - ParentLimit)
  1954. else ScaleBy := 1;
  1955. { 调整当前的Zone的子女的ZoneLimit }
  1956. if SizingZone.ChildZones <> nil then
  1957. ForEachAt(SizingZone.ChildZones, ScaleChildZone, tskForward);
  1958. Zone := SizingZone;
  1959. while (Zone.NextSibling <> nil) and (not Zone.NextSibling.Visibled) do
  1960. begin
  1961. Zone.NextSibling.ZoneLimit := SizingZone.ZoneLimit;
  1962. Zone := Zone.NextSibling;
  1963. end;
  1964. if SizingZone.NextSibling <> nil then
  1965. begin
  1966. { 如果当前的Zone有后一个兄弟,
  1967. 就用当前的Zone的后一个兄弟的ZoneLimit减去当前的Zone的ZoneLimit }
  1968. if SizingZone.NextSibling.ZoneLimit - OldLimit > 0 then
  1969. ScaleBy := (SizingZone.NextSibling.ZoneLimit - SizingZone.ZoneLimit) / (SizingZone.NextSibling.ZoneLimit - OldLimit)
  1970. else ScaleBy := 1;
  1971. ParentLimit := SizingZone.NextSibling.ZoneLimit;
  1972. { 调整当前的Zone的下一个兄弟的子女的ZoneLimit }
  1973. if SizingZone.NextSibling.ChildZones <> nil then
  1974. ForEachAt(SizingZone.NextSibling.ChildZones, ScaleSiblingZone, tskForward);
  1975. end;
  1976. SetNewBounds(SizingZone.ParentZone);
  1977. ForEachAt(SizingZone.ParentZone, UpdateZone, tskForward);
  1978. SizingZone := nil;
  1979. end;
  1980. procedure TCnVIDDockTree.DrawDockSiteRect;
  1981. begin
  1982. // inherited;
  1983. end;
  1984. procedure TCnVIDDockTree.InsertSibling(NewZone, SiblingZone: TCnDockZone;
  1985. InsertLast, Update: Boolean);
  1986. begin
  1987. if (FDropOnZone <> nil) then
  1988. SiblingZone := FDropOnZone;
  1989. inherited;
  1990. end;
  1991. procedure TCnVIDDockTree.PositionDockRect(Client, DropCtl: TControl;
  1992. DropAlign: TAlign; var DockRect: TRect);
  1993. var
  1994. VisibleClients,
  1995. NewX, NewY, NewWidth, NewHeight: Integer;
  1996. Zone: TCnDockZone;
  1997. HTFlag: Integer;
  1998. MousePos: TPoint;
  1999. Scale: Double;
  2000. CtrlRect: TRect;
  2001. procedure DockOverSplitter;
  2002. begin
  2003. NewX := Zone.ParentZone.Left;
  2004. NewY := Zone.ParentZone.Top;
  2005. NewWidth := Zone.ParentZone.Width;
  2006. NewHeight := Zone.ParentZone.Height;
  2007. case Zone.ParentZone.Orientation of
  2008. doHorizontal:
  2009. begin
  2010. Scale := (Zone.ZoneLimit - Zone.ParentZone.ChildZones.LimitBegin) / NewHeight;
  2011. NewHeight := Min(NewHeight div 2, Client.ClientHeight);
  2012. NewY := Zone.ZoneLimit - Round(NewHeight * Scale);
  2013. end;
  2014. doVertical:
  2015. begin
  2016. Scale := (Zone.ZoneLimit - Zone.ParentZone.ChildZones.LimitBegin) / NewWidth;
  2017. NewWidth := Min(NewWidth div 2, Client.ClientWidth);
  2018. NewX := Zone.ZoneLimit - Round(NewWidth * Scale);
  2019. end;
  2020. end;
  2021. DockRect := Bounds(NewX, NewY, NewWidth, NewHeight);
  2022. if Zone.Visibled then
  2023. begin
  2024. if Zone.ParentZone.Orientation = doHorizontal then
  2025. CnGlobalDockPresident.DragObject.DropAlign := alBottom
  2026. else if Zone.ParentZone.Orientation = doVertical then
  2027. CnGlobalDockPresident.DragObject.DropAlign := alRight;
  2028. CnGlobalDockPresident.DragObject.DropOnControl := Zone.ChildControl;
  2029. FDropOnZone := Zone;
  2030. end;
  2031. end;
  2032. Label LBDropCtlExist;
  2033. begin
  2034. if DropAlign = alNone then
  2035. DropAlign := alClient;
  2036. VisibleClients := DockSite.VisibleDockClientCount;
  2037. FDropOnZone := nil;
  2038. MousePos := CnGlobalDockPresident.DragObject.DragPos;
  2039. MapWindowPoints(0, DockSite.Handle, MousePos, 2);
  2040. Zone := InternalHitTest(MousePos, HTFlag);
  2041. if Zone <> nil then
  2042. begin
  2043. if Zone.ChildControl <> nil then
  2044. begin
  2045. if (HTFlag = HTCaption) or (HTFlag = HTClose) then
  2046. begin
  2047. DockRect := Zone.ChildControl.BoundsRect;
  2048. CnGlobalDockPresident.DragObject.DropAlign := alClient;
  2049. if Zone.ChildControl is TCnTabDockHostForm then
  2050. begin
  2051. if CnGlobalDockPresident.DragObject is TCnVIDDragDockObject then
  2052. TCnVIDDragDockObject(CnGlobalDockPresident.DragObject).FDropTabControl :=
  2053. TCnVIDTabPageControl(TCnTabDockHostForm(Zone.ChildControl).PageControl);
  2054. end else
  2055. begin
  2056. if CnGlobalDockPresident.DragObject is TCnVIDDragDockObject then
  2057. TCnVIDDragDockObject(CnGlobalDockPresident.DragObject).FDropTabControl := nil;
  2058. end;
  2059. end;
  2060. end;
  2061. end;
  2062. { 当DockSite小于两个停靠控件在她里面,DockRect就应该作为被设置成DockSite的客户区域 }
  2063. if (DropCtl = nil)(* or (DropCtl.DockOrientation = doNoOrient) or
  2064. {(DropCtl = Client) or }(VisibleClients < 2) *)then
  2065. begin
  2066. if Zone <> nil then
  2067. begin
  2068. if Zone.ChildControl <> nil then
  2069. begin
  2070. if (HTFlag = HTCaption) or (HTFlag = HTClose) then
  2071. begin
  2072. CnGlobalDockPresident.DragObject.DropOnControl := Zone.ChildControl;
  2073. end else if HTFlag = HTClient then
  2074. begin
  2075. DropCtl := Zone.ChildControl;
  2076. goto LBDropCtlExist;
  2077. end else if HTFlag = HTSplitter then
  2078. DockOverSplitter;
  2079. end else if HTFlag = HTSplitter then
  2080. begin
  2081. DockOverSplitter;
  2082. end else Exit;
  2083. end else
  2084. begin
  2085. DockRect := Rect(0, 0, DockSite.ClientWidth, DockSite.ClientHeight);
  2086. { 当那里有一个停靠客户我们把DockSite的客户区分成一半 }
  2087. if VisibleClients > 0 then
  2088. with DockRect do
  2089. case DropAlign of
  2090. alLeft: Right := Right div 2;
  2091. alRight: Left := Right div 2;
  2092. alTop: Bottom := Bottom div 2;
  2093. alBottom: Top := Bottom div 2;
  2094. end;
  2095. end;
  2096. end
  2097. else begin
  2098. LBDropCtlExist:
  2099. { 否者,如果DockSite包含超过一个客户的时候, 根据鼠标下面的控件设置DockRect的坐标}
  2100. Zone := FindControlZone(DropCtl);
  2101. CtrlRect := DockRect;
  2102. MapWindowPoints(0, DockSite.Handle, CtrlRect, 2);
  2103. if Zone <> nil then
  2104. begin
  2105. { 判断鼠标是否在分割条附近,如果是的话,就调用DockOverSplitter函数然后退出,
  2106. 否者就计算CtrlRect的大小,在这里CtrlRect是指的是DropOnControl的大小 }
  2107. if Zone.ParentZone.Orientation = doVertical then
  2108. begin
  2109. if (DropAlign = alRight) and (Zone.NextSibling <> nil) then
  2110. begin
  2111. DockOverSplitter;
  2112. MapWindowPoints(DockSite.Handle, 0, DockRect, 2);
  2113. Exit;
  2114. end else if (DropAlign = alLeft) and (Zone.PrevSibling <> nil) then
  2115. begin
  2116. Zone := Zone.PrevSibling;
  2117. DockOverSplitter;
  2118. MapWindowPoints(DockSite.Handle, 0, DockRect, 2);
  2119. Exit;
  2120. end else
  2121. begin
  2122. if DropAlign in [alLeft, alRight] then
  2123. CtrlRect := Bounds(Zone.ParentZone.Left, Zone.ParentZone.Top, Zone.ParentZone.Width, Zone.ParentZone.Height)
  2124. else if (DropAlign in [alTop, alBottom, alClient]) then// or ((DockSite is TCnConjoinPanel) and (DropAlign = alClient)) then
  2125. begin
  2126. CtrlRect := DropCtl.BoundsRect;
  2127. Dec(CtrlRect.Top, GrabberSize);
  2128. end;
  2129. OffsetRect(CtrlRect, 0, GrabberSize);
  2130. end;
  2131. end else if Zone.ParentZone.Orientation = doHorizontal then
  2132. begin
  2133. if (DropAlign = alBottom) and (Zone.NextSibling <> nil) then
  2134. begin
  2135. DockOverSplitter;
  2136. MapWindowPoints(DockSite.Handle, 0, DockRect, 2);
  2137. Exit;
  2138. end else if (DropAlign = alTop) and (Zone.PrevSibling <> nil) then
  2139. begin
  2140. Zone := Zone.PrevSibling;
  2141. DockOverSplitter;
  2142. MapWindowPoints(DockSite.Handle, 0, DockRect, 2);
  2143. Exit;
  2144. end else
  2145. begin
  2146. if DropAlign in [alTop, alBottom] then
  2147. CtrlRect := Bounds(Zone.ParentZone.Left, Zone.ParentZone.Top, Zone.ParentZone.Width, Zone.ParentZone.Height)
  2148. else if (DropAlign in [alLeft, alRight, alClient]) then //or ((DockSite is TCnConjoinPanel) and (DropAlign = alClient)) then
  2149. begin
  2150. CtrlRect := DropCtl.BoundsRect;
  2151. Dec(CtrlRect.Top, GrabberSize);
  2152. end;
  2153. OffsetRect(CtrlRect, 0, GrabberSize);
  2154. end;
  2155. end else
  2156. begin
  2157. CtrlRect := DropCtl.BoundsRect;
  2158. Dec(CtrlRect.Top, GrabberSize);
  2159. OffsetRect(CtrlRect, 0, GrabberSize);
  2160. end;
  2161. { 然后根据CtrlRect和Control自身的位置来计算停靠的预览界面的大小 }
  2162. NewX := CtrlRect.Left;
  2163. NewY := CtrlRect.Top - GrabberSize;
  2164. NewWidth := CtrlRect.Right - CtrlRect.Left;
  2165. NewHeight := CtrlRect.Bottom - CtrlRect.Top;// + GrabberSize;
  2166. if DropAlign in [alLeft, alRight] then
  2167. NewWidth := Min(Client.UndockWidth, NewWidth div 2)
  2168. else if DropAlign in [alTop, alBottom] then
  2169. NewHeight := Min(Client.UndockHeight, NewHeight div 2);
  2170. case DropAlign of
  2171. alRight: Inc(NewX, CtrlRect.Right - CtrlRect.Left - NewWidth);
  2172. alBottom: Inc(NewY, CtrlRect.Bottom - CtrlRect.Top - NewHeight);
  2173. end;
  2174. DockRect := Bounds(NewX, NewY, NewWidth, NewHeight);
  2175. if DropAlign = alClient then
  2176. DockRect := Bounds(NewX, NewY, NewWidth, NewHeight);
  2177. if DropAlign = alNone then
  2178. begin
  2179. end;
  2180. end;
  2181. end;
  2182. MapWindowPoints(DockSite.Handle, 0, DockRect, 2);
  2183. end;
  2184. function TCnVIDDockTree.GetDockEdge(DockRect: TRect; MousePos: TPoint;
  2185. var DropAlign: TAlign; Control: TControl): TControl;
  2186. begin
  2187. Result := inherited GetDockEdge(DockRect, MousePos, DropAlign, Control);
  2188. if FLockDropDockSizeCount = 0 then
  2189. begin
  2190. // 只有在锁打开的时候才能调用这个程序
  2191. if DropAlign in [alLeft, alRight] then
  2192. DropDockSize := DockRect.Right - DockRect.Left
  2193. else if DropAlign in [alTop, alBottom] then
  2194. DropDockSize := DockRect.Bottom - DockRect.Top
  2195. else DropDockSize := 0;
  2196. Self.DockRect := DockRect;
  2197. end;
  2198. end;
  2199. procedure TCnVIDDockTree.InsertNewParent(NewZone, SiblingZone: TCnDockZone;
  2200. ParentOrientation: TDockOrientation; InsertLast, Update: Boolean);
  2201. begin
  2202. if FDropOnZone <> nil then
  2203. begin
  2204. SiblingZone := FDropOnZone;
  2205. InsertSibling(NewZone, SiblingZone, InsertLast, Update);
  2206. end else
  2207. inherited;
  2208. end;
  2209. procedure TCnVIDDockTree.RemoveZone(Zone: TCnDockZone; Hide: Boolean);
  2210. begin
  2211. if (FDropOnZone <> nil) and
  2212. ((FDropOnZone.NextSibling = Zone) or (FDropOnZone = Zone)) then
  2213. FDropOnZone := nil;
  2214. inherited;
  2215. end;
  2216. procedure TCnVIDDockTree.GetSiteInfo(Client: TControl;
  2217. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  2218. var Zone: TCnDockZone;
  2219. HTFlag: Integer;
  2220. Pos: TPoint;
  2221. Align: TAlign;
  2222. begin
  2223. { 根据鼠标位置来判断是否可以进行停靠操作 }
  2224. Pos := DockSite.ScreenToClient(MousePos);
  2225. Zone := InternalHitTest(Pos, HTFlag);
  2226. if Zone <> nil then
  2227. begin
  2228. if HTFlag = HTSPLITTER then
  2229. begin
  2230. InfluenceRect := GetSpiltterRect(Zone);
  2231. MapWindowPoints(DockSite.Handle, 0, InfluenceRect, 2);
  2232. end else
  2233. begin
  2234. Pos := MousePos;
  2235. if Zone.ChildControl <> nil then
  2236. Pos := Zone.ChildControl.ScreenToClient(MousePos);
  2237. Align := ComputeVIDDockingRect(Zone.ChildControl, Client, InfluenceRect, Pos);
  2238. if (Align = alNone) or (Client = Zone.ChildControl) then
  2239. begin
  2240. InfluenceRect := Rect(0, 0, 0, 0);
  2241. CanDock := False;
  2242. end else
  2243. begin
  2244. if Zone.ParentZone.Orientation = doVertical then
  2245. begin
  2246. if (Align = alRight) and (Zone.NextSibling <> nil) and (Zone.NextSibling.Visibled) then
  2247. begin
  2248. InfluenceRect := GetSpiltterRect(Zone);
  2249. InflateRect(InfluenceRect, DefExpandoRect, 0);
  2250. end else if (Align = alLeft) and (Zone.PrevSibling <> nil) and (Zone.PrevSibling.Visibled) then
  2251. begin
  2252. InfluenceRect := GetSpiltterRect(Zone.PrevSibling);
  2253. InflateRect(InfluenceRect, DefExpandoRect, 0);
  2254. end else
  2255. Exit;
  2256. end else if Zone.ParentZone.Orientation = doHorizontal then
  2257. begin
  2258. if (Align = alBottom) and (Zone.NextSibling <> nil) and (Zone.NextSibling.Visibled) then
  2259. begin
  2260. InfluenceRect := GetSpiltterRect(Zone);
  2261. InflateRect(InfluenceRect, 0, DefExpandoRect);
  2262. end else if (Align = alTop) and (Zone.PrevSibling <> nil) and (Zone.PrevSibling.Visibled) then
  2263. begin
  2264. InfluenceRect := GetSpiltterRect(Zone.PrevSibling);
  2265. InflateRect(InfluenceRect, 0, DefExpandoRect);
  2266. end else
  2267. Exit;
  2268. end else
  2269. Exit;
  2270. end;
  2271. MapWindowPoints(DockSite.Handle, 0, InfluenceRect, 2);
  2272. end;
  2273. end else
  2274. begin
  2275. InfluenceRect := Rect(0, 0, 0, 0);
  2276. CanDock := False;
  2277. end;
  2278. end;
  2279. procedure TCnVIDDockTree.LockDropDockSize;
  2280. begin
  2281. Inc(FLockDropDockSizeCount);
  2282. end;
  2283. procedure TCnVIDDockTree.UnlockDropDockSize;
  2284. begin
  2285. Dec(FLockDropDockSizeCount);
  2286. if FLockDropDockSizeCount < 0 then
  2287. FLockDropDockSizeCount := 0;
  2288. end;
  2289. procedure TCnVIDDockTree.PaintDockGrabberRect(Canvas: TCanvas;
  2290. Control: TControl; const ARect: TRect);
  2291. begin
  2292. { 没事做 }
  2293. end;
  2294. procedure TCnVIDDockTree.SetCaptionLeftOffset(const Value: Integer);
  2295. begin
  2296. FCaptionLeftOffset := Value;
  2297. end;
  2298. procedure TCnVIDDockTree.SetCaptionRightOffset(const Value: Integer);
  2299. begin
  2300. FCaptionRightOffset := Value;
  2301. end;
  2302. procedure TCnVIDDockTree.DrawCloseButton(Canvas: TCanvas; Zone: TCnDockZone; Left, Top: Integer);
  2303. var AZone: TCnAdvDockZone;
  2304. ADockClient: TCnDockClient;
  2305. begin
  2306. AZone := TCnAdvDockZone(Zone);
  2307. if AZone <> nil then
  2308. begin
  2309. { 如果EnableCloseBtn属性为False,就不画关闭按钮 }
  2310. ADockClient := FindDockClient(Zone.ChildControl);
  2311. if (ADockClient <> nil) and (not ADockClient.EnableCloseBtn) then Exit;
  2312. DrawFrameControl(Canvas.Handle, Rect(Left, Top, Left+ButtonWidth,
  2313. Top+ButtonHeight), DFC_CAPTION, DFCS_CAPTIONCLOSE or Integer(AZone.CloseBtnDown) * DFCS_PUSHED)
  2314. end;
  2315. end;
  2316. procedure TCnVIDDockTree.GetCaptionRect(var Rect: TRect);
  2317. begin
  2318. Inc(Rect.Left, 2 + CaptionLeftOffset);
  2319. Inc(Rect.Top, 3);
  2320. Dec(Rect.Right, ButtonWidth + CaptionRightOffset - 1);
  2321. Dec(Rect.Bottom, 2);
  2322. end;
  2323. procedure TCnVIDDockTree.AdjustDockRect(Control: TControl;
  2324. var ARect: TRect);
  2325. begin
  2326. if (DockSite.Align <> alClient) or (TopZone.VisibleChildTotal > 1) then
  2327. inherited;
  2328. end;
  2329. procedure TCnVIDDockTree.IgnoreZoneInfor(Stream: TMemoryStream);
  2330. var CompName: string;
  2331. begin
  2332. { TopZone中的Visibled(一字节)和VisibleSize(四字节)没有用,被忽略掉 }
  2333. Stream.Position := Stream.Position + 6;
  2334. { 读出控件的名称 }
  2335. ReadControlName(Stream, CompName);
  2336. end;
  2337. { TCnVIDConjoinPanel }
  2338. function TCnVIDConjoinPanel.CreateDockManager: IDockManager;
  2339. var Option: TCnVIDConjoinServerOption;
  2340. begin
  2341. Result := inherited CreateDockManager;
  2342. if (ParentForm <> nil) and (ParentForm.DockClient.DockStyle <> nil) and (Result <> nil) then
  2343. begin
  2344. Option := TCnVIDConjoinServerOption(ParentForm.DockClient.DockStyle.ConjoinServerOption);
  2345. (Result as ICnDockManager).GrabberSize := Option.GrabbersSize;
  2346. end;
  2347. end;
  2348. procedure TCnVIDConjoinPanel.CustomDockDrop(Source: TCnDragDockObject; X,
  2349. Y: Integer);
  2350. //var
  2351. // VIDSource: TCnVIDDragDockObject;
  2352. begin
  2353. { if Source is TCnVIDDragDockObject then
  2354. begin
  2355. VIDSource := TCnVIDDragDockObject(Source);
  2356. VIDSource.CurrState := dsDragEnter;
  2357. VIDSource.OldState := dsDragEnter;
  2358. SetTabControlPreview(VIDSource, VIDSource.FDropTabControl, dsDragLeave, VIDSource.DropAlign);
  2359. end;}
  2360. if not ((Source.Control.HostDockSite <> nil) and
  2361. (Source.DropOnControl = Source.Control.HostDockSite.Parent) and
  2362. (Source.DropAlign = alClient)) then
  2363. begin
  2364. inherited CustomDockDrop(Source, X, Y);
  2365. ParentForm.Caption := '';
  2366. if CnDockManager <> nil then
  2367. CnDockManager.ActiveControl := Source.Control;
  2368. if (Source.Control is TWinControl) and (Source.Control.Visible)
  2369. and TWinControl(Source.Control).CanFocus then
  2370. TWinControl(Source.Control).SetFocus;
  2371. end;
  2372. end;
  2373. procedure TCnVIDConjoinPanel.CustomDockOver(Source: TCnDragDockObject; X,
  2374. Y: Integer; State: TDragState; var Accept: Boolean);
  2375. var DropAlign: TAlign;
  2376. // VIDSource: TCnVIDDragDockObject;
  2377. // DropCtl: TControl;
  2378. begin
  2379. inherited CustomDockOver(Source, X, Y, State, Accept);
  2380. if Accept and (Source is TCnVIDDragDockObject) then
  2381. begin
  2382. { VIDSource := TCnVIDDragDockObject(Source);
  2383. DropCtl := VIDSource.GetDropCtl;
  2384. if (DropCtl <> VIDSource.DropOnControl) or
  2385. (VIDSource.FOldDropTabControl <> VIDSource.FDropTabControl) then
  2386. SetTabControlPreview(VIDSource, VIDSource.FOldDropTabControl, dsDragLeave, VIDSource.DropAlign);
  2387. SetTabControlPreview(VIDSource, VIDSource.FDropTabControl, State, VIDSource.DropAlign);
  2388. if State = dsDragLeave then
  2389. VIDSource.FDropTabControl := nil;
  2390. VIDSource.FOldDropTabControl := VIDSource.FDropTabControl;}
  2391. if State = dsDragMove then
  2392. begin
  2393. DropAlign := Source.DropAlign;
  2394. CnDockManager.GetDockEdge(Source.EraseDockRect, Source.DragPos, DropAlign, Source.Control);
  2395. end;
  2396. // VIDSource.OldState := VIDSource.CurrState;
  2397. // VIDSource.CurrState := State;
  2398. end;
  2399. end;
  2400. procedure TCnVIDConjoinPanel.CustomGetDockEdge(Source: TCnDragDockObject;
  2401. MousePos: TPoint; var DropAlign: TAlign);
  2402. begin
  2403. end;
  2404. procedure TCnVIDConjoinPanel.CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl;
  2405. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  2406. begin
  2407. CnDockManager.GetSiteInfo(Client, InfluenceRect, MousePos, CanDock);
  2408. CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
  2409. end;
  2410. function TCnVIDConjoinPanel.CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl;
  2411. Client: TControl): Boolean;
  2412. begin
  2413. Result := inherited CustomUnDock(Source, NewTarget, Client);
  2414. end;
  2415. procedure TCnVIDConjoinPanel.DockDrop(Source: TDragDockObject; X,
  2416. Y: Integer);
  2417. begin
  2418. inherited DockDrop(Source, X, Y);
  2419. end;
  2420. procedure TCnVIDConjoinPanel.UpdateCaption(Exclude: TControl);
  2421. begin
  2422. if VisibleDockClientCount > 1 then
  2423. ParentForm.Caption := ''
  2424. else
  2425. inherited UpdateCaption(Exclude);
  2426. end;
  2427. { TCnVIDTabPageControl }
  2428. procedure TCnVIDTabPageControl.CustomDockDrop(Source: TCnDragDockObject; X,
  2429. Y: Integer);
  2430. var ARect: TRect;
  2431. i: Integer;
  2432. VIDSource: TCnVIDDragDockObject;
  2433. DockClient: TCnDockClient;
  2434. Host: TCnConjoinDockHostForm;
  2435. Index: Integer;
  2436. begin
  2437. if Source.DropAlign in [alClient, alNone] then
  2438. begin
  2439. if Source is TCnVIDDragDockObject then
  2440. begin
  2441. Cn_LockWindow(nil);
  2442. IsLoading := True;
  2443. try
  2444. DoFloatForm(Source.Control);
  2445. FreeAllDockableForm;
  2446. VIDSource := TCnVIDDragDockObject(Source);
  2447. //SetTabControlPreview(VIDSource, VIDSource.FDropTabControl, dsDragLeave, VIDSource.DropAlign);
  2448. for i := 0 to VIDSource.SourceDockClientCount - 1 do
  2449. begin
  2450. Source.Control := VIDSource.SourceDockClients[i];
  2451. inherited CustomDockDrop(Source, X, Y);
  2452. if Source.Control is TCustomForm then
  2453. begin
  2454. if FTabImageList <> nil then
  2455. begin
  2456. Index := FTabImageList.AddIcon(TForm(Source.Control).Icon);
  2457. if Index <> -1 then
  2458. ActivePage.ImageIndex := Index;
  2459. end;
  2460. end;
  2461. end;
  2462. finally
  2463. IsLoading := False;
  2464. Cn_UnLockWindow;
  2465. ReshowAllVisibleWindow;
  2466. CnGlobalDockPresident.DragObject.Control := nil;
  2467. end;
  2468. end;
  2469. end else
  2470. begin
  2471. // 创建平铺的服务窗体
  2472. DockClient := FindDockClient(ParentForm);
  2473. if DockClient <> nil then
  2474. begin
  2475. ARect := ParentForm.BoundsRect;
  2476. Host := DockClient.CreateConjoinHostAndDockControl(ParentForm, Source.Control, Source.DropAlign);
  2477. Host.BoundsRect := ARect;
  2478. SetDockSite(ParentForm, False);
  2479. SetDockSite(TWinControl(Source.Control), False);
  2480. Host.Visible := True;
  2481. end;
  2482. end;
  2483. FPanel.SelectSheet := nil;
  2484. ParentForm.Caption := ActivePage.Caption;
  2485. end;
  2486. procedure TCnVIDTabPageControl.CustomDockOver(Source: TCnDragDockObject; X,
  2487. Y: Integer; State: TDragState; var Accept: Boolean);
  2488. var ARect: TRect;
  2489. // VIDSource: TCnVIDDragDockObject;
  2490. begin
  2491. {如果停靠客户上面有TDockClient控件,就同意停靠}
  2492. Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
  2493. if Accept then
  2494. begin
  2495. if ParentForm.HostDockSite = nil then
  2496. begin
  2497. Source.DropAlign := ComputeVIDDockingRect(Self, Source.Control, ARect, Point(X, Y));
  2498. if Source.DropAlign = alClient then
  2499. ARect.Top := ARect.Top + Cn_GetSysCaptionHeight;
  2500. { if Source is TCnVIDDragDockObject then
  2501. begin
  2502. VIDSource := TCnVIDDragDockObject(Source);
  2503. SetTabControlPreview(VIDSource, Self, State, VIDSource.DropAlign);
  2504. VIDSource.FDropTabControl := Self;
  2505. end;}
  2506. if Accept and (Source.DropAlign <> alNone) then
  2507. begin
  2508. Source.DockRect := ARect;
  2509. gi_DockRect := ARect;
  2510. end;
  2511. end else
  2512. begin
  2513. if ParentForm.HostDockSite is TCnCustomDockPanel then
  2514. begin
  2515. ARect := Source.DockRect;
  2516. TCnCustomDockPanel(ParentForm.HostDockSite).CnDockManager.PositionDockRect(Source.Control, Source.DropOnControl, Source.DropAlign, ARect);
  2517. Source.DockRect := ARect;
  2518. end;
  2519. end;
  2520. end;
  2521. end;
  2522. procedure TCnVIDTabPageControl.CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl;
  2523. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  2524. const
  2525. DefExpandoRect = 20;
  2526. var
  2527. CH_BW: Integer;
  2528. ARect: TRect;
  2529. begin
  2530. CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
  2531. if ParentForm.HostDockSite <> nil then
  2532. CanDock := False;
  2533. if CanDock then
  2534. begin
  2535. {获得停靠控件的矩形区域}
  2536. GetWindowRect(Parent.Handle, InfluenceRect);
  2537. if PtInRect(InfluenceRect, MousePos) then
  2538. begin
  2539. ARect := InfluenceRect;
  2540. InflateRect(ARect, -DefExpandoRect, -DefExpandoRect);
  2541. {获得标题栏的高度和边框的宽度}
  2542. CH_BW := Cn_GetSysCaptionHeightAndBorderWidth;
  2543. Inc(ARect.Top, CH_BW + 1);
  2544. Dec(ARect.Bottom, TabHeight);
  2545. if PtInRect(ARect, MousePos) then
  2546. InfluenceRect := Rect(0, 0, 0, 0);
  2547. end;
  2548. end;
  2549. end;
  2550. procedure TCnVIDTabPageControl.Change;
  2551. begin
  2552. // 当PageControl的当前Tab改变的时候,就要改变标题栏的Caption。
  2553. inherited Change;
  2554. ParentForm.Caption := ActivePage.Caption;
  2555. if ParentForm.HostDockSite is TCnCustomDockPanel then
  2556. begin
  2557. // 刷新ParentForm.HostDockSite中的把手部分。
  2558. if ParentForm.Visible and ParentForm.CanFocus then
  2559. ParentForm.SetFocus;
  2560. ParentForm.HostDockSite.Invalidate;
  2561. end;
  2562. if (ActivePage <> nil) and (ActivePage.Visible) and (ActivePage.CanFocus) then
  2563. begin
  2564. if ParentForm.Visible and ParentForm.CanFocus then
  2565. ActivePage.SetFocus;
  2566. end;
  2567. end;
  2568. procedure TCnVIDTabPageControl.AdjustClientRect(var Rect: TRect);
  2569. begin
  2570. // 调整Tab的Client的大小。
  2571. Rect := ClientRect;
  2572. if (Parent is TCnTabDockHostForm) and (VisibleDockClientCount = 1) then Exit;
  2573. case TabPosition of
  2574. tpTop: Inc(Rect.Top, Panel.FTabHeight - 1);
  2575. tpBottom: Dec(Rect.Bottom, Panel.FTabHeight - 1);
  2576. tpLeft: Inc(Rect.Left, Panel.FTabHeight - 1);
  2577. tpRight: Dec(Rect.Right, Panel.FTabHeight - 1);
  2578. end;
  2579. end;
  2580. procedure TCnVIDTabPageControl.CreateParams(var Params: TCreateParams);
  2581. begin
  2582. inherited;
  2583. end;
  2584. procedure TCnVIDTabPageControl.DrawTab(TabIndex: Integer;
  2585. const Rect: TRect; Active: Boolean);
  2586. begin
  2587. inherited DrawTab(TabIndex, Rect, Active);
  2588. end;
  2589. function TCnVIDTabPageControl.GetActiveFont: TFont;
  2590. begin
  2591. Result := FPanel.FActiveFont;
  2592. end;
  2593. function TCnVIDTabPageControl.GetActiveSheetColor: TColor;
  2594. begin
  2595. Result := FPanel.FActiveSheetColor;
  2596. end;
  2597. function TCnVIDTabPageControl.GetInactiveFont: TFont;
  2598. begin
  2599. Result := FPanel.FInactiveFont;
  2600. end;
  2601. function TCnVIDTabPageControl.GetInactiveSheetColor: TColor;
  2602. begin
  2603. Result := FPanel.Color;
  2604. end;
  2605. function TCnVIDTabPageControl.GetTabBottomOffset: Integer;
  2606. begin
  2607. Result := FPanel.TabBottomOffset;
  2608. end;
  2609. function TCnVIDTabPageControl.GetTabLeftOffset: Integer;
  2610. begin
  2611. Result := FPanel.TabLeftOffset;
  2612. end;
  2613. function TCnVIDTabPageControl.GetTabRightOffset: Integer;
  2614. begin
  2615. Result := FPanel.TabRightOffset;
  2616. end;
  2617. function TCnVIDTabPageControl.GetTabTopOffset: Integer;
  2618. begin
  2619. Result := FPanel.TabTopOffset;
  2620. end;
  2621. procedure TCnVIDTabPageControl.Paint;
  2622. begin
  2623. inherited Paint;
  2624. end;
  2625. procedure TCnVIDTabPageControl.Resize;
  2626. begin
  2627. // 当PageControl的大小改变的时候,也需要改变Fpanel的位置。
  2628. inherited Resize;
  2629. if Fpanel = nil then Exit;
  2630. case TabPosition of
  2631. tpLeft:
  2632. begin
  2633. // Fpanel在左边
  2634. FPanel.Left := 0;
  2635. FPanel.Width := Panel.FTabHeight;
  2636. FPanel.Top := 0;
  2637. FPanel.Height := Height;
  2638. end;
  2639. tpRight:
  2640. begin
  2641. // Fpanel在右边
  2642. FPanel.Left := Width - Panel.FTabHeight;
  2643. FPanel.Top := 0;
  2644. FPanel.Width := Panel.FTabHeight;
  2645. FPanel.Height := Height;
  2646. end;
  2647. tpTop:
  2648. begin
  2649. // Fpanel在上边
  2650. FPanel.Left := 0;
  2651. FPanel.Top := 0;
  2652. FPanel.Width := Width;
  2653. FPanel.Height := Panel.FTabHeight;
  2654. end;
  2655. tpBottom:
  2656. begin
  2657. // Fpanel在下边
  2658. FPanel.Left := 0;
  2659. FPanel.Top := Height - Panel.FTabHeight;
  2660. FPanel.Width := Width;
  2661. FPanel.Height := Panel.FTabHeight;
  2662. end;
  2663. end;
  2664. end;
  2665. procedure TCnVIDTabPageControl.SetActiveFont(const Value: TFont);
  2666. begin
  2667. FPanel.FActiveFont.Assign(Value);
  2668. if ActivePage <> nil then
  2669. TCnVIDDockTabSheet(ActivePage).SetSheetSort(ActivePage.Caption);
  2670. FPanel.Invalidate;
  2671. end;
  2672. procedure TCnVIDTabPageControl.SetActiveSheetColor(const Value: TColor);
  2673. begin
  2674. FPanel.FActiveSheetColor := Value;
  2675. FPanel.Invalidate;
  2676. end;
  2677. procedure TCnVIDTabPageControl.SetInactiveFont(const Value: TFont);
  2678. var i: Integer;
  2679. begin
  2680. FPanel.FInactiveFont.Assign(Value);
  2681. for i := 0 to PageCount - 1 do
  2682. if Pages[i] <> ActivePage then
  2683. TCnVIDDockTabSheet(Pages[i]).SetSheetSort(Pages[i].Caption);
  2684. FPanel.Invalidate;
  2685. end;
  2686. procedure TCnVIDTabPageControl.SetInactiveSheetColor(const Value: TColor);
  2687. begin
  2688. if FPanel.Color <> Value then
  2689. begin
  2690. FPanel.Color := Value;
  2691. FPanel.Invalidate;
  2692. end;
  2693. end;
  2694. procedure TCnVIDTabPageControl.SetTabBottomOffset(const Value: Integer);
  2695. begin
  2696. if FPanel.TabBottomOffset <> Value then
  2697. begin
  2698. FPanel.TabBottomOffset := Value;
  2699. FPanel.Invalidate;
  2700. end;
  2701. end;
  2702. procedure TCnVIDTabPageControl.SetTabHeight(Value: Smallint);
  2703. begin
  2704. inherited SetTabHeight(Value);
  2705. if Panel.FTabHeight <> Value then
  2706. begin
  2707. Panel.FTabHeight := Value;
  2708. FPanel.Invalidate;
  2709. end;
  2710. end;
  2711. procedure TCnVIDTabPageControl.SetTabLeftOffset(const Value: Integer);
  2712. begin
  2713. if FPanel.TabLeftOffset <> Value then
  2714. begin
  2715. FPanel.TabLeftOffset := Value;
  2716. FPanel.Invalidate;
  2717. end;
  2718. end;
  2719. procedure TCnVIDTabPageControl.SetTabPosition(Value: TTabPosition);
  2720. begin
  2721. Assert(Value in [tpTop, tpBottom], gs_CannotSetTabPosition);
  2722. inherited SetTabPosition(Value);
  2723. Resize;
  2724. end;
  2725. procedure TCnVIDTabPageControl.SetTabRightOffset(const Value: Integer);
  2726. begin
  2727. if FPanel.TabRightOffset <> Value then
  2728. begin
  2729. FPanel.TabRightOffset := Value;
  2730. FPanel.Invalidate;
  2731. end;
  2732. end;
  2733. procedure TCnVIDTabPageControl.SetTabTopOffset(const Value: Integer);
  2734. begin
  2735. if FPanel.TabTopOffset <> Value then
  2736. begin
  2737. FPanel.TabTopOffset := Value;
  2738. FPanel.Invalidate;
  2739. end;
  2740. end;
  2741. constructor TCnVIDTabPageControl.Create(AOwner: TComponent);
  2742. begin
  2743. inherited Create(AOwner);
  2744. FPanel := nil;
  2745. TabWidth := 1;
  2746. MultiLine := True;
  2747. CnDockTabSheetClass := TCnVIDDockTabSheet;
  2748. CnTabPanelClass := TCnTabPanel;
  2749. FTempSheet := nil;
  2750. TabPosition := tpBottom;
  2751. FTabImageList := nil;
  2752. Images := nil;
  2753. if AOwner is TCnTabDockHostForm then
  2754. begin
  2755. FTabImageList := TCustomImageList.Create(AOwner);
  2756. Images := FTabImageList;
  2757. end;
  2758. end;
  2759. destructor TCnVIDTabPageControl.Destroy;
  2760. begin
  2761. if FTabImageList <> nil then
  2762. begin
  2763. FTabImageList.Free;
  2764. FTabImageList := nil;
  2765. end;
  2766. if FPanel <> nil then
  2767. begin
  2768. FPanel.Free;
  2769. FPanel := nil;
  2770. end;
  2771. inherited;
  2772. end;
  2773. procedure TCnVIDTabPageControl.Loaded;
  2774. begin
  2775. inherited;
  2776. CreatePanel;
  2777. end;
  2778. procedure TCnVIDTabPageControl.CreatePanel;
  2779. begin
  2780. if FPanel = nil then
  2781. begin
  2782. FPanel := CnTabPanelClass.Create(Self);
  2783. FPanel.Page := Self;
  2784. FPanel.Parent := Self;
  2785. FPanel.TabLeftOffset := 5;
  2786. FPanel.TabRightOffset := 5;
  2787. FPanel.TabTopOffset := 3;
  2788. FPanel.TabBottomOffset := 3;
  2789. ActiveSheetColor := clBtnFace;
  2790. InactiveSheetColor := clBtnShadow;
  2791. end;
  2792. Resize;
  2793. end;
  2794. procedure TCnVIDTabPageControl.CreateWnd;
  2795. begin
  2796. inherited;
  2797. end;
  2798. procedure TCnVIDTabPageControl.SetActivePage(Page: TCnDockTabSheet);
  2799. begin
  2800. inherited SetActivePage(Page);
  2801. FPanel.Invalidate;
  2802. end;
  2803. procedure TCnVIDTabPageControl.DockDrop(Source: TDragDockObject; X,
  2804. Y: Integer);
  2805. var Index: Integer;
  2806. begin
  2807. inherited DockDrop(Source, X, Y);
  2808. FPanel.SelectSheet := nil;
  2809. ParentForm.Caption := ActivePage.Caption;
  2810. if Source.Control is TCustomForm then
  2811. begin
  2812. if Source.Control.Visible and (Source.Control.Parent is TCnDockTabSheet) then
  2813. ActivePage := TCnDockTabSheet(Source.Control.Parent);
  2814. if FTabImageList <> nil then
  2815. begin
  2816. Index := FTabImageList.AddIcon(TForm(Source.Control).Icon);
  2817. if (Index <> -1) and (ActivePage <> nil) then
  2818. ActivePage.ImageIndex := Index;
  2819. end;
  2820. end;
  2821. end;
  2822. function TCnVIDTabPageControl.GetDockClientFromMousePos(
  2823. MousePos: TPoint): TControl;
  2824. var PageIndex: Integer;
  2825. begin
  2826. Result := nil;
  2827. case TabPosition of
  2828. tpTop:
  2829. PageIndex := Panel.FindSheetWithPos(MousePos.X, MousePos.y, 0, Panel.Height - TabBottomOffset);
  2830. tpBottom:
  2831. PageIndex := Panel.FindSheetWithPos(MousePos.x, MousePos.y, TabBottomOffset, Panel.Height);
  2832. tpLeft:
  2833. PageIndex := Panel.FindSheetWithPos(MousePos.y, MousePos.x, 0, Panel.Height - TabBottomOffset);
  2834. tpRight:
  2835. PageIndex := Panel.FindSheetWithPos(MousePos.y, MousePos.x, TabBottomOffset, Panel.Height);
  2836. else
  2837. PageIndex := -1;
  2838. end;
  2839. if PageIndex >= 0 then
  2840. begin
  2841. Result := Pages[PageIndex].Controls[0];
  2842. if Result.HostDockSite <> Self then Result := nil;
  2843. end;
  2844. end;
  2845. procedure TCnVIDTabPageControl.CustomGetDockEdge(Source: TCnDragDockObject;
  2846. MousePos: TPoint; var DropAlign: TAlign);
  2847. var ARect: TRect;
  2848. begin
  2849. DropAlign := ComputeVIDDockingRect(Self, Source.Control, ARect, MousePos);
  2850. end;
  2851. function TCnVIDTabPageControl.GetVisibleTheetCount: Integer;
  2852. var i: Integer;
  2853. begin
  2854. Result := 0;
  2855. for i := 0 to PageCount - 1 do
  2856. if Pages[i].TabVisible then
  2857. Inc(Result);
  2858. end;
  2859. procedure TCnVIDTabPageControl.UpdateCaption(Exclude: TControl);
  2860. begin
  2861. ParentForm.Caption := ActivePage.Caption;
  2862. end;
  2863. procedure TCnVIDTabPageControl.SetHotTrack(Value: Boolean);
  2864. begin
  2865. inherited SetHotTrack(Value);
  2866. end;
  2867. procedure TCnVIDTabPageControl.SetImages(Value: TCustomImageList);
  2868. begin
  2869. inherited SetImages(Value);
  2870. if Panel <> nil then
  2871. begin
  2872. Panel.ShowTabImages := Value <> nil;
  2873. Panel.Invalidate;
  2874. end;
  2875. end;
  2876. function TCnVIDTabPageControl.GetHotTrackColor: TColor;
  2877. begin
  2878. Result := Panel.FHotTrackColor;
  2879. end;
  2880. procedure TCnVIDTabPageControl.SetHotTrackColor(const Value: TColor);
  2881. begin
  2882. if Panel.FHotTrackColor <> Value then
  2883. begin
  2884. Panel.FHotTrackColor := Value;
  2885. Panel.Invalidate;
  2886. end;
  2887. end;
  2888. function TCnVIDTabPageControl.GetShowTabImages: Boolean;
  2889. begin
  2890. Result := FPanel.FShowTabImages;
  2891. end;
  2892. procedure TCnVIDTabPageControl.SetShowTabImages(const Value: Boolean);
  2893. begin
  2894. FPanel.ShowTabImages := Value;
  2895. end;
  2896. function TCnVIDTabPageControl.CustomUnDock(Source: TCnDragDockObject;
  2897. NewTarget: TWinControl; Client: TControl): Boolean;
  2898. var CurrPage: TCnDockTabSheet;
  2899. i: Integer;
  2900. begin
  2901. if not ((Source.Control.HostDockSite <> nil) and
  2902. (Source.DropOnControl = Source.Control.HostDockSite.Parent) and
  2903. (Source.DropAlign = alClient)) then
  2904. begin
  2905. CurrPage := GetPageFromDockClient(Client);
  2906. if (CurrPage <> nil) then
  2907. begin
  2908. if (FTabImageList <> nil) and ShowTabImages and
  2909. (FTabImageList.Count > CurrPage.ImageIndex) then
  2910. begin
  2911. FTabImageList.Delete(CurrPage.ImageIndex);
  2912. for i := 0 to PageCount - 1 do
  2913. if Pages[i].ImageIndex > CurrPage.ImageIndex then
  2914. Pages[i].ImageIndex := Pages[i].ImageIndex - 1;
  2915. end;
  2916. end;
  2917. Result := inherited CustomUnDock(Source, NewTarget, Client);
  2918. end else Result := True;
  2919. end;
  2920. procedure TCnVIDTabPageControl.AfterConstruction;
  2921. begin
  2922. inherited;
  2923. CreatePanel;
  2924. end;
  2925. function TCnVIDTabPageControl.GetPage(Index: Integer): TCnVIDDockTabSheet;
  2926. begin
  2927. Result := TCnVIDDockTabSheet(inherited Pages[Index]);
  2928. end;
  2929. function TCnVIDTabPageControl.GetActiveVIDPage: TCnVIDDockTabSheet;
  2930. begin
  2931. Result := TCnVIDDockTabSheet(inherited ActivePage);
  2932. end;
  2933. procedure TCnVIDTabPageControl.SetActiveVIDPage(
  2934. const Value: TCnVIDDockTabSheet);
  2935. begin
  2936. ActivePage := Value;
  2937. end;
  2938. { TCnTabPanel }
  2939. constructor TCnTabPanel.Create(AOwner: TComponent);
  2940. begin
  2941. inherited Create(AOwner);
  2942. Page := nil;
  2943. FCaptionTopOffset := 0;
  2944. FCaptionLeftOffset := 5;
  2945. FCaptionRightOffset := 5;
  2946. FTabBottomOffset := 3;
  2947. FTabSplitterWidth := 3;
  2948. FTabHeight := 22;
  2949. FSortList := TList.Create;
  2950. FActiveFont := TFont.Create;
  2951. FActiveFont.Color := clBlack;
  2952. FInactiveFont := TFont.Create;
  2953. FInactiveFont.Color := clWhite;
  2954. FHotTrackColor := clBlue;
  2955. FTempPages := TList.Create;
  2956. FSelectHotIndex := -1;
  2957. FShowTabImages := False;
  2958. FSelectSheet := nil;
  2959. end;
  2960. procedure TCnTabPanel.DeleteSorts(Sheet: TCnVIDDockTabSheet);
  2961. var SheetIndex: Integer;
  2962. begin
  2963. SheetIndex := FSortList.IndexOf(Sheet);
  2964. if SheetIndex >= 0 then
  2965. FSortList.Delete(SheetIndex);
  2966. if Sheet <> nil then
  2967. Sheet.TabVisible := False;
  2968. SetShowTabWidth;
  2969. Page.Invalidate;
  2970. end;
  2971. destructor TCnTabPanel.Destroy;
  2972. begin
  2973. FActiveFont.Free;
  2974. FInactiveFont.Free;
  2975. FSortList.Free;
  2976. FTempPages.Free;
  2977. inherited;
  2978. end;
  2979. function TCnTabPanel.FindSheetWithPos(cX, cY, cTopOffset, cBottomOffset: Integer): Integer;
  2980. var i: Integer;
  2981. CompleteWidth, CurrTabWidth: Integer;
  2982. Pages: TList;
  2983. begin
  2984. Result := -1;
  2985. if (cY > cBottomOffset) or (cY < cTopOffset) then Exit;
  2986. CompleteWidth := 0;
  2987. if FSelectSheet = nil then
  2988. Pages := Page.PageSheets
  2989. else Pages := FTempPages;
  2990. for i := 0 to Pages.Count - 1 do
  2991. begin
  2992. if not TCnVIDDockTabSheet(Pages[i]).TabVisible then Continue;
  2993. CurrTabWidth := TCnVIDDockTabSheet(Pages[i]).ShowTabWidth;
  2994. if (cX >= FTabLeftOffset + CompleteWidth) and (cX <= FTabLeftOffset + CurrTabWidth + CompleteWidth + FTabSplitterWidth) then
  2995. begin
  2996. Result := i;
  2997. Exit;
  2998. end;
  2999. Inc(CompleteWidth, CurrTabWidth + FTabSplitterWidth);
  3000. end;
  3001. end;
  3002. function TCnTabPanel.GetPageIndexFromMousePos(X, Y: Integer): Integer;
  3003. begin
  3004. Result := -1;
  3005. case Page.TabPosition of
  3006. tpTop:
  3007. Result := FindSheetWithPos(X, y, 0, Height - TabBottomOffset);
  3008. tpBottom:
  3009. Result := FindSheetWithPos(x, y, TabBottomOffset, Height);
  3010. tpLeft:
  3011. Result := FindSheetWithPos(y, x, 0, Height - TabBottomOffset);
  3012. tpRight:
  3013. Result := FindSheetWithPos(y, x, TabBottomOffset, Height);
  3014. end;
  3015. end;
  3016. function TCnTabPanel.GetMaxTabWidth: TCnDockTabSheet;
  3017. var i: Integer;
  3018. MaxWidth, CurrWidth: Integer;
  3019. begin
  3020. Result := nil;
  3021. MaxWidth := 0;
  3022. if Page = nil then Exit;
  3023. for i := 0 to Page.PageCount - 1 do
  3024. begin
  3025. CurrWidth := Canvas.TextWidth(Page.Tabs[i]);
  3026. if MaxWidth < CurrWidth then
  3027. begin
  3028. Result := Page.Pages[i];
  3029. MaxWidth := CurrWidth;
  3030. end;
  3031. end;
  3032. end;
  3033. function TCnTabPanel.GetMinTabWidth: TCnDockTabSheet;
  3034. var i: Integer;
  3035. MinWidth, CurrWidth: Integer;
  3036. begin
  3037. Result := nil;
  3038. MinWidth := 0;
  3039. for i := 0 to Page.PageCount - 1 do
  3040. begin
  3041. CurrWidth := Canvas.TextWidth(Page.Tabs[i]);
  3042. if MinWidth > CurrWidth then
  3043. begin
  3044. Result := Page.Pages[i];
  3045. MinWidth := CurrWidth;
  3046. end;
  3047. end;
  3048. end;
  3049. function TCnTabPanel.GetPanelHeight: Integer;
  3050. begin
  3051. Result := 0;
  3052. case Page.TabPosition of
  3053. tpLeft, tpRight:
  3054. Result := Width;
  3055. tpTop, tpBottom:
  3056. Result := Height;
  3057. end;
  3058. end;
  3059. function TCnTabPanel.GetPanelWidth: Integer;
  3060. begin
  3061. Result := 0;
  3062. case Page.TabPosition of
  3063. tpLeft, tpRight:
  3064. Result := Height;
  3065. tpTop, tpBottom:
  3066. Result := Width;
  3067. end;
  3068. end;
  3069. function TCnTabPanel.GetSorts(Index: Integer): TCnVIDDockTabSheet;
  3070. begin
  3071. Result := FSortList[Index];
  3072. end;
  3073. function TCnTabPanel.GetTotalTabWidth: Integer;
  3074. var i: Integer;
  3075. begin
  3076. Result := 0;
  3077. if FSortList = nil then Exit;
  3078. for i := 0 to FSortList.Count - 1 do
  3079. Inc(Result, Sorts[i].TabWidth + Integer(i <> FSortList.Count - 1) * FTabSplitterWidth);
  3080. end;
  3081. procedure TCnTabPanel.MouseDown(Button: TMouseButton; Shift: TShiftState;
  3082. X, Y: Integer);
  3083. var Ctrl: TControl;
  3084. Index: Integer;
  3085. Msg: TWMMouse;
  3086. Sheet: TCnVIDDockTabSheet;
  3087. begin
  3088. inherited MouseDown(Button, Shift, X, Y);
  3089. if Page = nil then Exit;
  3090. { 首先根据鼠标的坐标确定是哪个Sheet }
  3091. Index := GetPageIndexFromMousePos(X, Y);
  3092. if (Index >= 0) then
  3093. begin
  3094. if Index <> Page.ActivePageIndex then
  3095. begin
  3096. Sheet := Page.ActiveVIDPage;
  3097. Page.ActivePageIndex := Index;
  3098. Sheet.SetSheetSort(Sheet.Caption);
  3099. Page.ActiveVIDPage.SetSheetSort(Page.ActiveVIDPage.Caption);
  3100. Page.Change;
  3101. Invalidate;
  3102. end;
  3103. if Button = mbLeft then
  3104. begin
  3105. // 只有在鼠标左键操作的时候才可以移动Tab。
  3106. FSelectSheet := TCnVIDDockTabSheet(Page.ActivePage);
  3107. { Delphi6.0以上版本 }
  3108. {$IFDEF COMPILER6_UP}
  3109. FTempPages.Assign(Page.PageSheets);
  3110. {$ELSE}
  3111. { Delphi5.0以下版本 }
  3112. AssignList(Page.PageSheets, FTempPages);
  3113. {$ENDIF}
  3114. end;
  3115. Ctrl := GetDockClientFromPageIndex(Index);
  3116. if Ctrl <> nil then
  3117. begin
  3118. { 查找到DockCtl上的TCnDockClient,然后把她赋值给全局变量GlobalDockClient }
  3119. GlobalDockClient := FindDockClient(Ctrl);
  3120. if GlobalDockClient <> nil then
  3121. begin
  3122. Msg.Msg := WM_NCLBUTTONDOWN + Integer(Button) * 3 + Integer(ssDouble in Shift) * 2;
  3123. Msg.Pos.x := X;
  3124. Msg.Pos.y := Y;
  3125. if not (ssDouble in Shift) then
  3126. // 单击鼠标
  3127. GlobalDockClient.DoNCButtonDown(Page.DoMouseEvent(Msg, Page), Button, msTabPage)
  3128. else
  3129. begin
  3130. // 双击鼠标
  3131. GlobalDockClient.DoNCButtonDblClk(Page.DoMouseEvent(Msg, Page), Button, msTabPage);
  3132. if (Button = mbLeft) and GlobalDockClient.CanFloat then
  3133. Ctrl.ManualDock(nil, nil, alNone);
  3134. end;
  3135. end;
  3136. end;
  3137. end;
  3138. end;
  3139. procedure TCnTabPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
  3140. var Index: Integer;
  3141. Ctrl: TControl;
  3142. ARect: TRect;
  3143. begin
  3144. inherited MouseMove(Shift, X, Y);
  3145. Index := GetPageIndexFromMousePos(X, Y);
  3146. if Page.HotTrack and (Index <> FSelectHotIndex) then
  3147. begin
  3148. FSelectHotIndex := Index;
  3149. Invalidate;
  3150. end;
  3151. if Assigned(FSelectSheet) then
  3152. begin
  3153. Index := GetPageIndexFromMousePos(X, Y);
  3154. if Index >= 0 then
  3155. begin
  3156. if (Index <> Page.ActivePageIndex) and (Page.PageCount > Index) then
  3157. begin
  3158. FSelectSheet.PageIndex := Index;
  3159. Invalidate;
  3160. end;
  3161. end else
  3162. begin
  3163. case Page.TabPosition of
  3164. tpTop:
  3165. ARect := Rect(0, 0, Width, Height - FTabBottomOffset);
  3166. tpBottom:
  3167. ARect := Rect(0, FTabBottomOffset, Width, Height);
  3168. tpLeft:
  3169. ARect := Rect(0, 0, Width - FTabBottomOffset, Height);
  3170. tpRight:
  3171. ARect := Rect(FTabBottomOffset, 0, Width, Height);
  3172. else
  3173. ARect := Rect(0, 0, 0, 0);
  3174. end;
  3175. if PtInRect(ARect, Point(X, Y)) then Exit;
  3176. if Page.FTempSheet = nil then
  3177. begin
  3178. Ctrl := GetDockClientFromPageIndex(FSelectSheet.PageIndex);
  3179. if Ctrl <> nil then
  3180. { 如果条件都满足,就调用CnGlobalDockPresident的BeginDrag方法,开始停靠操作 }
  3181. CnGlobalDockPresident.BeginDrag(Ctrl, False, 1);
  3182. end;
  3183. end;
  3184. end;
  3185. end;
  3186. procedure TCnTabPanel.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  3187. Y: Integer);
  3188. var Ctrl: TControl;
  3189. Index: Integer;
  3190. Msg: TWMMouse;
  3191. begin
  3192. inherited;
  3193. FSelectSheet := nil;
  3194. if Page = nil then Exit;
  3195. { 首先根据鼠标的坐标确定是哪个Sheet }
  3196. Index := GetPageIndexFromMousePos(X, Y);
  3197. Ctrl := GetDockClientFromPageIndex(Index);
  3198. if Ctrl <> nil then
  3199. begin
  3200. { 查找到DockCtl上的TCnDockClient,然后把她赋值给全局变量GlobalDockClient }
  3201. GlobalDockClient := FindDockClient(Ctrl);
  3202. if (GlobalDockClient <> nil) then
  3203. begin
  3204. Msg.Msg := WM_NCLBUTTONUP + Integer(Button) * 3 + Integer(ssDouble in Shift) * 2;
  3205. Msg.Pos := PointToSmallPoint(Page.ScreenToClient(ClientToScreen(Point(X, Y))));
  3206. if not (ssDouble in Shift) then
  3207. // 单击鼠标
  3208. GlobalDockClient.DoNCButtonUp(Page.DoMouseEvent(Msg, Page), Button, msTabPage);
  3209. end;
  3210. end;
  3211. end;
  3212. procedure TCnTabPanel.Paint;
  3213. var ARect: TRect;
  3214. CurrTabWidth: Integer;
  3215. i, CompleteWidth: Integer;
  3216. ImageWidth: Integer;
  3217. CaptionString: string;
  3218. // LogFont : TLogFont;
  3219. begin
  3220. inherited Paint;
  3221. if Page = nil then Exit;
  3222. if (Page.Images <> nil) and (Page.ShowTabImages) then
  3223. ImageWidth := Page.Images.Width
  3224. else ImageWidth := 0;
  3225. { 首先填充整个Panel的颜色 }
  3226. Canvas.Brush.Color := Page.ActiveSheetColor;
  3227. case Page.TabPosition of
  3228. tpLeft: Canvas.FillRect(Rect(PanelHeight - FTabBottomOffset, 0, PanelHeight, PanelWidth));
  3229. tpRight: Canvas.FillRect(Rect(0, 0, FTabBottomOffset, PanelWidth));
  3230. tpTop: Canvas.FillRect(Rect(0, PanelHeight - FTabBottomOffset, PanelWidth, PanelHeight));
  3231. tpBottom: Canvas.FillRect(Rect(0, 0, PanelWidth, FTabBottomOffset));
  3232. end;
  3233. { 再画一条黑色的阴影线 }
  3234. case Page.TabPosition of
  3235. tpTop, tpLeft: Canvas.Pen.Color := clWhite;
  3236. tpBottom, tpRight: Canvas.Pen.Color := clBlack;
  3237. end;
  3238. case Page.TabPosition of
  3239. tpLeft:
  3240. begin
  3241. Canvas.MoveTo(PanelHeight - FTabBottomOffset, 0);
  3242. Canvas.LineTo(PanelHeight - FTabBottomOffset, PanelWidth);
  3243. end;
  3244. tpRight:
  3245. begin
  3246. Canvas.MoveTo(FTabBottomOffset, 0);
  3247. Canvas.LineTo(FTabBottomOffset, PanelWidth);
  3248. end;
  3249. tpTop:
  3250. begin
  3251. Canvas.MoveTo(0, PanelHeight - FTabBottomOffset);
  3252. Canvas.LineTo(PanelWidth, PanelHeight - FTabBottomOffset);
  3253. end;
  3254. tpBottom:
  3255. begin
  3256. Canvas.MoveTo(0, FTabBottomOffset);
  3257. Canvas.LineTo(PanelWidth, FTabBottomOffset);
  3258. end;
  3259. end;
  3260. CompleteWidth := 0;
  3261. Canvas.Brush.Style := bsClear;
  3262. for i := 0 to Page.PageCount - 1 do
  3263. begin
  3264. if not Page.Pages[i].TabVisible then Continue;
  3265. { 获得当前页面的宽度, 宽度 = 字符串的宽度加上左边距和右边距 }
  3266. CurrTabWidth := TCnVIDDockTabSheet(Page.Pages[i]).ShowTabWidth;// + ImageWidth;
  3267. if Page.ActivePageIndex = i then
  3268. begin
  3269. { 画一个被选中的页面 }
  3270. Canvas.Brush.Color := Page.ActiveSheetColor;
  3271. case Page.TabPosition of
  3272. tpLeft: Canvas.FillRect(Rect(FTabTopOffset, CompleteWidth + FTabLeftOffset,
  3273. PanelHeight, CompleteWidth + FTabLeftOffset + CurrTabWidth));
  3274. tpRight: Canvas.FillRect(Rect(FTabBottomOffset, CompleteWidth + FTabLeftOffset,
  3275. PanelHeight - FTabTopOffset, CompleteWidth + FTabLeftOffset + CurrTabWidth));
  3276. tpTop: Canvas.FillRect(Rect(CompleteWidth + FTabLeftOffset, FTabTopOffset,
  3277. CompleteWidth + FTabLeftOffset + CurrTabWidth, PanelHeight));
  3278. tpBottom: Canvas.FillRect(Rect(CompleteWidth + FTabLeftOffset, FTabBottomOffset,
  3279. CompleteWidth + FTabLeftOffset + CurrTabWidth, PanelHeight - FTabTopOffset));
  3280. end;
  3281. { 画两条被照亮的白线 }
  3282. Canvas.Pen.Color := clWhite;
  3283. case Page.TabPosition of
  3284. tpLeft:
  3285. begin
  3286. Canvas.MoveTo(PanelHeight - FTabBottomOffset, CompleteWidth + FTabLeftOffset);
  3287. Canvas.LineTo(FTabTopOffset, CompleteWidth + FTabLeftOffset);
  3288. Canvas.LineTo(FTabTopOffset, CompleteWidth + FTabLeftOffset + CurrTabWidth);
  3289. Canvas.Pen.Color := clBlack;
  3290. Canvas.LineTo(PanelHeight - FTabBottomOffset, CompleteWidth + FTabLeftOffset + CurrTabWidth);
  3291. end;
  3292. tpRight:
  3293. begin
  3294. Canvas.MoveTo(FTabTopOffset, CompleteWidth + FTabLeftOffset);
  3295. Canvas.LineTo(PanelHeight - FTabBottomOffset, CompleteWidth + FTabLeftOffset);
  3296. Canvas.Pen.Color := clBlack;
  3297. Canvas.LineTo(PanelHeight - FTabBottomOffset, CompleteWidth + FTabLeftOffset + CurrTabWidth);
  3298. Canvas.LineTo(FTabTopOffset, CompleteWidth + FTabLeftOffset + CurrTabWidth);
  3299. end;
  3300. tpTop:
  3301. begin
  3302. Canvas.MoveTo(CompleteWidth + FTabLeftOffset, PanelHeight - FTabBottomOffset);
  3303. Canvas.LineTo(CompleteWidth + FTabLeftOffset, FTabTopOffset);
  3304. Canvas.LineTo(CompleteWidth + FTabLeftOffset + CurrTabWidth, FTabTopOffset);
  3305. Canvas.Pen.Color := clBlack;
  3306. Canvas.LineTo(CompleteWidth + FTabLeftOffset + CurrTabWidth, PanelHeight - FTabTopOffset);
  3307. end;
  3308. tpBottom:
  3309. begin
  3310. Canvas.MoveTo(CompleteWidth + FTabLeftOffset, FTabBottomOffset);
  3311. Canvas.LineTo(CompleteWidth + FTabLeftOffset, PanelHeight - FTabTopOffset);
  3312. Canvas.Pen.Color := clBlack;
  3313. Canvas.LineTo(CompleteWidth + FTabLeftOffset + CurrTabWidth, PanelHeight - FTabTopOffset);
  3314. Canvas.LineTo(CompleteWidth + FTabLeftOffset + CurrTabWidth, FTabBottomOffset);
  3315. end;
  3316. end;
  3317. { 字体为焦点字体 }
  3318. Canvas.Font.Assign(FActiveFont);
  3319. end else
  3320. begin
  3321. { 画页面之间的分割线 }
  3322. if (i < Page.ActivePageIndex - 1) or (i > Page.ActivePageIndex) then
  3323. begin
  3324. Canvas.Pen.Color := Page.InactiveFont.Color;
  3325. case Page.TabPosition of
  3326. tpLeft, tpRight:
  3327. begin
  3328. Canvas.MoveTo(PanelHeight - FTabBottomOffset - 3, CompleteWidth + FTabLeftOffset + CurrTabWidth);
  3329. Canvas.LineTo(FTabTopOffset + 2, CompleteWidth + FTabLeftOffset + CurrTabWidth);
  3330. end;
  3331. tpTop, tpBottom:
  3332. begin
  3333. Canvas.MoveTo(CompleteWidth + FTabLeftOffset + CurrTabWidth , PanelHeight - FTabBottomOffset - 3);
  3334. Canvas.LineTo(CompleteWidth + FTabLeftOffset + CurrTabWidth , FTabTopOffset + 2);
  3335. end;
  3336. end;
  3337. end;
  3338. Canvas.Brush.Color := Page.InactiveSheetColor;
  3339. { 字体为非焦点字体 }
  3340. Canvas.Font.Assign(FInactiveFont);
  3341. end;
  3342. if FSelectHotIndex = i then
  3343. Canvas.Font.Color := FHotTrackColor;
  3344. case Page.TabPosition of
  3345. tpLeft: ARect := Rect(FTabTopOffset + FCaptionTopOffset + 1,
  3346. CompleteWidth + FTabLeftOffset + FCaptionLeftOffset,
  3347. PanelHeight,
  3348. CompleteWidth + FTabLeftOffset + CurrTabWidth - FCaptionRightOffset);
  3349. tpRight: ARect := Rect(FTabBottomOffset + FCaptionTopOffset + 1,
  3350. CompleteWidth + FTabLeftOffset + FCaptionLeftOffset,
  3351. PanelHeight,
  3352. CompleteWidth + FTabLeftOffset + CurrTabWidth - FCaptionRightOffset);
  3353. tpTop: ARect := Rect(CompleteWidth + FTabLeftOffset + FCaptionLeftOffset + Integer(FShowTabImages) * (ImageWidth + FCaptionLeftOffset),
  3354. FTabTopOffset + FCaptionTopOffset + 1,
  3355. CompleteWidth + FTabLeftOffset + CurrTabWidth - FCaptionRightOffset,// + Integer(FShowTabImages) * FCaptionRightOffset,
  3356. PanelHeight);
  3357. tpBottom: ARect := Rect(CompleteWidth + FTabLeftOffset + FCaptionLeftOffset + Integer(FShowTabImages) * (ImageWidth + FCaptionLeftOffset),
  3358. FTabBottomOffset + FCaptionTopOffset + 1,
  3359. CompleteWidth + FTabLeftOffset + CurrTabWidth - FCaptionRightOffset,// + Integer(FShowTabImages) * FCaptionRightOffset,
  3360. PanelHeight);
  3361. end;
  3362. CaptionString := Page.Pages[i].Caption;
  3363. { 画文字 }
  3364. DrawText(Canvas.Handle, PChar(CaptionString), Length(CaptionString),
  3365. ARect, DT_LEFT or DT_SINGLELINE or DT_END_ELLIPSIS);
  3366. { 画图象 }
  3367. if FShowTabImages and (Page.Images <> nil) and (CurrTabWidth > ImageWidth + 2 * FCaptionLeftOffset) then
  3368. Page.Images.Draw(Canvas, CompleteWidth + FTabLeftOffset + FCaptionLeftOffset,
  3369. FTabBottomOffset + FCaptionTopOffset + 1, Page.Pages[i].ImageIndex, True);
  3370. Inc(CompleteWidth, CurrTabWidth + FTabSplitterWidth);
  3371. end;
  3372. { 最后画一个边框 }
  3373. Canvas.Brush.Color := Page.ActiveSheetColor;
  3374. ARect := ClientRect;
  3375. Canvas.FrameRect(ARect);
  3376. end;
  3377. procedure TCnTabPanel.Resize;
  3378. begin
  3379. inherited Resize;
  3380. SetShowTabWidth;
  3381. end;
  3382. procedure TCnTabPanel.SetCaptionLeftOffset(const Value: Integer);
  3383. begin
  3384. if FCaptionLeftOffset <> Value then
  3385. begin
  3386. FCaptionLeftOffset := Value;
  3387. Invalidate;
  3388. end;
  3389. end;
  3390. procedure TCnTabPanel.SetCaptionRightOffset(const Value: Integer);
  3391. begin
  3392. if FCaptionRightOffset <> Value then
  3393. begin
  3394. FCaptionRightOffset := Value;
  3395. Invalidate;
  3396. end;
  3397. end;
  3398. procedure TCnTabPanel.SetCaptionTopOffset(const Value: Integer);
  3399. begin
  3400. if FCaptionTopOffset <> Value then
  3401. begin
  3402. FCaptionTopOffset := Value;
  3403. Invalidate;
  3404. end;
  3405. end;
  3406. procedure TCnTabPanel.SetPage(const Value: TCnVIDTabPageControl);
  3407. begin
  3408. FPage := Value;
  3409. end;
  3410. procedure TCnTabPanel.SetPanelHeight(const Value: Integer);
  3411. begin
  3412. if PanelHeight <> Value then
  3413. begin
  3414. case Page.TabPosition of
  3415. tpLeft, tpRight: Width := Value;
  3416. tpTop, tpBottom: Height := Value;
  3417. end;
  3418. SetShowTabWidth;
  3419. end;
  3420. end;
  3421. procedure TCnTabPanel.SetTabBottomOffset(const Value: Integer);
  3422. begin
  3423. if FTabBottomOffset <> Value then
  3424. begin
  3425. FTabBottomOffset := Value;
  3426. Invalidate;
  3427. end;
  3428. end;
  3429. procedure TCnTabPanel.SetTabLeftOffset(const Value: Integer);
  3430. begin
  3431. if FTabLeftOffset <> Value then
  3432. begin
  3433. FTabLeftOffset := Value;
  3434. Invalidate;
  3435. end;
  3436. end;
  3437. procedure TCnTabPanel.SetTabRightOffset(const Value: Integer);
  3438. begin
  3439. if FTabRightOffset <> Value then
  3440. begin
  3441. FTabRightOffset := Value;
  3442. Invalidate;
  3443. end;
  3444. end;
  3445. procedure TCnTabPanel.SetTabSplitterWidth(const Value: Integer);
  3446. begin
  3447. if FTabSplitterWidth <> Value then
  3448. begin
  3449. FTabSplitterWidth := Value;
  3450. Invalidate;
  3451. end;
  3452. end;
  3453. procedure TCnTabPanel.SetTabTopOffset(const Value: Integer);
  3454. begin
  3455. if FTabTopOffset <> Value then
  3456. begin
  3457. FTabTopOffset := Value;
  3458. Invalidate;
  3459. end;
  3460. end;
  3461. procedure TCnTabPanel.SetTotalTabWidth(const Value: Integer);
  3462. begin
  3463. end;
  3464. function TCnTabPanel.GetDockClientFromPageIndex(Index: Integer): TControl;
  3465. begin
  3466. Result := nil;
  3467. if Index >= 0 then
  3468. begin
  3469. if Page.Pages[Index].ControlCount = 1 then
  3470. begin
  3471. Result := Page.Pages[Index].Controls[0];
  3472. if Result.HostDockSite <> Page then Result := nil;
  3473. end;
  3474. end;
  3475. end;
  3476. procedure TCnTabPanel.SetShowTabWidth;
  3477. var i, j, TempWidth: Integer;
  3478. PanelWidth, VisibleCount: Integer;
  3479. ImageWidth: Integer;
  3480. begin
  3481. if Page = nil then Exit;
  3482. if FSortList = nil then Exit;
  3483. PanelWidth := 0;
  3484. case Page.TabPosition of
  3485. tpTop, tpBottom:
  3486. PanelWidth := Width;
  3487. tpLeft, tpRight:
  3488. PanelWidth := Height;
  3489. end;
  3490. // 总共的宽度
  3491. TempWidth := PanelWidth - FCaptionLeftOffset - FCaptionRightOffset;
  3492. if Page.ShowTabImages then
  3493. ImageWidth := Page.Images.Width + FCaptionLeftOffset
  3494. else ImageWidth := 0;
  3495. VisibleCount := Page.VisibleTheetCount;
  3496. j := 0;
  3497. for i := 0 to FSortList.Count - 1 do
  3498. begin
  3499. // 只有可见的Tab才能调整Tab的宽度
  3500. if not Sorts[i].TabVisible then Continue;
  3501. // 只有当Tab能够显示的宽度小于Tab本身的宽度TabWidth的时候才重新设置Tab的ShowTabWidth,
  3502. // 否者就把Tab的ShowTabWidth设置成Tab本身的宽度TabWidth。
  3503. if (VisibleCount - j) * (Sorts[i].TabWidth + FTabSplitterWidth + ImageWidth) > TempWidth then
  3504. begin
  3505. Sorts[i].FShowTabWidth := TempWidth div (VisibleCount - j) - FTabSplitterWidth;
  3506. end else
  3507. Sorts[i].FShowTabWidth := Sorts[i].TabWidth + ImageWidth;
  3508. // TempWidth需要减去显示宽度ShowTabWidth和分割宽度TabSplitterWidth。
  3509. Dec(TempWidth, Sorts[i].FShowTabWidth + FTabSplitterWidth);
  3510. // 可见的Tab+1。
  3511. Inc(j);
  3512. end;
  3513. end;
  3514. procedure TCnTabPanel.CMMouseLeave(var Message: TMessage);
  3515. begin
  3516. inherited;
  3517. if FSelectHotIndex <> -1 then
  3518. begin
  3519. FSelectHotIndex := -1;
  3520. Invalidate;
  3521. end;
  3522. end;
  3523. procedure TCnTabPanel.SetShowTabImages(const Value: Boolean);
  3524. begin
  3525. if FShowTabImages <> Value then
  3526. begin
  3527. FShowTabImages := Value;
  3528. SetShowTabWidth;
  3529. Invalidate;
  3530. end;
  3531. end;
  3532. procedure TCnTabPanel.SetTabHeight(const Value: Integer);
  3533. begin
  3534. FTabHeight := Value;
  3535. Height := FTabHeight + FTabTopOffset + FTabBottomOffset;
  3536. end;
  3537. { TCnVIDDockTabSheet }
  3538. constructor TCnVIDDockTabSheet.Create(AOwner: TComponent);
  3539. begin
  3540. inherited Create(AOwner);
  3541. FIsSourceDockClient := False;
  3542. end;
  3543. destructor TCnVIDDockTabSheet.Destroy;
  3544. begin
  3545. if (PageControl is TCnVIDTabPageControl) and (PageControl <> nil) then
  3546. TCnVIDTabPageControl(PageControl).Panel.DeleteSorts(Self);
  3547. inherited Destroy;
  3548. end;
  3549. procedure TCnVIDDockTabSheet.Loaded;
  3550. begin
  3551. inherited;
  3552. SetSheetSort(Caption);
  3553. end;
  3554. procedure TCnVIDDockTabSheet.SetPageControl(
  3555. APageControl: TCnDockPageControl);
  3556. begin
  3557. inherited;
  3558. end;
  3559. procedure TCnVIDDockTabSheet.SetSheetSort(CaptionStr: string);
  3560. var TempWidth: Integer;
  3561. procedure DoSetSheetSort;
  3562. var i: Integer;
  3563. begin
  3564. TCnVIDTabPageControl(PageControl).Panel.FSortList.Remove(Self);
  3565. for i := 0 to TCnVIDTabPageControl(PageControl).Panel.FSortList.Count - 1 do
  3566. begin
  3567. if TCnVIDTabPageControl(PageControl).Panel.Sorts[i].TabWidth > TempWidth then
  3568. begin
  3569. TCnVIDTabPageControl(PageControl).Panel.FSortList.Insert(i, Self);
  3570. Exit;
  3571. end;
  3572. end;
  3573. TCnVIDTabPageControl(PageControl).Panel.FSortList.Add(Self);
  3574. end;
  3575. var TabPanel: TCnTabPanel;
  3576. begin
  3577. if (PageControl is TCnVIDTabPageControl) and (PageControl <> nil) then
  3578. begin
  3579. TabPanel := TCnVIDTabPageControl(PageControl).Panel;
  3580. if PageControl.ActivePage = Self then
  3581. TabPanel.Canvas.Font.Assign(TabPanel.Page.ActiveFont)
  3582. else TabPanel.Canvas.Font.Assign(TabPanel.Page.InactiveFont);
  3583. TempWidth := TabPanel.Canvas.TextWidth(
  3584. CaptionStr) + TabPanel.CaptionLeftOffset + TabPanel.CaptionRightOffset;
  3585. if TempWidth <> FTabWidth then
  3586. begin
  3587. DoSetSheetSort;
  3588. FTabWidth := TempWidth;
  3589. TabPanel.SetShowTabWidth;
  3590. TabPanel.Invalidate;
  3591. end;
  3592. end;
  3593. end;
  3594. procedure TCnVIDDockTabSheet.SetTabWidth(const Value: Integer);
  3595. begin
  3596. FTabWidth := Value;
  3597. end;
  3598. procedure TCnVIDDockTabSheet.UpdateTabShowing;
  3599. begin
  3600. inherited UpdateTabShowing;
  3601. TCnVIDTabPageControl(PageControl).Panel.SetShowTabWidth;
  3602. end;
  3603. procedure TCnVIDDockTabSheet.WMSETTEXT(var Message: TMessage);
  3604. begin
  3605. inherited;
  3606. SetSheetSort(PChar(Message.LParam));
  3607. end;
  3608. function TCnVIDDockStyle.GetControlName: string;
  3609. begin
  3610. Result := Format(gs_LikeVIDStyle, [inherited GetControlName]);
  3611. end;
  3612. { TCnVIDDragDockObject }
  3613. constructor TCnVIDDragDockObject.Create(AControl: TControl);
  3614. procedure DoGetSourceDockClients(Control: TControl);
  3615. var i: Integer;
  3616. DockableControl: TWinControl;
  3617. begin
  3618. if (Control is TCnDockableForm) then
  3619. begin
  3620. DockableControl := TCnDockableForm(Control).DockableControl;
  3621. for i := 0 to DockableControl.DockClientCount - 1 do
  3622. begin
  3623. // if not DockableControl.DockClients[i].Visible then Continue;
  3624. DoGetSourceDockClients(DockableControl.DockClients[i]);
  3625. end;
  3626. end else
  3627. FSourceDockClientList.Add(Control);
  3628. end;
  3629. begin
  3630. inherited Create(AControl);
  3631. FSourceDockClientList := TList.Create;
  3632. DoGetSourceDockClients(AControl);
  3633. FDropTabControl := nil;
  3634. FIsTabDockOver := False;
  3635. CurrState := dsDragEnter;
  3636. OldState := CurrState;
  3637. end;
  3638. procedure TCnVIDDragDockObject.GetBrush_PenSize_DrawRect(
  3639. var ABrush: TBrush; var PenSize: Integer; var DrawRect: TRect; Erase: Boolean);
  3640. begin
  3641. if DragTarget = nil then DropAlign := alNone;
  3642. inherited GetBrush_PenSize_DrawRect(ABrush, PenSize, DrawRect, Erase);
  3643. FIsTabDockOver := ((FOldDropAlign = alClient) and FErase) or
  3644. ((DropAlign = alClient) and not FErase);
  3645. FOldDropAlign := DropAlign;
  3646. FOldTarget := DragTarget;
  3647. end;
  3648. {$J+}
  3649. procedure TCnVIDDragDockObject.DefaultDockImage(Erase: Boolean);
  3650. var
  3651. DesktopWindow: HWND;
  3652. DC: HDC;
  3653. OldBrush: HBrush;
  3654. DrawRect: TRect;
  3655. PenSize: Integer;
  3656. ABrush: TBrush;
  3657. ButtomOffset: Integer;
  3658. MaxTabWidth: Integer;
  3659. const
  3660. LeftOffset = 4;
  3661. procedure DoDrawDefaultImage;
  3662. begin
  3663. with DrawRect do
  3664. begin
  3665. PatBlt(DC, Left + PenSize, Top, Right - Left - PenSize, PenSize, PATINVERT);
  3666. PatBlt(DC, Right - PenSize, Top + PenSize, PenSize, Bottom - Top - PenSize, PATINVERT);
  3667. PatBlt(DC, Left, Bottom - PenSize, Right - Left - PenSize, PenSize, PATINVERT);
  3668. PatBlt(DC, Left, Top, PenSize, Bottom - Top - PenSize, PATINVERT);
  3669. end;
  3670. end;
  3671. procedure DoDrawTabImage;
  3672. begin
  3673. with DrawRect do
  3674. begin
  3675. ButtomOffset := 15;
  3676. MaxTabWidth := 30;
  3677. PatBlt(DC, Left + PenSize, Top, Right - Left - PenSize, PenSize, PATINVERT);
  3678. PatBlt(DC, Right - PenSize, Top + PenSize, PenSize, Bottom - Top - 2 * PenSize - ButtomOffset, PATINVERT);
  3679. if DrawRect.Right - DrawRect.Left - 2 * PenSize < LeftOffset + 2 * PenSize + 2 * MaxTabWidth then
  3680. MaxTabWidth := (DrawRect.Right - DrawRect.Left - 4 * PenSize - LeftOffset) div 2;
  3681. if DrawRect.Bottom - DrawRect.Top - 2 * PenSize < 2 * ButtomOffset then
  3682. ButtomOffset := Max((DrawRect.Bottom - DrawRect.Top - 2 * PenSize) div 2, 0);
  3683. PatBlt(DC, Left, Bottom - PenSize - ButtomOffset, 2*PenSize + LeftOffset, PenSize, PATINVERT);
  3684. PatBlt(DC, Left + PenSize + LeftOffset, Bottom - ButtomOffset, PenSize, ButtomOffset, PATINVERT);
  3685. PatBlt(DC, Left + 2*PenSize + LeftOffset, Bottom - PenSize, MaxTabWidth, PenSize, PATINVERT);
  3686. PatBlt(DC, Left + 2*PenSize + LeftOffset + MaxTabWidth, Bottom - PenSize - ButtomOffset, PenSize, PenSize + ButtomOffset, PATINVERT);
  3687. PatBlt(DC, Left + 3*PenSize + LeftOffset + MaxTabWidth, Bottom - PenSize - ButtomOffset, Right - Left - 3*PenSize - LeftOffset - MaxTabWidth, PenSize, PATINVERT);
  3688. PatBlt(DC, Left, Top, PenSize, Bottom - Top - PenSize - ButtomOffset, PATINVERT);
  3689. end;
  3690. end;
  3691. begin
  3692. { 获得画刷句柄,画笔宽度和绘画区域 }
  3693. FErase := Erase;
  3694. GetBrush_PenSize_DrawRect(ABrush, PenSize, DrawRect, Erase);
  3695. DesktopWindow := GetDesktopWindow;
  3696. DC := GetDCEx(DesktopWindow, 0, DCX_CACHE or DCX_LOCKWINDOWUPDATE);
  3697. try
  3698. OldBrush := SelectObject(DC, ABrush.Handle);
  3699. if not FIsTabDockOver then
  3700. DoDrawDefaultImage
  3701. else DoDrawTabImage;
  3702. SelectObject(DC, OldBrush);
  3703. finally
  3704. ReleaseDC(DesktopWindow, DC);
  3705. end;
  3706. end;
  3707. {$J-}
  3708. destructor TCnVIDDragDockObject.Destroy;
  3709. begin
  3710. FDropTabControl := nil;
  3711. FSourceDockClientList.Free;
  3712. inherited Destroy;
  3713. end;
  3714. function TCnVIDDragDockObject.DragFindWindow(const Pos: TPoint): HWND;
  3715. begin
  3716. Result := 0;
  3717. end;
  3718. function TCnVIDDragDockObject.GetDropCtl: TControl;
  3719. var ARect: TRect;
  3720. i: Integer;
  3721. begin
  3722. Result := inherited GetDropCtl;
  3723. if (Result = nil) and (TargetControl is TCnCustomDockPanel) then
  3724. begin
  3725. for i := 0 to TargetControl.DockClientCount - 1 do
  3726. begin
  3727. if TargetControl.DockClients[i].Visible then
  3728. begin
  3729. ARect := TCnCustomDockPanel(DragTarget).CnDockManager.GetFrameRectEx(TargetControl.DockClients[i]);
  3730. if PtInRect(ARect, DragPos) then
  3731. begin
  3732. Result := TargetControl.DockClients[i];
  3733. Exit;
  3734. end;
  3735. end;
  3736. end;
  3737. end;
  3738. end;
  3739. function TCnVIDDragDockObject.GetSourceDockClient(
  3740. Index: Integer): TControl;
  3741. begin
  3742. Result := TControl(FSourceDockClientList[Index]);
  3743. end;
  3744. function TCnVIDDragDockObject.GetSourceDockClientCount: Integer;
  3745. begin
  3746. Result := FSourceDockClientList.Count;
  3747. end;
  3748. procedure TCnVIDDragDockObject.MouseMsg(var Msg: TMessage);
  3749. var APos: TPoint;
  3750. Page: TCnVIDTabPageControl;
  3751. begin
  3752. inherited MouseMsg(Msg);
  3753. case Msg.Msg of
  3754. WM_CAPTURECHANGED:
  3755. begin
  3756. if GlobalDockClient.ParentForm.HostDockSite is TCnVIDTabPageControl then
  3757. TCnVIDTabPageControl(GlobalDockClient.ParentForm.HostDockSite).Panel.MouseUp(mbLeft, [], 0, 0)
  3758. else if TWinControl(CnGlobalDockPresident.DragObject.DragTarget) is TCnVIDTabPageControl then
  3759. TCnVIDTabPageControl(CnGlobalDockPresident.DragObject.TargetControl).Panel.MouseUp(mbLeft, [], 0, 0);
  3760. end;
  3761. WM_MOUSEMOVE:
  3762. begin
  3763. if CnGlobalDockPresident.DragObject.TargetControl is TCnVIDTabPageControl then
  3764. begin
  3765. Page := TCnVIDTabPageControl(CnGlobalDockPresident.DragObject.TargetControl);
  3766. if Page.FTempSheet <> nil then
  3767. begin
  3768. APos := Point(TWMMouse(Msg).XPos, TWMMouse(Msg).YPos);
  3769. APos := Page.Panel.ScreenToClient(APos);
  3770. Page.Panel.MouseMove([], APos.X, APos.Y);
  3771. end;
  3772. end;
  3773. end;
  3774. end;
  3775. end;
  3776. procedure TCnVIDDragDockObject.SetOldState(const Value: TDragState);
  3777. begin
  3778. FOldState := Value;
  3779. end;
  3780. procedure TCnVIDDragDockObject.SetCurrState(const Value: TDragState);
  3781. begin
  3782. FCurrState := Value;
  3783. end;
  3784. function TCnVIDDragDockObject.CanLeave(NewTarget: TWinControl): Boolean;
  3785. begin
  3786. Result := inherited CanLeave(NewTarget);
  3787. end;
  3788. { TCnVIDDockZone }
  3789. {constructor TCnVIDDockZone.Create(Tree: TCnDockTree);
  3790. begin
  3791. inherited;
  3792. end;}
  3793. destructor TCnVIDDockZone.Destroy;
  3794. begin
  3795. inherited;
  3796. end;
  3797. function TCnVIDDockZone.GetSplitterLimit(IsMin: Boolean): Integer;
  3798. begin
  3799. if IsMin then
  3800. Result := ZoneLimit
  3801. else Result := LimitBegin;
  3802. end;
  3803. procedure TCnVIDDockZone.Insert(DockSize: Integer; Hide: Boolean);
  3804. var PrevShift,
  3805. NextShift: Integer;
  3806. TempSize: Integer;
  3807. BorderSize: Integer;
  3808. BeforeVisibleZone,
  3809. AfterVisibleZone: TCnDockZone;
  3810. BeginSize: Integer;
  3811. begin
  3812. if (ParentZone <> nil) and (ParentZone.VisibleChildCount = 0) then
  3813. ParentZone.Insert(ParentZone.VisibleSize, Hide);
  3814. if (ParentZone = nil) or ((ParentZone = Tree.TopZone) and (ParentZone.ChildCount <= 1)) then
  3815. begin
  3816. Visibled := True;
  3817. Exit;
  3818. end;
  3819. if (ParentZone <> nil) and (ParentZone.ChildZones <> nil) then
  3820. BeginSize := ParentZone.ChildZones.LimitBegin
  3821. else BeginSize := 0;
  3822. BeforeVisibleZone := BeforeClosestVisibleZone;
  3823. AfterVisibleZone := AfterClosestVisibleZone;
  3824. BorderSize := TCnVIDDockTree(Tree).BorderWidth * Integer(AfterClosestVisibleZone <> nil) div 2;
  3825. TempSize := ParentZone.HeightWidth[ParentZone.Orientation] + BorderSize;
  3826. Visibled := False;
  3827. if DockSize >= TempSize - (ParentZone.VisibleChildCount) * TCnVIDDockTree(Tree).MinSize then
  3828. DockSize := (TempSize - (ParentZone.VisibleChildCount) * TCnVIDDockTree(Tree).MinSize) div 2;
  3829. if DockSize < TCnVIDDockTree(Tree).MinSize then
  3830. DockSize := TempSize div 2;
  3831. if (BeforeVisibleZone = nil) and (AfterVisibleZone = nil) then
  3832. begin
  3833. PrevShift := 0;
  3834. NextShift := 0;
  3835. ZoneLimit := TempSize + BeginSize;
  3836. end else
  3837. if BeforeVisibleZone = nil then
  3838. begin
  3839. { 要插入的节点是在父节点的最前面 }
  3840. PrevShift := 0;
  3841. NextShift := DockSize + BorderSize;
  3842. ZoneLimit := DockSize + LimitBegin + BorderSize;
  3843. if ParentZone.VisibleChildCount = 1 then
  3844. AfterVisibleZone.ZoneLimit := TempSize + BeginSize;
  3845. end else if AfterVisibleZone = nil then
  3846. begin
  3847. { 要插入的节点是在父节点的最后面 }
  3848. PrevShift := DockSize + BorderSize;
  3849. NextShift := 0;
  3850. if (ParentZone.VisibleChildCount = 1) and (ParentZone = Tree.TopZone) then
  3851. BeforeVisibleZone.ZoneLimit := Tree.TopXYLimit - PrevShift
  3852. else
  3853. BeforeVisibleZone.ZoneLimit := BeforeVisibleZone.ZoneLimit - PrevShift;
  3854. ZoneLimit := TempSize + BeginSize;
  3855. end else
  3856. begin
  3857. { 要插入的节点是在父节点的中间 }
  3858. PrevShift := Round((BeforeVisibleZone.ZoneLimit - BeginSize) * (DockSize + BorderSize) / TempSize);
  3859. NextShift := DockSize - PrevShift;
  3860. if (ParentZone.VisibleChildCount = 1) and (ParentZone = Tree.TopZone) then
  3861. BeforeVisibleZone.ZoneLimit := Tree.TopXYLimit - PrevShift
  3862. else
  3863. BeforeVisibleZone.ZoneLimit := BeforeVisibleZone.ZoneLimit - PrevShift;
  3864. ZoneLimit := BeforeVisibleZone.ZoneLimit + DockSize;
  3865. end;
  3866. { 如果新节点有上一个兄弟节点 }
  3867. if PrevShift <> 0 then
  3868. begin
  3869. with TCnVIDDockTree(Tree) do
  3870. begin
  3871. { 当遍历到新节点的上一个兄弟节点的时候,就停止遍历 }
  3872. ReplacementZone := BeforeVisibleZone;
  3873. try
  3874. if (BeforeVisibleZone.ZoneLimit - BeginSize) * (BeforeVisibleZone.ZoneLimit - BeginSize + PrevShift) <> 0 then
  3875. ScaleBy := (BeforeVisibleZone.ZoneLimit - BeginSize) / (BeforeVisibleZone.ZoneLimit - BeginSize + PrevShift)
  3876. else ScaleBy := 1;
  3877. ParentLimit := BeginSize;
  3878. ShiftScaleOrient := ParentZone.Orientation;
  3879. if ScaleBy <> 1 then
  3880. ForEachAt(ParentZone.ChildZones, ScaleChildZone, tskMiddle, tspChild);
  3881. finally
  3882. ReplacementZone := nil;
  3883. end;
  3884. end;
  3885. { 对PrevSibling的ZoneLimit进行调整 }
  3886. if BeforeVisibleZone.LimitSize < TCnVIDDockTree(Tree).MinSize then
  3887. BeforeVisibleZone.ZoneLimit := BeforeVisibleZone.LimitBegin + TCnVIDDockTree(Tree).MinSize;
  3888. end;
  3889. { 如果新节点有下一个兄弟节点 }
  3890. if NextShift <> 0 then
  3891. begin
  3892. with TCnVIDDockTree(Tree) do
  3893. begin
  3894. if (TempSize + BeginSize - LimitBegin - NextShift) * (TempSize + BeginSize - LimitBegin) <> 0 then
  3895. ScaleBy := (TempSize + BeginSize - LimitBegin - NextShift) / (TempSize + BeginSize - LimitBegin)
  3896. else ScaleBy := 1;
  3897. ParentLimit := TempSize + BeginSize;
  3898. ShiftScaleOrient := ParentZone.Orientation;
  3899. if ScaleBy <> 1 then
  3900. ForEachAt(AfterVisibleZone, ScaleSiblingZone, tskForward);
  3901. end;
  3902. end;
  3903. Visibled := True;
  3904. end;
  3905. procedure TCnVIDDockZone.Remove(DockSize: Integer; Hide: Boolean);
  3906. var PrevShift,
  3907. NextShift: Integer;
  3908. TempSize: Integer;
  3909. BorderSize: Integer;
  3910. BeforeVisibleZone,
  3911. AfterVisibleZone: TCnDockZone;
  3912. BeginSize: Integer;
  3913. begin
  3914. if (ParentZone <> nil) and (ParentZone.VisibleChildCount = 1) and (ParentZone <> Tree.TopZone) then
  3915. ParentZone.Remove(ParentZone.LimitSize, Hide);
  3916. if (ParentZone = nil) or ((ParentZone = Tree.TopZone) and (ParentZone.ChildCount <= 1)) then
  3917. begin
  3918. Visibled := False;
  3919. Exit;
  3920. end;
  3921. if (ParentZone <> nil) and (ParentZone.ChildZones <> nil) then
  3922. BeginSize := ParentZone.ChildZones.LimitBegin
  3923. else BeginSize := 0;
  3924. BeforeVisibleZone := BeforeClosestVisibleZone;
  3925. AfterVisibleZone := AfterClosestVisibleZone;
  3926. BorderSize := TCnVIDDockTree(Tree).BorderWidth * Integer(AfterClosestVisibleZone <> nil) div 2;
  3927. TempSize := ParentZone.HeightWidth[ParentZone.Orientation] + BorderSize;
  3928. if DockSize > TempSize - (ParentZone.VisibleChildCount-1) * TCnVIDDockTree(Tree).MinSize then
  3929. DockSize := TempSize - (ParentZone.VisibleChildCount-1) * TCnVIDDockTree(Tree).MinSize;
  3930. if DockSize = 0 then
  3931. DockSize := TempSize div 2;
  3932. Visibled := False;
  3933. if (BeforeVisibleZone = nil) and (AfterVisibleZone = nil) then
  3934. Exit;
  3935. if BeforeVisibleZone = nil then
  3936. begin
  3937. { 要插入的节点是在父节点的最前面 }
  3938. PrevShift := 0;
  3939. NextShift := -DockSize + BorderSize;
  3940. ZoneLimit := -DockSize + BorderSize + BeginSize;
  3941. end else if AfterVisibleZone = nil then
  3942. begin
  3943. { 要插入的节点是在父节点的最后面 }
  3944. PrevShift := -DockSize + BorderSize;
  3945. NextShift := 0;
  3946. BeforeVisibleZone.ZoneLimit := BeforeVisibleZone.ZoneLimit - PrevShift;
  3947. ZoneLimit := TempSize + BeginSize;
  3948. end else
  3949. begin
  3950. { 要插入的节点是在父节点的中间 }
  3951. PrevShift := -Round((BeforeVisibleZone.ZoneLimit - BeginSize) * (DockSize + BorderSize) / (TempSize - (DockSize + BorderSize)));
  3952. NextShift := -DockSize - PrevShift;
  3953. BeforeVisibleZone.ZoneLimit := BeforeVisibleZone.ZoneLimit - PrevShift;
  3954. ZoneLimit := BeforeVisibleZone.ZoneLimit;
  3955. end;
  3956. { 如果新节点有上一个兄弟节点 }
  3957. if PrevShift <> 0 then
  3958. begin
  3959. with TCnVIDDockTree(Tree) do
  3960. begin
  3961. { 当遍历到新节点的上一个兄弟节点的时候,就停止遍历 }
  3962. ReplacementZone := BeforeVisibleZone;
  3963. try
  3964. if (BeforeVisibleZone.ZoneLimit - BeginSize)*(BeforeVisibleZone.ZoneLimit - BeginSize + PrevShift) <> 0 then
  3965. ScaleBy := (BeforeVisibleZone.ZoneLimit - BeginSize) / (BeforeVisibleZone.ZoneLimit - BeginSize + PrevShift)
  3966. else ScaleBy := 1;
  3967. ParentLimit := BeginSize;
  3968. ShiftScaleOrient := ParentZone.Orientation;
  3969. if ScaleBy <> 1 then
  3970. ForEachAt(ParentZone.ChildZones, ScaleChildZone, tskMiddle, tspChild);
  3971. finally
  3972. ReplacementZone := nil;
  3973. end;
  3974. end;
  3975. { 对PrevSibling的ZoneLimit进行调整 }
  3976. if BeforeVisibleZone.LimitSize < TCnVIDDockTree(Tree).MinSize then
  3977. BeforeVisibleZone.ZoneLimit := BeforeVisibleZone.LimitBegin + TCnVIDDockTree(Tree).MinSize;
  3978. end;
  3979. { 如果新节点有下一个兄弟节点 }
  3980. if NextShift <> 0 then
  3981. begin
  3982. with TCnVIDDockTree(Tree) do
  3983. begin
  3984. if (TempSize + BeginSize - LimitBegin) * (TempSize + BeginSize - LimitBegin + NextShift) <> 0 then
  3985. ScaleBy := (TempSize + BeginSize - LimitBegin) / (TempSize + BeginSize - LimitBegin + NextShift)
  3986. else ScaleBy := 1;
  3987. ParentLimit := TempSize + BeginSize;
  3988. ShiftScaleOrient := ParentZone.Orientation;
  3989. if ScaleBy <> 1 then
  3990. ForEachAt(AfterVisibleZone, ScaleSiblingZone, tskForward);
  3991. end;
  3992. end;
  3993. end;
  3994. { TCnVIDTabServerOption }
  3995. procedure TCnVIDTabServerOption.Assign(Source: TPersistent);
  3996. begin
  3997. if Source is TCnVIDTabServerOption then
  3998. begin
  3999. FActiveFont.Assign(TCnVIDTabServerOption(Source).FActiveFont);
  4000. FActiveSheetColor := TCnVIDTabServerOption(Source).FActiveSheetColor;
  4001. FHotTrackColor := TCnVIDTabServerOption(Source).FHotTrackColor;
  4002. FInactiveFont.Assign(TCnVIDTabServerOption(Source).FInactiveFont);
  4003. FInactiveSheetColor := TCnVIDTabServerOption(Source).FInactiveSheetColor;
  4004. FShowTabImages := TCnVIDTabServerOption(Source).FShowTabImages;
  4005. end;
  4006. inherited Assign(Source);
  4007. end;
  4008. constructor TCnVIDTabServerOption.Create(ADockStyle: TCnBasicDockStyle);
  4009. begin
  4010. inherited Create(ADockStyle);
  4011. TabPosition := tpBottom;
  4012. FActiveFont := TFont.Create;
  4013. FActiveSheetColor := clBtnFace;
  4014. FHotTrackColor := clBlue;
  4015. FInactiveFont := TFont.Create;
  4016. FInactiveFont.Color := clWhite;
  4017. FInactiveSheetColor := clBtnShadow;
  4018. FShowTabImages := False;
  4019. end;
  4020. destructor TCnVIDTabServerOption.Destroy;
  4021. begin
  4022. FActiveFont.Free;
  4023. FInactiveFont.Free;
  4024. inherited;
  4025. end;
  4026. function TCnVIDTabServerOption.GetActiveFont: TFont;
  4027. begin
  4028. Result := FActiveFont;
  4029. end;
  4030. function TCnVIDTabServerOption.GetActiveSheetColor: TColor;
  4031. begin
  4032. Result := FActiveSheetColor;
  4033. end;
  4034. function TCnVIDTabServerOption.GetHotTrackColor: TColor;
  4035. begin
  4036. Result := FHotTrackColor;
  4037. end;
  4038. function TCnVIDTabServerOption.GetInactiveFont: TFont;
  4039. begin
  4040. Result := FInactiveFont;
  4041. end;
  4042. function TCnVIDTabServerOption.GetInactiveSheetColor: TColor;
  4043. begin
  4044. Result := FInactiveSheetColor;
  4045. end;
  4046. function TCnVIDTabServerOption.GetShowTabImages: Boolean;
  4047. begin
  4048. Result := FShowTabImages;
  4049. end;
  4050. procedure TCnVIDTabServerOption.ResetDockControlOption;
  4051. begin
  4052. inherited;
  4053. end;
  4054. procedure TCnVIDTabServerOption.ResetTabPageControl(
  4055. APage: TCnTabPageControl);
  4056. begin
  4057. inherited;
  4058. if APage is TCnVIDTabPageControl then
  4059. begin
  4060. TCnVIDTabPageControl(APage).ActiveFont := ActiveFont;
  4061. TCnVIDTabPageControl(APage).ActiveSheetColor := ActiveSheetColor;
  4062. TCnVIDTabPageControl(APage).HotTrackColor := HotTrackColor;
  4063. TCnVIDTabPageControl(APage).InactiveFont := InactiveFont;
  4064. TCnVIDTabPageControl(APage).InactiveSheetColor := InactiveSheetColor;
  4065. TCnVIDTabPageControl(APage).ShowTabImages := ShowTabImages;
  4066. TCnVIDTabPageControl(APage).TabPosition := TabPosition;
  4067. end;
  4068. end;
  4069. procedure TCnVIDTabServerOption.SetActiveFont(const Value: TFont);
  4070. begin
  4071. FActiveFont.Assign(Value);
  4072. ResetDockControlOption;
  4073. end;
  4074. procedure TCnVIDTabServerOption.SetActiveSheetColor(const Value: TColor);
  4075. begin
  4076. if FActiveSheetColor <> Value then
  4077. begin
  4078. FActiveSheetColor := Value;
  4079. ResetDockControlOption;
  4080. end;
  4081. end;
  4082. procedure TCnVIDTabServerOption.SetHotTrackColor(const Value: TColor);
  4083. begin
  4084. if FHotTrackColor <> Value then
  4085. begin
  4086. FHotTrackColor := Value;
  4087. ResetDockControlOption;
  4088. end;
  4089. end;
  4090. procedure TCnVIDTabServerOption.SetInactiveFont(const Value: TFont);
  4091. begin
  4092. FInactiveFont.Assign(Value);
  4093. ResetDockControlOption;
  4094. end;
  4095. procedure TCnVIDTabServerOption.SetInactiveSheetColor(const Value: TColor);
  4096. begin
  4097. if FInactiveSheetColor <> Value then
  4098. begin
  4099. FInactiveSheetColor := Value;
  4100. ResetDockControlOption;
  4101. end;
  4102. end;
  4103. procedure TCnVIDTabServerOption.SetShowTabImages(const Value: Boolean);
  4104. begin
  4105. if FShowTabImages <> Value then
  4106. begin
  4107. FShowTabImages := Value;
  4108. ResetDockControlOption;
  4109. end;
  4110. end;
  4111. procedure TCnVIDTabServerOption.SetTabPosition(const Value: TTabPosition);
  4112. begin
  4113. if Value = tpBottom then
  4114. inherited SetTabPosition(Value)
  4115. else
  4116. raise Exception.Create(gs_TabPositionMustBetpBottom);
  4117. end;
  4118. { TCnVIDConjoinServerOption }
  4119. procedure TCnVIDConjoinServerOption.Assign(Source: TPersistent);
  4120. begin
  4121. if Source is TCnVIDConjoinServerOption then
  4122. begin
  4123. FTextEllipsis := TCnVIDConjoinServerOption(Source).FTextEllipsis;
  4124. FTextAlignment := TCnVIDConjoinServerOption(Source).FTextAlignment;
  4125. FInactiveTitleEndColor := TCnVIDConjoinServerOption(Source).FInactiveTitleEndColor;
  4126. FInactiveTitleStartColor := TCnVIDConjoinServerOption(Source).FInactiveTitleStartColor;
  4127. FActiveTitleEndColor := TCnVIDConjoinServerOption(Source).FActiveTitleEndColor;
  4128. FActiveTitleStartColor := TCnVIDConjoinServerOption(Source).FActiveTitleStartColor;
  4129. FActiveFont.Assign(TCnVIDConjoinServerOption(Source).FActiveFont);
  4130. FInactiveFont.Assign(TCnVIDConjoinServerOption(Source).FInactiveFont);
  4131. FSystemInfo := TCnVIDConjoinServerOption(Source).FSystemInfo;
  4132. end;
  4133. inherited Assign(Source);
  4134. end;
  4135. constructor TCnVIDConjoinServerOption.Create(
  4136. ADockStyle: TCnBasicDockStyle);
  4137. begin
  4138. inherited Create(ADockStyle);
  4139. GrabbersSize := 18;
  4140. FActiveFont := TFont.Create;
  4141. FInactiveFont := TFont.Create;
  4142. SystemInfo := True;
  4143. end;
  4144. destructor TCnVIDConjoinServerOption.Destroy;
  4145. begin
  4146. FActiveFont.Free;
  4147. FInactiveFont.Free;
  4148. inherited;
  4149. end;
  4150. procedure TCnVIDConjoinServerOption.SetActiveTitleEndColor(
  4151. const Value: TColor);
  4152. begin
  4153. if FActiveTitleEndColor <> Value then
  4154. begin
  4155. FActiveTitleEndColor := Value;
  4156. FSystemInfo := False;
  4157. ResetDockControlOption;
  4158. end;
  4159. end;
  4160. procedure TCnVIDConjoinServerOption.SetActiveTitleStartColor(
  4161. const Value: TColor);
  4162. begin
  4163. if FActiveTitleStartColor <> Value then
  4164. begin
  4165. FActiveTitleStartColor := Value;
  4166. FSystemInfo := False;
  4167. ResetDockControlOption;
  4168. end;
  4169. end;
  4170. procedure TCnVIDConjoinServerOption.SetInactiveTitleEndColor(
  4171. const Value: TColor);
  4172. begin
  4173. if FInactiveTitleEndColor <> Value then
  4174. begin
  4175. FInactiveTitleEndColor := Value;
  4176. FSystemInfo := False;
  4177. ResetDockControlOption;
  4178. end;
  4179. end;
  4180. procedure TCnVIDConjoinServerOption.SetInactiveTitleStartColor(
  4181. const Value: TColor);
  4182. begin
  4183. if FInactiveTitleStartColor <> Value then
  4184. begin
  4185. FInactiveTitleStartColor := Value;
  4186. FSystemInfo := False;
  4187. ResetDockControlOption;
  4188. end;
  4189. end;
  4190. procedure TCnVIDConjoinServerOption.SetSystemInfo(const Value: Boolean);
  4191. begin
  4192. if FSystemInfo <> Value then
  4193. begin
  4194. FSystemInfo := Value;
  4195. if FSystemInfo then
  4196. SetDefaultSystemCaptionInfo;
  4197. ResetDockControlOption;
  4198. end;
  4199. end;
  4200. procedure TCnVIDConjoinServerOption.SetTextAlignment(
  4201. const Value: TAlignment);
  4202. begin
  4203. if FTextAlignment <> Value then
  4204. begin
  4205. FTextAlignment := Value;
  4206. FSystemInfo := False;
  4207. ResetDockControlOption;
  4208. end;
  4209. end;
  4210. procedure TCnVIDConjoinServerOption.SetTextEllipsis(const Value: Boolean);
  4211. begin
  4212. if FTextEllipsis <> Value then
  4213. begin
  4214. FTextEllipsis := Value;
  4215. FSystemInfo := False;
  4216. ResetDockControlOption;
  4217. end;
  4218. end;
  4219. procedure TCnVIDConjoinServerOption.SetDefaultSystemCaptionInfo;
  4220. begin
  4221. FActiveTitleStartColor := Cn_GetActiveTitleBeginColor;
  4222. FActiveTitleEndColor := Cn_GetActiveTitleEndColor;
  4223. FInactiveTitleStartColor := Cn_GetInactiveTitleBeginColor;
  4224. FInactiveTitleEndColor := Cn_GetInactiveTitleEndColor;
  4225. FTextAlignment := taLeftJustify;
  4226. FTextEllipsis := True;
  4227. FActiveFont.Assign(Cn_GetTitleFont);
  4228. FActiveFont.Style := FActiveFont.Style + [fsBold];
  4229. FInactiveFont.Assign(FActiveFont);
  4230. FActiveFont.Color := Cn_GetActiveTitleFontColor;
  4231. FInactiveFont.Color := Cn_GetInactiveTitleFontColor;
  4232. GrabbersSize := VIDDefaultGrabbersSize;
  4233. SplitterWidth := VIDDefaultSplitterWidth;
  4234. end;
  4235. procedure TCnVIDConjoinServerOption.SetActiveFont(const Value: TFont);
  4236. begin
  4237. FActiveFont.Assign(Value);
  4238. FSystemInfo := False;
  4239. ResetDockControlOption;
  4240. end;
  4241. procedure TCnVIDConjoinServerOption.SetInactiveFont(const Value: TFont);
  4242. begin
  4243. FInactiveFont.Assign(Value);
  4244. FSystemInfo := False;
  4245. ResetDockControlOption;
  4246. end;
  4247. procedure TCnVIDConjoinServerOption.ResetDockControlOption;
  4248. begin
  4249. inherited ResetDockControlOption;
  4250. FSystemInfo := FSystemInfo and (GrabbersSize = VIDDefaultGrabbersSize)
  4251. and (SplitterWidth = VIDDefaultSplitterWidth);
  4252. TCnVIDDockStyle(DockStyle).DoSystemInfoChange(FSystemInfo);
  4253. end;
  4254. procedure TCnVIDConjoinServerOption.SetActiveFont_WithoutChangeSystemInfo(
  4255. const Value: TFont);
  4256. begin
  4257. FActiveFont.Assign(Value);
  4258. end;
  4259. procedure TCnVIDConjoinServerOption.SetActiveTitleEndColor_WithoutChangeSystemInfo(
  4260. const Value: TColor);
  4261. begin
  4262. FActiveTitleEndColor := Value;
  4263. end;
  4264. procedure TCnVIDConjoinServerOption.SetActiveTitleStartColor_WithoutChangeSystemInfo(
  4265. const Value: TColor);
  4266. begin
  4267. FActiveTitleStartColor := Value;
  4268. end;
  4269. procedure TCnVIDConjoinServerOption.SetInactiveFont_WithoutChangeSystemInfo(
  4270. const Value: TFont);
  4271. begin
  4272. FInactiveFont.Assign(Value);
  4273. end;
  4274. procedure TCnVIDConjoinServerOption.SetInactiveTitleEndColor_WithoutChangeSystemInfo(
  4275. const Value: TColor);
  4276. begin
  4277. FInactiveTitleEndColor := Value;
  4278. end;
  4279. procedure TCnVIDConjoinServerOption.SetInactiveTitleStartColor_WithoutChangeSystemInfo(
  4280. const Value: TColor);
  4281. begin
  4282. FInactiveTitleStartColor := Value;
  4283. end;
  4284. procedure TCnVIDConjoinServerOption.SetTextAlignment_WithoutChangeSystemInfo(
  4285. const Value: TAlignment);
  4286. begin
  4287. FTextAlignment := Value;
  4288. end;
  4289. procedure TCnVIDConjoinServerOption.SetTextEllipsis_WithoutChangeSystemInfo(
  4290. const Value: Boolean);
  4291. begin
  4292. FTextEllipsis := Value;
  4293. end;
  4294. end.