CnDockFormControl.pas 182 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. {*******************************************************}
  21. { }
  22. { 停靠服务和客户控件 }
  23. { CnDockFormControl 单元 }
  24. { }
  25. { 版权 (C) 2002,2003 鲁小班 }
  26. { }
  27. {*******************************************************}
  28. unit CnDockFormControl;
  29. {* |<PRE>
  30. ================================================================================
  31. * 软件名称:不可视工具组件包停靠单元
  32. * 单元名称:停靠服务和客户控件单元
  33. * 单元作者:CnPack开发组 周益波(鲁小班)
  34. * 备 注:本单元由原作者授权CnPack开发组移植,已保留原作者版权信息
  35. * 开发平台:
  36. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
  37. * 本 地 化:该单元中的字符串均符合本地化处理方式
  38. * 单元标识:$Id$
  39. * 修改记录:2007.07.13 V1.0
  40. * 移植单元
  41. ================================================================================
  42. |</PRE>}
  43. {------------------------------------------------------------------------------+
  44. CnDockFormControl -- 版本 0.00
  45. 作者: 周益波
  46. E-mail: zhouyibo2000@sina.com
  47. QQ: 51571811
  48. 开始时间 -- 2002-01-14
  49. 结束时间 -- 2002-01-20
  50. 主要功能:
  51. 使窗体具有停靠功能,并且管理停靠窗体。
  52. 如何使用:
  53. 在您的主窗体上放一个TCnDockServer,在一般的工具窗体上放一个TCnDockClient
  54. 控件,这样,工具窗体就可以停靠到主窗体上了,可以停靠到主窗体的上下左右
  55. 四个方向上。同时,两个工具窗体还有相互停靠的功能,它们可以停靠成平铺型和
  56. 分页型的窗体。
  57. CnDockFormControl单元还提供了一些函数和过程来操作停靠窗体,它们的定义见下面的
  58. 注释。
  59. 在下面的代码中,还定义了两个类的引用,这样,用户就可以用自定义的类替换掉原先
  60. 的类,改变她们的默认特性。
  61. BUG--
  62. 1.在进行停靠操作时,停靠窗体的第一个Windows标准控件里面的内容有可能被清空,
  63. 2.停靠窗体的Caption有可能被清空。
  64. +------------------------------------------------------------------------------}
  65. {------------------------------------------------------------------------------+
  66. CnDockFormControl -- 版本 0.01
  67. 结束时间 -- 2002-02-09
  68. 增加了保存停靠信息和还原停靠信息的功能,
  69. 用户不但可以把停靠信息存储在INI文件中,还可以保存在注册表中。
  70. 因为在还原停靠信息的时候把桌面锁住了,所以不会产生闪烁现象。
  71. 增加了对停靠选项的处理函数
  72. +------------------------------------------------------------------------------}
  73. {------------------------------------------------------------------------------+
  74. CnDockFormControl -- 版本 0.02
  75. 结束时间 -- 2002-02-20
  76. 增加了辅助控件TCnBasicDockStyle,用来改变停靠的风格,如:
  77. 停靠的预览效果,停靠后把手的外观等。
  78. 而且用户可以继承TCnBasicDockStyle,用来自定义外观,提供最大的灵活性
  79. 用户可以分别继承TCnDockSplitter,TCnDockPanel,TCnConjoinPanel,
  80. TCnTabPageControl,TCnDockZone和TCnDockTree类来改变停靠风格。
  81. 目前增加的停靠风格类是CnDelphiDockStyle和CnVCDockStyle,
  82. 她们分别表示类似Delphi和类似VC++的风格。
  83. +------------------------------------------------------------------------------}
  84. {------------------------------------------------------------------------------+
  85. CnDockFormControl -- 版本 0.03
  86. 结束时间 -- 2002-03-10
  87. 修正了0.00版中的两个BUG,程序运行的更加稳定、可靠了。
  88. 增加了TCnVIDDockStyle类,她是模仿Visual InderDev的停靠的风格,还没有完全完成,
  89. +------------------------------------------------------------------------------}
  90. {------------------------------------------------------------------------------+
  91. CnDockFormControl -- 版本 0.031
  92. 结束时间 -- 2002-03-17
  93. 完成了一个很有难度的功能,就是当停靠控件是TCnConjoinDockHostForm的时候,
  94. 就把它上面的TCnConjoinPanel的停靠信息保存起来,然后再把它还原到DropOnControl中。
  95. +------------------------------------------------------------------------------}
  96. {------------------------------------------------------------------------------+
  97. CnDockFormControl -- 版本 0.04
  98. 结束时间 -- 2002-04-17
  99. 对程序的底层代码进行了大幅度的修改,现在,这套控件已经不再受Delphi的VCL类库的
  100. 限制了,我们完全可以根据自己的意愿来设置停靠的风格了。
  101. 其中增加了TCnDockPresident类,这个类用于当鼠标拖动控件的时候处理停靠事件。
  102. 又增加了TCnCustomDockControl类,这个类从TCustomControl继承过来,在她里面定义
  103. 了一些和停靠相关的函数和方法。后面的TCnDockPanel, TCnConjoinPanel和
  104. TCnTabPageControl都从TCnCustomDockControl继承。这样,只要把她们三个类中相同的
  105. 代码都放在TCnCustomDockControl中,就起到了代码重用的作用;还有,当检测这个类
  106. 的级别的时候也很方便。由于代码大幅度的修改,暂时停靠风格类还不能完全使用,
  107. 不过应该马上可以修改好的。关于停靠风格,以后还要增加:
  108. TCnWPSDockStyle(类似WPS的停靠风格),
  109. TCnPhotoShopDockStyle(类似PhotoShop的停靠风格),
  110. TCnTancentDockStyle(类似腾讯浏览器的停靠风格),
  111. TCnOfficeDockStyle(类似Office XP的停靠风格),
  112. TCnNETDockStyle(类似.NET的停靠风格),
  113. TCnVBDockStyle(类似Visual Basic的停靠风格),
  114. TCnCustomDockStyle(自定义的停靠风格)。
  115. ...
  116. +------------------------------------------------------------------------------}
  117. {------------------------------------------------------------------------------+
  118. CnDockFormControl -- 版本 0.041
  119. 结束时间 -- 2002-04-24
  120. 增加了一些TCnDockClient中的属性,如:
  121. DirectDrag(当鼠标点击标题栏的时候是否立刻进行停靠操作),
  122. NCPopupMenu(当鼠标右键点击标题栏的时候是否产生弹出菜单),
  123. ShowHint(当鼠标移动到标题栏上的时候是否显示提示信息)。
  124. 又增加了一些TCnDockClient的事件,如:
  125. OnFormShowHint(当提示信息显示的时候触发)
  126. OnNCButtonDown(当鼠标在标题栏上按下的时候触发)
  127. OnNCButtonUp(当鼠标在标题栏上释放的时候触发)
  128. OnNCMouseMove(当鼠标在标题栏上移动的时候触发)
  129. OnNCButtonDblClk(当鼠标在标题栏上双击的时候触发)
  130. OnPaintDockGrabber(当重画把手的时候触发)
  131. OnPaintDockSplitter(当重画分割条的时候触发)
  132. 对TCnVCDockStyle类进行了一些改进,使它看上去更象VC的停靠风格,不过有些地方
  133. 还有待改进,这只是时间问题。
  134. 现在这套控件看上去功能越来越强大了,嘻嘻,不过我还不急着发布她,希望把她做地完美
  135. 无缺后再发布。
  136. +------------------------------------------------------------------------------}
  137. {------------------------------------------------------------------------------+
  138. CnDockFormControl -- 版本 0.041
  139. 结束时间 -- 2002-05-10
  140. 对TCnVCDockStyle类进行了进一步的改进,现在她的特性已经很类似于VC++的停靠风格了。
  141. +------------------------------------------------------------------------------}
  142. {------------------------------------------------------------------------------+
  143. CnDockFormControl -- 版本 0.042
  144. 结束时间 -- 2002-05-24
  145. 做了一个类似Visual C++界面的程序,用来演示TCnVCDockStyle控件,做的很酷哦.
  146. +------------------------------------------------------------------------------}
  147. {------------------------------------------------------------------------------+
  148. CnDockFormControl -- 版本 0.050
  149. 结束时间 -- 2002-06-13
  150. 初步完成了Visual InterDev中的停靠分页的界面。而且有一个副产物TCnVIDTabPageControl
  151. 控件,可以作为一般的分页控件来使用。
  152. +------------------------------------------------------------------------------}
  153. {------------------------------------------------------------------------------+
  154. CnDockFormControl -- 版本 0.051
  155. 结束时间 -- 2002-07-03
  156. 基本上完成了Visual InterDev中的停靠分页的界面。
  157. +------------------------------------------------------------------------------}
  158. {------------------------------------------------------------------------------+
  159. CnDockFormControl -- 版本 0.060
  160. 结束时间 -- 2002-08-11
  161. 已经完成Visual InterDev中的停靠分页的界面,在TCnBasicDockStyle类中增加了两个
  162. 属性:TCnBasicConjoinServerOption和TCnBasicTabServerOption,用户可以继承这
  163. 两个类来实现自己的停靠风格的属性。
  164. 并且制作了一个帮助文件,接下去就开始测试了,准备在十月份发布这套控件。
  165. +------------------------------------------------------------------------------}
  166. {------------------------------------------------------------------------------+
  167. CnDockFormControl -- 版本 0.065
  168. 结束时间 -- 2002-08-20
  169. 找到了一些BUG,并且已经改正,继续测试,可靠性是软件的根本。
  170. +------------------------------------------------------------------------------}
  171. {------------------------------------------------------------------------------+
  172. CnDockFormControl -- 版本 0.070
  173. 结束时间 -- 2002-09-14
  174. 增加了一个很重要的功能,就是当用户关闭一个已经停靠了的窗体后,可以把这个窗体
  175. 在停靠服务器中的原来的位置保存下来,用户再次显示它的时候,可以还原到原来的位置
  176. 和大小,这个功能在Visual C++和Visual InterDev中都有,可是在Delphi中没有,
  177. 现在我把这个功能也加到CnDelphiDockStyle中了。
  178. +------------------------------------------------------------------------------}
  179. {------------------------------------------------------------------------------+
  180. CnDockFormControl -- 版本 0.100
  181. 结束时间 -- 2002-11-20
  182. 程序的试用版已经发布了,反响还不错,用户发现了一些Bug,现在已经修改了。
  183. 后来又增加了一个类似Visual InterDev的Demo,本来想增加一个双击标题栏还原的
  184. 功能,结果改啊改,但是最后发现改不下去了,为什么?说出来丢脸,由于刚开始做
  185. 这个控件的时候没有想到会做成象现在功能这么强大,程序结构没有设计好,到后来
  186. 发觉再改下去的话,程序就会发展到不可控制的混乱程度。最后,只能忍痛割爱,暂时
  187. 把双击还原的功能去掉,然后初步决定等到做完了类似VS.NET的停靠风格后就发布正式
  188. 版,所以这几天正忙着做类似VS.NET的停靠风格TCnVSNETDockStyle呢。大概能到12月中
  189. 能做完,然后还要测试,恐怕只能等到2003年1月份才能发布了。
  190. 等正式版发布的时候,我还要把帮助文件翻译成English,让老外也来用我们中国人的
  191. 控件,但是我还不知道是作为免费软件还是共享软件发布,到时候再说吧。
  192. 本人初步打算把DockPresident移植到C#上面,不过不知道能在什么时候开始,因为我
  193. 对C#也是一知半解,前一阵子学了一下,现在又放下了,唉,没时间啊。
  194. +------------------------------------------------------------------------------}
  195. {------------------------------------------------------------------------------+
  196. CnDockFormControl -- 版本 0.0110
  197. 结束时间 -- 2002-12-14
  198. 初步完成了类似VS.NET停靠风格的类TCnVSNETDockStyle,功能基本上和VS.NET停靠风格
  199. 差不多,不过由于Delphi的特殊性,有些地方没有办法和VS.NET停靠风格完全一样,如果
  200. 读者想了解VS.NET的停靠风格,请参看《VS.NET的停靠风格》。
  201. +------------------------------------------------------------------------------}
  202. {------------------------------------------------------------------------------+
  203. CnDockFormControl -- 版本 0.0112
  204. 结束时间 -- 2002-12-20
  205. 做了一个类似MSDN2002停靠风格的Demo,效果还不错,呵呵。
  206. +------------------------------------------------------------------------------}
  207. {------------------------------------------------------------------------------+
  208. CnDockFormControl -- 版本 0.0120
  209. 结束时间 -- 2003-1-4
  210. 新版本的控件已经基本上完成,现在进入测试阶段,预计春节后发布。接下去的时间主要
  211. 是作测试,并且修改一些细节的东东,完善帮助,补全文档等等。
  212. 程序的代码量已经突破25000行,如果去掉注释部分应该也有20000多行,也算是中等规模
  213. 的控件了,呵呵,足足花了我一年的业余时间,中途也曾经打过退堂鼓,但还是咬牙坚持
  214. 了下来,不管这个控件以后的命运会怎么样,能够完成她其实已经是一种胜利了,呵呵。
  215. 接下去的任务就是要把她养大,花点时间来推广她,如果哪位朋友觉得Dock President
  216. 还不错,就请向您的朋友推荐一下,在这里鲁小班先向您表示感谢了。
  217. +------------------------------------------------------------------------------}
  218. {------------------------------------------------------------------------------+
  219. CnDockFormControl -- 版本 0.0121
  220. 结束时间 -- 2003-2-16
  221. 改正了一个问题,那就是在WinXP下面装载停靠信息的时候,屏幕会闪烁,其实这个
  222. 问题在98或者2000以下是没有的,因为程序已经调用了LockWindowUpdate函数,
  223. 但是在XP下面不知道是什么原因,还是会出现这种闪烁的情况,后来没办法,只能在
  224. 装载的时候过滤掉CM_SHOWINGCHANGED消息,然后在装载的最后把应该显示但是没有
  225. 显示的客户窗体显示出来。
  226. +------------------------------------------------------------------------------}
  227. {$P+,S-,W-,R-,T-,H+,X+}
  228. interface
  229. {$I CnPack.inc}
  230. uses
  231. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Menus,
  232. Extctrls, Comctrls, Stdctrls, Consts, Inifiles, CommCtrl, Registry, CnDockTree,
  233. CnDockSupportClass, CnDockSupportControl, CnClasses, CnConsts, CnCompConsts;
  234. const
  235. { 停靠的状态 }
  236. DS_Unknow = 0; // 不知道是什么状态
  237. DS_Docking = 1; // 停靠状态
  238. DS_Floating = 2; // 浮动状态
  239. type
  240. TCnSplitterSize = 0..32767;
  241. TCnDockBaseControl = class;
  242. TCnDockServer = class;
  243. TCnDockClient = class;
  244. TCnConjoinPanel = class;
  245. TCnTabPageControl = class;
  246. TCnConjoinDockHostForm = class;
  247. TCnTabDockHostForm = class;
  248. { 用来在停靠服务端中调整客户端的分割条 }
  249. TCnDockSplitter = class({TSplitter)//}TCustomDockPanelSplitter)
  250. private
  251. { 表示被哪个TDockServer拥有 }
  252. FDockServer: TCnDockServer;
  253. function GetSplitterIndex: Integer;
  254. protected
  255. function FindControl: TControl; override;
  256. property DockServer: TCnDockServer read FDockServer write FDockServer;
  257. public
  258. constructor Create(AOwner: TComponent); override;
  259. property SplitterIndex: Integer read GetSplitterIndex;
  260. end;
  261. // 当调用ShowDockPanel函数设置DockPanel的宽度或者高度的时候,
  262. // 用来指定到底是按照DockPanel本身的TBDockHeight和LRDockWidth
  263. // 还是按照Client的TBDockHeight和LRDockWidth来设置。
  264. TSetDockPanelSizeFrom = (sdfDockPanel, sdfClient);
  265. { 停靠服务端中用来停靠客户端的Panel }
  266. TCnDockPanel = class(TCnCustomDockPanel)
  267. private
  268. { 表示被哪个TDockServer拥有 }
  269. FDockServer: TCnDockServer;
  270. function GetPanelIndex: Integer;
  271. protected
  272. procedure SetDockServer(const Value: TCnDockServer); virtual;
  273. procedure ReloadDockedControl(const AControlName: string;
  274. var AControl: TControl); override;
  275. { ------------------------------------------------------------------------ }
  276. procedure CustomStartDock(var Source: TCnDragDockObject); override;
  277. procedure CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  278. var CanDock: Boolean); override;
  279. procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer;
  280. State: TDragState; var Accept: Boolean); override;
  281. procedure CustomPositionDockRect(Source: TCnDragDockObject; X, Y: Integer); override;
  282. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  283. procedure CustomEndDock(Target: TObject; X, Y: Integer); override;
  284. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  285. { ------------------------------------------------------------------------ }
  286. function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
  287. { ------------------------------------------------------------------------ }
  288. procedure Resize; override;
  289. public
  290. constructor Create(AOwner: TComponent); override;
  291. destructor Destroy; override;
  292. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  293. { 显示停靠的窗体 }
  294. procedure ShowDockPanel(MakeVisible: Boolean; Client: TControl;
  295. PanelSizeFrom: TSetDockPanelSizeFrom = sdfClient); virtual;
  296. procedure ResetPosition;
  297. property PanelIndex: Integer read GetPanelIndex;
  298. property DockServer: TCnDockServer read FDockServer write SetDockServer;
  299. end;
  300. TCnAdvDockPanel = class(TCnDockPanel)
  301. private
  302. procedure CMUnDockClient(var Message: TCMUnDockClient); message CM_UNDOCKCLIENT;
  303. protected
  304. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  305. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  306. { ------------------------------------------------------------------------ }
  307. function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
  308. public
  309. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  310. end;
  311. TCnDockPanelClass = class of TCnDockPanel;
  312. TCnDockSplitterClass = class of TCnDockSplitter;
  313. TCnConjoinPanelClass = class of TCnConjoinPanel;
  314. TCnTabDockClass = class of TCnTabPageControl;
  315. { 分割条的风格 }
  316. TCnSplitterStyle = class(TPersistent)
  317. private
  318. FSplitter: TCnDockSplitter;
  319. FDockServer: TCnDockServer;
  320. FColor: TColor;
  321. FCursor: TCursor;
  322. FParentColor: Boolean;
  323. FResizeStyle: TResizeStyle;
  324. FSize: TCnSplitterSize; // 大小,当是[左,右]时就是宽度,当是[上,下]时就是高度。
  325. FMinSize: TCnSplitterSize; // 距离父控件最小的位置
  326. procedure SetColor(const Value: TColor);
  327. procedure SetCursor(const Value: TCursor);
  328. procedure SetParentColor(const Value: Boolean);
  329. procedure SetResizeStyle(const Value: TResizeStyle);
  330. procedure SetSize(const Value: TCnSplitterSize);
  331. procedure SetMinSize(const Value: TCnSplitterSize);
  332. protected
  333. procedure AssignTo(Dest: TPersistent); override;
  334. procedure AssignToSplitter(Dest: TCnDockSplitter);
  335. procedure SetSplitterStyle;
  336. property Splitter: TCnDockSplitter read FSplitter write FSplitter;
  337. public
  338. constructor Create(ASplitter: TCnDockSplitter; ACursor: TCursor); virtual;
  339. procedure Assign(Source: TPersistent); override;
  340. published
  341. property Color: TColor read FColor write SetColor default clBtnFace;
  342. property Cursor: TCursor read FCursor write SetCursor;
  343. property ParentColor: Boolean read FParentColor write SetParentColor default True;
  344. property ResizeStyle: TResizeStyle read FResizeStyle write SetResizeStyle
  345. default rsPattern;
  346. property Size: TCnSplitterSize read FSize write SetSize default 3;
  347. property MinSize: TCnSplitterSize read FMinSize write SetMinSize default 30;
  348. end;
  349. TCnBasicDockStyle = class;
  350. { TCnBasicConjoinServerOption和TCnBasicTabServerOption共同的父类 }
  351. TCnBasicServerOption = class(TPersistent)
  352. private
  353. FDockStyle: TCnBasicDockStyle;
  354. protected
  355. { 重新设置和DockStyle有联系的TCnDockBaseControl的配置 }
  356. procedure ResetDockControlOption; virtual; abstract;
  357. { 重新设置ADockServer的配置 }
  358. procedure ResetDockServerOption(ADockServer: TCnDockServer); virtual;// abstract;
  359. { 重新设置ADockClient的配置 }
  360. procedure ResetDockClientOption(ADockClient: TCnDockClient); virtual;// abstract;
  361. property DockStyle: TCnBasicDockStyle read FDockStyle write FDockStyle;
  362. public
  363. constructor Create(ADockStyle: TCnBasicDockStyle); virtual;
  364. destructor Destroy; override;
  365. procedure Assign(Source: TPersistent); override;
  366. end;
  367. TGrabbersSize = 1..MaxInt;
  368. TSplitterWidth = 1..MaxInt;
  369. { 平铺服务器的选项类 }
  370. TCnBasicConjoinServerOption = class(TCnBasicServerOption)
  371. private
  372. FGrabbersSize: TGrabbersSize;
  373. FSplitterWidth: TSplitterWidth;
  374. protected
  375. procedure SetGrabbersSize(const Value: TGrabbersSize); virtual;
  376. procedure SetSplitterWidth(const Value: TSplitterWidth); virtual;
  377. { ------------------------------------------------------------------------ }
  378. procedure ResetDockControlOption; override;
  379. procedure ResetDockServerOption(ADockServer: TCnDockServer); override;
  380. procedure ResetDockClientOption(ADockClient: TCnDockClient); override;
  381. { 重新设置TCnDockPanel的属性 }
  382. procedure ResetDockPanel(APanel: TCnDockPanel); virtual;
  383. { 重新设置TCnConjoinPanel的属性 }
  384. procedure ResetConjoinPanel(APanel: TCnConjoinPanel); virtual;
  385. public
  386. constructor Create(ADockStyle: TCnBasicDockStyle); override;
  387. destructor Destroy; override;
  388. procedure Assign(Source: TPersistent); override;
  389. procedure SetGrabbersSize_WithoutChangeSystemInfo(const Value: TGrabbersSize);
  390. procedure SetSplitterWidth_WithoutChangeSystemInfo(const Value: TSplitterWidth);
  391. published
  392. property GrabbersSize: TGrabbersSize read FGrabbersSize write SetGrabbersSize;
  393. property SplitterWidth: TSplitterWidth read FSplitterWidth write SetSplitterWidth;
  394. end;
  395. { 分页服务器的选项类 }
  396. TCnBasicTabServerOption = class(TCnBasicServerOption)
  397. private
  398. FTabPosition: TTabPosition;
  399. FHotTrack: Boolean;
  400. protected
  401. procedure SetTabPosition(const Value: TTabPosition); virtual;
  402. procedure SetHotTrack(const Value: Boolean); virtual;
  403. { ------------------------------------------------------------------------ }
  404. procedure ResetDockControlOption; override;
  405. procedure ResetDockServerOption(ADockServer: TCnDockServer); override;
  406. procedure ResetDockClientOption(ADockClient: TCnDockClient); override;
  407. { 重新设置TCnTabPageControl的属性 }
  408. procedure ResetTabPageControl(APage: TCnTabPageControl); virtual;
  409. public
  410. constructor Create(ADockStyle: TCnBasicDockStyle); override;
  411. destructor Destroy; override;
  412. procedure Assign(Source: TPersistent); override;
  413. published
  414. property HotTrack: Boolean read FHotTrack write SetHotTrack default False;
  415. property TabPosition: TTabPosition read FTabPosition write SetTabPosition
  416. default tpTop;
  417. end;
  418. TCnBasicConjoinServerOptionClass = class of TCnBasicConjoinServerOption;
  419. TCnBasicTabServerOptionClass = class of TCnBasicTabServerOption;
  420. { 所有停靠风格的基类 }
  421. TCnBasicDockStyle = class(TCnComponent)
  422. private
  423. FCnDockPanelClass: TCnDockPanelClass; // TCnDockServer中四个TCnDockPanel的类的引用
  424. FCnDockSplitterClass: TCnDockSplitterClass;// TCnDockServer中四个TSplitter的类的引用
  425. FCnConjoinPanelClass: TCnConjoinPanelClass;// 平铺服务器的类的引用
  426. FCnTabDockClass: TCnTabDockClass; // 分页服务器的类的引用
  427. FCnDockPanelTreeClass: TCnDockTreeClass; // TCnDockPanel中IDockManager的类的引用
  428. FCnDockPanelZoneClass: TCnDockZoneClass; // TCnDockPanel中IDockManager的节点类的引用
  429. FCnConjoinPanelTreeClass: TCnDockTreeClass;// TCnConjoinPanel中IDockManager的类的引用
  430. FCnConjoinPanelZoneClass: TCnDockZoneClass;
  431. FCnConjoinServerOptionClass: TCnBasicConjoinServerOptionClass;
  432. FCnTabServerOptionClass: TCnBasicTabServerOptionClass;
  433. FCnConjoinServerOption: TCnBasicConjoinServerOption;
  434. FCnTabServerOption: TCnBasicTabServerOption;
  435. FParentForm: TForm; // 父窗体
  436. FOldWindowProc: TWndMethod;
  437. { 一个列表,用来存储所有引用了TCnBasicDockStyle对象的TCnDockBaseControl对象 }
  438. FDockBaseControlList: TList;
  439. function GetDockBaseControlListCount: Integer;
  440. function GetDockBaseControlLists(Index: Integer): TCnDockBaseControl;
  441. protected
  442. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  443. procedure FormStartDock(DockClient: TCnDockClient; var Source: TCnDragDockObject); virtual;
  444. procedure FormGetSiteInfo(Source: TCnDragDockObject; DockClient: TCnDockClient; Client: TControl;
  445. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean); virtual;
  446. procedure FormDockOver(DockClient: TCnDockClient; Source: TCnDragDockObject; X, Y: Integer;
  447. State: TDragState; var Accept: Boolean); virtual;
  448. procedure FormPositionDockRect(DockClient: TCnDockClient; Source: TCnDragDockObject); virtual;
  449. procedure FormDockDrop(DockClient: TCnDockClient; Source: TCnDragDockObject; X, Y: Integer); virtual;
  450. procedure FormEndDock(DockClient: TCnDockClient; Target: TObject; X, Y: Integer); virtual;
  451. function FormUnDock(DockClient: TCnDockClient; NewTarget: TWinControl; Client: TControl): Boolean; virtual;
  452. procedure FormGetDockEdge(DockClient: TCnDockClient; Source: TCnDragDockObject;
  453. MousePos: TPoint; var DropAlign: TAlign); virtual;
  454. { ------------------------------------------------------------------------ }
  455. { 创建平铺停靠分割的选项类 }
  456. procedure CreateConjoinServerOption(var Option: TCnBasicConjoinServerOption); virtual;
  457. { 创建分页停靠分割的选项类 }
  458. procedure CreateTabServerOption(var Option: TCnBasicTabServerOption); virtual;
  459. { 创建平铺和分页停靠分割的选项类 }
  460. procedure CreateServerOption; virtual;
  461. { 释放平铺和分页停靠分割的选项类 }
  462. procedure FreeServerOption; virtual;
  463. { ------------------------------------------------------------------------ }
  464. procedure SetDockBaseControl(IsCreate: Boolean;
  465. DockBaseControl: TCnDockBaseControl); virtual;
  466. { 捕获TCnDockServer的WindowProc消息,如果要还要执行默认的消息处理就返回False,否则就返回True }
  467. function DockServerWindowProc(DockServer: TCnDockServer; var Message: TMessage): Boolean; virtual;
  468. { 捕获TCnDockClient的WindowProc消息,如果要还要执行默认的消息处理就返回False,否则就返回True }
  469. function DockClientWindowProc(DockClient: TCnDockClient; var Message: TMessage): Boolean; virtual;
  470. { 捕获父控件的WindowProc消息 }
  471. procedure ParentFormWindowProc(var Message: TMessage); virtual;
  472. { 把ADockBaseControl添加到FDockBaseControlList中,
  473. 如果已经存在了就不插入,反之插入到列表的结尾处 }
  474. procedure AddDockBaseControl(ADockBaseControl: TCnDockBaseControl); virtual;
  475. { 把ADockBaseControl从FDockBaseControlList中删除,
  476. 如果不存在了就不删除,反之删除 }
  477. procedure RemoveDockBaseControl(ADockBaseControl: TCnDockBaseControl); virtual;
  478. { ------------------------------------------------------------------------ }
  479. procedure SetConjoinServerOption(
  480. const Value: TCnBasicConjoinServerOption); virtual;
  481. procedure SetTabServerOption(const Value: TCnBasicTabServerOption); virtual;
  482. function GetConjoinServerOption: TCnBasicConjoinServerOption; virtual;
  483. function GetTabServerOption: TCnBasicTabServerOption; virtual;
  484. { 给当前的APanel的平铺的风格赋值,子类可以重载这个方法添加新的属性 }
  485. procedure AssignConjoinServerOption(APanel: TCnCustomDockPanel); virtual;
  486. { 给当前的APage的分页的风格赋值,子类可以重载这个方法添加新的属性 }
  487. procedure AssignTabServerOption(APage: TCnTabPageControl); virtual;
  488. procedure Loaded; override;
  489. property DockBaseControlList: TList read FDockBaseControlList;
  490. public
  491. constructor Create(AOwner: TComponent); override;
  492. destructor Destroy; override;
  493. procedure AfterConstruction; override;
  494. function CanSetEnableDocked(ADockBaseControl: TCnDockBaseControl): Boolean; virtual;
  495. function CanSetLeftDocked(ADockBaseControl: TCnDockBaseControl): Boolean; virtual;
  496. function CanSetRightDocked(ADockBaseControl: TCnDockBaseControl): Boolean; virtual;
  497. function CanSetTopDocked(ADockBaseControl: TCnDockBaseControl): Boolean; virtual;
  498. function CanSetBottomDocked(ADockBaseControl: TCnDockBaseControl): Boolean; virtual;
  499. function CanSetEachOtherDocked(ADockBaseControl: TCnDockBaseControl): Boolean; virtual;
  500. function GetControlName: string; virtual;
  501. function GetDockStyleVersion: string; virtual;
  502. { 重新设置光标的形状 }
  503. procedure ResetCursor(Source: TCnDragDockObject); virtual;
  504. { 获得DockClient参数的停靠状态 }
  505. function GetDockState(DockClient: TCnDockClient): Integer; virtual;
  506. procedure ResetDockControlConjoinOption;
  507. procedure ResetDockControlTabOption;
  508. { ------------------------------------------------------------------------ }
  509. procedure ShowDockForm(ADockClient: TCnDockClient); virtual;// 显示ADockClient中的ParentForm;
  510. procedure HideDockForm(ADockClient: TCnDockClient); virtual;// 隐藏ADockClient中的ParentForm;
  511. function GetDockFormVisible(ADockClient: TCnDockClient): Boolean; virtual;// 得到ADockClient中的ParentForm是否可见.
  512. { ------------------------------------------------------------------------ }
  513. property DockBaseControlListCount: Integer read GetDockBaseControlListCount;
  514. property DockBaseControlLists[Index: Integer]: TCnDockBaseControl read GetDockBaseControlLists;
  515. { 还原原先的客户的状态 }
  516. procedure RestoreClient(DockClient: TCnDockClient); virtual;
  517. { ------------------------------------------------------------------------ }
  518. property Version: string read GetDockStyleVersion;// 版本号
  519. property ControlName: string read GetControlName; // 控件名称
  520. { ------------------------------------------------------------------------ }
  521. property CnDockPanelClass: TCnDockPanelClass
  522. read FCnDockPanelClass write FCnDockPanelClass;
  523. property CnDockSplitterClass: TCnDockSplitterClass
  524. read FCnDockSplitterClass write FCnDockSplitterClass;
  525. property CnConjoinPanelClass: TCnConjoinPanelClass
  526. read FCnConjoinPanelClass write FCnConjoinPanelClass;
  527. property CnTabDockClass: TCnTabDockClass
  528. read FCnTabDockClass write FCnTabDockClass;
  529. property CnDockPanelTreeClass: TCnDockTreeClass
  530. read FCnDockPanelTreeClass write FCnDockPanelTreeClass;
  531. property CnDockPanelZoneClass: TCnDockZoneClass
  532. read FCnDockPanelZoneClass write FCnDockPanelZoneClass;
  533. property CnConjoinPanelTreeClass: TCnDockTreeClass
  534. read FCnConjoinPanelTreeClass write FCnConjoinPanelTreeClass;
  535. property CnConjoinPanelZoneClass: TCnDockZoneClass
  536. read FCnConjoinPanelZoneClass write FCnConjoinPanelZoneClass;
  537. { ------------------------------------------------------------------------ }
  538. property CnConjoinServerOptionClass: TCnBasicConjoinServerOptionClass
  539. read FCnConjoinServerOptionClass write FCnConjoinServerOptionClass;
  540. property CnTabServerOptionClass: TCnBasicTabServerOptionClass
  541. read FCnTabServerOptionClass write FCnTabServerOptionClass;
  542. { ------------------------------------------------------------------------ }
  543. property ParentForm: TForm read FParentForm write FParentForm;
  544. { ------------------------------------------------------------------------ }
  545. property ConjoinServerOption: TCnBasicConjoinServerOption
  546. read GetConjoinServerOption write SetConjoinServerOption;
  547. property TabServerOption: TCnBasicTabServerOption
  548. read GetTabServerOption write SetTabServerOption;
  549. end;
  550. TCnAdvDockStyle = class(TCnBasicDockStyle)
  551. protected
  552. function DockClientWindowProc(DockClient: TCnDockClient; var Message: TMessage): Boolean; override;
  553. end;
  554. { 停靠服务端和客户端共同的父类 }
  555. TCnDockBaseControl = class(TCnComponent)
  556. private
  557. FEnableDock, // 是否可以停靠在服务端
  558. FLeftDock, // 是否可以停靠在服务端的左边
  559. FTopDock, // 是否可以停靠在服务端的上边
  560. FRightDock, // 是否可以停靠在服务端的右边
  561. FBottomDock, // 是否可以停靠在服务端的下边
  562. FEachOtherDock: Boolean;// 是否可以相互停靠
  563. FDockStyle: TCnBasicDockStyle;
  564. FOldOnClose: TCloseEvent;
  565. FOldOnCreate: TNotifyEvent;
  566. FParentForm: TForm;
  567. FOldWindowProc: TWndMethod;
  568. protected
  569. procedure Loaded; override;
  570. procedure SetParentComponent(Value: TComponent); override;
  571. { ------------------------------------------------------------------------ }
  572. function CanSetEnableDocked: Boolean; virtual;
  573. function CanSetLeftDocked: Boolean; virtual;
  574. function CanSetRightDocked: Boolean; virtual;
  575. function CanSetTopDocked: Boolean; virtual;
  576. function CanSetBottomDocked: Boolean; virtual;
  577. function CanSetEachOtherDocked: Boolean; virtual;
  578. { ------------------------------------------------------------------------ }
  579. procedure DoFormOnClose(Sender: TObject; var Action: TCloseAction); virtual;
  580. procedure DoFormOnCreate(Sender: TObject); virtual;
  581. { ------------------------------------------------------------------------ }
  582. procedure SetBottomDock(const Value: Boolean); virtual;
  583. procedure SetEachotherDock(const Value: Boolean); virtual;
  584. procedure SetEnableDock(const Value: Boolean); virtual;
  585. procedure SetLeftDock(const Value: Boolean); virtual;
  586. procedure SetRightDock(const Value: Boolean); virtual;
  587. procedure SetTopDock(const Value: Boolean); virtual;
  588. procedure SetDockStyle(const Value: TCnBasicDockStyle); virtual;
  589. { ------------------------------------------------------------------------ }
  590. procedure Notification(AComponent: TComponent;
  591. Operation: TOperation); override;
  592. procedure WindowProc(var Message: TMessage); virtual;
  593. public
  594. constructor Create(AOwner: TComponent); override;
  595. destructor Destroy; override;
  596. procedure Assign(Source: TPersistent); override;
  597. property ParentForm: TForm read FParentForm;
  598. { ------------------------------------------------------------------------ }
  599. // class function GetDockStyleVersion: string; virtual;
  600. function GetDockStyleVersion: string; virtual;
  601. { ------------------------------------------------------------------------ }
  602. property EnableDock: Boolean read FEnableDock write SetEnableDock default True;
  603. property LeftDock: Boolean read FLeftDock write SetLeftDock default True;
  604. property TopDock: Boolean read FTopDock write SetTopDock default True;
  605. property RightDock: Boolean read FRightDock write SetRightDock default True;
  606. property BottomDock: Boolean read FBottomDock write SetBottomDock default True;
  607. property EachOtherDock: Boolean read FEachotherDock write SetEachotherDock default True;
  608. { ------------------------------------------------------------------------ }
  609. property Version: string read GetDockStyleVersion; // 版本号
  610. { ------------------------------------------------------------------------ }
  611. property DockStyle: TCnBasicDockStyle read FDockStyle write SetDockStyle;
  612. end;
  613. TGetClientAlignSizeEvent = procedure(Align: TAlign; var Value: Integer) of object;
  614. TFinishSetDockPanelSizeEvent = procedure(DockPanel: TCnDockPanel) of object;
  615. { 停靠服务端 }
  616. TCnDockServer = class(TCnDockBaseControl)
  617. private
  618. FDockPanelClass: TCnDockPanelClass;
  619. FLeftDockPanel, // 左边的停靠面板
  620. FTopDockPanel, // 上边的停靠面板
  621. FBottomDockPanel, // 下边的停靠面板
  622. FRightDockPanel: TCnDockPanel; // 右边的停靠面板
  623. FDockSplitterClass: TCnDockSplitterClass;
  624. FLeftSplitter, // 左边的分割条
  625. FTopSplitter, // 上边的分割条
  626. FBottomSplitter, // 下边的分割条
  627. FRightSplitter: TCnDockSplitter; // 右边的分割条
  628. FLeftSplitterStyle, // 左边的分割条风格
  629. FTopSplitterStyle, // 上边的分割条风格
  630. FRightSplitterStyle, // 下边的分割条风格
  631. FBottomSplitterStyle: TCnSplitterStyle; // 右边的分割条风格
  632. FOnGetClientAlignSize: TGetClientAlignSizeEvent;
  633. FOnFinishSetDockPanelSize: TFinishSetDockPanelSizeEvent;
  634. procedure CreateDockPanelAndSplitter; // 创建四个停靠面板和分割条
  635. // procedure DestroyDockPanelAndSplitter;// 释放四个停靠面板和分割条
  636. procedure CreateSplitterStyle; // 创建风格条的风格
  637. procedure DestroySplitterStyle; // 释放风格条的风格
  638. { 设置分割条的风格 }
  639. procedure SetSplitterStyle; // 设置风格条的风格
  640. { 设置左边的风格条的风格 }
  641. procedure SetLeftSplitterStyle(const Value: TCnSplitterStyle);
  642. { 设置上边的风格条的风格 }
  643. procedure SetTopSplitterStyle(const Value: TCnSplitterStyle);
  644. { 设置右边的风格条的风格 }
  645. procedure SetRightSplitterStyle(const Value: TCnSplitterStyle);
  646. { 设置下边的风格条的风格 }
  647. procedure SetBottomSplitterStyle(const Value: TCnSplitterStyle);
  648. { 获得索引为Index的TCnDockPanel }
  649. function GetDockPanel(Index: Integer): TCnDockPanel;
  650. { 获得索引为Index的TCnDockSplitter }
  651. function GetDockSplitter(Index: Integer): TCnDockSplitter;
  652. procedure DoGetClientAlignControl(Align: TAlign; var Value: Integer);
  653. function GetDockPanelWithAlign(Index: TAlign): TCnDockPanel;
  654. function GetDockSplitterWithAlign(Index: TAlign): TCnDockSplitter;
  655. protected
  656. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  657. procedure Loaded; override;
  658. { ------------------------------------------------------------------------ }
  659. procedure DoFinishSetDockPanelSize(DockPanel: TCnDockPanel);
  660. procedure DoFloatDockClients(DockPanel: TCnDockPanel);
  661. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  662. procedure SetBottomDock(const Value: Boolean); override;
  663. procedure SetEnableDock(const Value: Boolean); override;
  664. procedure SetLeftDock(const Value: Boolean); override;
  665. procedure SetRightDock(const Value: Boolean); override;
  666. procedure SetTopDock(const Value: Boolean); override;
  667. { ------------------------------------------------------------------------ }
  668. procedure WMActivate(var Message: TWMActivate);
  669. procedure WindowProc(var Message: TMessage); override;
  670. public
  671. constructor Create(AOwner: TComponent); override;
  672. destructor Destroy; override;
  673. function GetClientAlignControl(Align: TAlign): Integer;
  674. property LeftDockPanel: TCnDockPanel read FLeftDockPanel;
  675. property RightDockPanel: TCnDockPanel read FRightDockPanel;
  676. property TopDockPanel: TCnDockPanel read FTopDockPanel;
  677. property BottomDockPanel: TCnDockPanel read FBottomDockPanel;
  678. property LeftSplitter: TCnDockSplitter read FLeftSplitter;
  679. property RightSplitter: TCnDockSplitter read FRightSplitter;
  680. property TopSplitter: TCnDockSplitter read FTopSplitter;
  681. property BottomSplitter: TCnDockSplitter read FBottomSplitter;
  682. property DockPanel[Index: Integer]: TCnDockPanel read GetDockPanel;
  683. property DockPanelWithAlign[Index: TAlign]: TCnDockPanel read GetDockPanelWithAlign;
  684. property DockSplitter[Index: Integer]: TCnDockSplitter read GetDockSplitter;
  685. property DockSplitterWithAlign[Index: TAlign]: TCnDockSplitter read GetDockSplitterWithAlign;
  686. property Version: string read GetDockStyleVersion; // 版本号
  687. published
  688. property LeftSplitterStyle: TCnSplitterStyle read FLeftSplitterStyle write SetLeftSplitterStyle;
  689. property TopSplitterStyle: TCnSplitterStyle read FTopSplitterStyle write SetTopSplitterStyle;
  690. property RightSplitterStyle: TCnSplitterStyle read FRightSplitterStyle write SetRightSplitterStyle;
  691. property BottomSplitterStyle: TCnSplitterStyle read FBottomSplitterStyle write SetBottomSplitterStyle;
  692. property OnGetClientAlignSize: TGetClientAlignSizeEvent
  693. read FOnGetClientAlignSize write FOnGetClientAlignSize;
  694. property OnFinishSetDockPanelSize: TFinishSetDockPanelSizeEvent
  695. read FOnFinishSetDockPanelSize write FOnFinishSetDockPanelSize;
  696. property EnableDock;
  697. property LeftDock;
  698. property TopDock;
  699. property RightDock;
  700. property BottomDock;
  701. property DockStyle;
  702. end;
  703. { 鼠标的位置,分别是'在浮动窗体上','在平铺服务器上','在分页服务器上' }
  704. TMouseStation = (msFloat, msConjoin, msTabPage);
  705. TNCButtonEvent = procedure(DockClient: TCnDockClient; Button: TMouseButton;
  706. X, Y: Smallint; HitTest: Longint; MouseStation: TMouseStation) of object;
  707. TNCButtonDownEvent = TNCButtonEvent;
  708. TNCButtonUpEvent = TNCButtonEvent;
  709. TNCButtonDblClkEvent = TNCButtonEvent;
  710. TNCMouseMoveEvent = procedure(DockClient: TCnDockClient;
  711. X, Y: Smallint; HitTest: Longint; MouseStation: TMouseStation) of object;
  712. TPaintDockEvent = procedure(Canvas: TCanvas;
  713. Control: TControl; const ARect: TRect) of object;
  714. TPaintDockGrabberEvent = TPaintDockEvent;
  715. TPaintDockSplitterEvent = TPaintDockEvent;
  716. TFormHintEvent = procedure(HTFlag: Integer; var HintStr: string; var CanShow: Boolean) of object;
  717. { 停靠客户端 }
  718. TCnDockClient = class(TCnDockBaseControl)
  719. private
  720. FConjoinPanelClass: TCnConjoinPanelClass;
  721. FTabDockClass: TCnTabDockClass;
  722. FParentVisible: Boolean; // 父窗口是否是可见的。
  723. FNCPopupMenu: TPopupMenu; // 当在窗体的标题栏上右击鼠标右键时,弹出的菜单。
  724. FDirectDrag: Boolean; // 当鼠标按下的时候是否立即进行停靠操作。
  725. FShowHint: Boolean; // 是否显示提示信息
  726. FCanFloat: Boolean; // 是否可以浮动,这个功能是应一个用户的要求添加的,
  727. // 为了防止程序的界面过于凌乱,有时候用户并不希望
  728. // 停靠的窗体浮动出来,就用这个属性来限制,如果是True,
  729. // 就允许浮动,否者就不允许,只能停靠到服务器上,
  730. // 当然在服务器之间是可以相互拖动的,默认为True.
  731. FRelativeServer: TCnDockServer; // 有关系的TCnDockServer的实例,这个功能也是应一个
  732. // 用户的要求添加的,当一个客户窗体打算停靠到服务器
  733. // 上面的时候,需要判断FRelativeServer和当前打算停靠
  734. // 的服务器是否是同一个,如果不是,就不能停靠,否者就
  735. // 能够停靠,默认值为nil,当这个属性是nil的时候,就说明
  736. // 可以停靠到所有的服务器上面.
  737. FDockLevel: Integer; // 停靠的级别,只有相同级别的客户窗体才可以相互停靠
  738. FEnableCloseBtn: Boolean; // 是否允许关闭按钮可用.
  739. FOnNCButtonDown: TNCButtonDownEvent;
  740. FOnNCButtonUp: TNCButtonUpEvent;
  741. FOnNCMouseMove: TNCMouseMoveEvent;
  742. FOnNCButtonDblClk: TNCButtonDblClkEvent;
  743. FOnPaintDockGrabber: TPaintDockGrabberEvent;
  744. FOnPaintDockSplitter: TPaintDockSplitterEvent;
  745. FOnFormShowHint: TFormHintEvent;
  746. FOnFormShow: TNotifyEvent;
  747. FOnFormHide: TNotifyEvent;
  748. FCurrentDockSite,
  749. FLastDockSite: TWinControl;// 上一次停靠的服务器
  750. FUnDockLeft, // 浮动时候的左边的位置
  751. FUnDockTop: Integer; // 浮动时候的右边的位置
  752. FVSPaneWidth: Integer; // 面板的宽度
  753. procedure SetParentVisible(const Value: Boolean);
  754. function GetLRDockWidth: Integer;
  755. function GetTBDockHeight: Integer;
  756. procedure SetLRDockWidth(const Value: Integer);
  757. procedure SetTBDockHeight(const Value: Integer);
  758. procedure SetNCPopupMenu(const Value: TPopupMenu);
  759. { ------------------------------------------------------------------------ }
  760. procedure WMNCLButtonDown(var Message: TWMNCHitMessage);
  761. procedure WMNCLButtonUp(var Message: TWMNCHitMessage);
  762. procedure WMNCLButtonDblClk(var Message: TWMNCHitMessage);
  763. procedure WMNCMButtonDown(var Message: TWMNCHitMessage);
  764. procedure WMNCMButtonUp(var Message: TWMNCHitMessage);
  765. procedure WMNCMButtonDblClk(var Message: TWMNCHitMessage);
  766. procedure WMNCRButtonDown(var Message: TWMNCHitMessage);
  767. procedure WMNCRButtonUp(var Message: TWMNCHitMessage);
  768. procedure WMNCRButtonDblClk(var Message: TWMNCHitMessage);
  769. procedure WMNCMouseMove(var Message: TWMNCHitMessage);
  770. procedure CMVisibleChanged(var Message: TMessage);
  771. procedure SetCurrentDockSite(const Value: TWinControl);
  772. procedure SetLastDockSite(const Value: TWinControl);
  773. procedure SetVSPaneWidth(const Value: Integer);
  774. procedure SetUnDockLeft(const Value: Integer);
  775. procedure SetUnDockTop(const Value: Integer);
  776. function GetDockState: Integer;
  777. procedure SetCanFloat(const Value: Boolean);
  778. procedure SetRelativeServer(const Value: TCnDockServer);
  779. procedure SetDockLevel(const Value: Integer);
  780. procedure SetEnableCloseBtn(const Value: Boolean);
  781. protected
  782. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  783. procedure Loaded; override;
  784. procedure DoMenuPopup(X, Y: Integer); virtual;
  785. { ------------------------------------------------------------------------ }
  786. procedure Deactivate; virtual;
  787. procedure Activate; virtual;
  788. { ------------------------------------------------------------------------ }
  789. procedure Notification(AComponent: TComponent;
  790. Operation: TOperation); override;
  791. { ------------------------------------------------------------------------ }
  792. procedure DoFloatDockClients(PanelAlign: TAlign);
  793. procedure DoFloatDockEachOther;
  794. procedure SetBottomDock(const Value: Boolean); override;
  795. procedure SetEachotherDock(const Value: Boolean); override;
  796. procedure SetEnableDock(const Value: Boolean); override;
  797. procedure SetLeftDock(const Value: Boolean); override;
  798. procedure SetRightDock(const Value: Boolean); override;
  799. procedure SetTopDock(const Value: Boolean); override;
  800. { ------------------------------------------------------------------------ }
  801. procedure DoFormOnClose(Sender: TObject;
  802. var Action: TCloseAction); override;
  803. { ------------------------------------------------------------------------ }
  804. procedure WMSize(var Message: TWMSize);
  805. procedure WMActivate(var Message: TWMActivate);
  806. // procedure WMWindowPosChanged(var Message: TWMWindowPosChanged)
  807. procedure WindowProc(var Message: TMessage); override;
  808. property RelativeServer: TCnDockServer read FRelativeServer write SetRelativeServer default nil;
  809. public
  810. constructor Create(AOwner: TComponent); override;
  811. destructor Destroy; override;
  812. { ------------------------------------------------------------------------ }
  813. procedure FormStartDock(var Source: TCnDragDockObject); virtual;
  814. procedure FormPositionDockRect(Source: TCnDragDockObject); virtual;
  815. procedure FormDockOver(Source: TCnDragDockObject; X, Y: Integer;
  816. State: TDragState; var Accept: Boolean); virtual;
  817. procedure FormDockDrop(Source: TCnDragDockObject; X, Y: Integer); virtual;
  818. procedure FormEndDock(Target: TObject; X, Y: Integer); virtual;
  819. function FormUnDock(NewTarget: TWinControl; Client: TControl): Boolean; virtual;
  820. procedure FormGetSiteInfo(Source: TCnDragDockObject;
  821. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  822. var CanDock: Boolean); virtual;
  823. procedure FormGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign); virtual;
  824. { ------------------------------------------------------------------------ }
  825. procedure Assign(Source: TPersistent); override;
  826. { 触发OnFormShow事件 }
  827. procedure MakeShowEvent;
  828. { 触发OnFormClose事件 }
  829. procedure MakeHideEvent;
  830. { 创建DefaultConjoinPanelClass的实例 }
  831. function CreateConjoinPanelClass(ConjoinHost: TForm): TCnConjoinPanel;
  832. { 创建DefaultTabDockClass的实例 }
  833. function CreateTabDockClass(TabHost: TForm): TCnTabPageControl;
  834. { ------------------------------------------------------------------------ }
  835. function CreateConjoinHostAndDockControl(Control1,
  836. Control2: TControl; DockType: TAlign): TCnConjoinDockHostForm; virtual;
  837. function CreateTabHostAndDockControl(Control1,
  838. Control2: TControl): TCnTabDockHostForm; virtual;
  839. { ------------------------------------------------------------------------ }
  840. procedure DoNCButtonDown(Message: TWMNCHitMessage; Button: TMouseButton;
  841. MouseStation: TMouseStation); virtual;
  842. procedure DoNCButtonUp(Message: TWMNCHitMessage; Button: TMouseButton;
  843. MouseStation: TMouseStation); virtual;
  844. procedure DoNCMouseMove(Message: TWMNCHitMessage;
  845. MouseStation: TMouseStation); virtual;
  846. procedure DoNCButtonDblClk(Message: TWMNCHitMessage; Button: TMouseButton;
  847. MouseStation: TMouseStation); virtual;
  848. { ------------------------------------------------------------------------ }
  849. procedure DoPaintDockGrabber(Canvas: TCanvas;
  850. Control: TControl; const ARect: TRect);
  851. procedure DoPaintDockSplitter(Canvas: TCanvas;
  852. Control: TControl; const ARect: TRect);
  853. procedure DoFormShowHint(HTFlag: Integer; var HintStr: string; var CanShow: Boolean);
  854. { ------------------------------------------------------------------------ }
  855. procedure ShowParentForm; // 显示ParentForm
  856. procedure HideParentForm; // 隐藏ParentForm
  857. { 还原所有的停靠客户 }
  858. procedure RestoreChild;
  859. { ------------------------------------------------------------------------ }
  860. property VSPaneWidth: Integer read FVSPaneWidth write SetVSPaneWidth;
  861. { ------------------------------------------------------------------------ }
  862. { 表示父控件的可见性 }
  863. property ParentVisible: Boolean read FParentVisible write SetParentVisible;
  864. { ------------------------------------------------------------------------ }
  865. { 当前的停靠服务器 }
  866. property CurrentDockSite: TWinControl read FCurrentDockSite write SetCurrentDockSite;
  867. { 当前的停靠服务器 }
  868. property LastDockSite: TWinControl read FLastDockSite write SetLastDockSite;
  869. property UnDockLeft: Integer read FUnDockLeft write SetUnDockLeft;
  870. property UnDockTop: Integer read FUnDockTop write SetUnDockTop;
  871. { 停靠客户的状态,是在浮动状态或者停靠状态,还是其他别的状态 }
  872. property DockState: Integer read GetDockState;
  873. published
  874. property OnFormShow: TNotifyEvent read FOnFormShow write FOnFormShow;
  875. property OnFormHide: TNotifyEvent read FOnFormHide write FOnFormHide;
  876. property OnNCButtonDown: TNCButtonDownEvent read FOnNCButtonDown write FOnNCButtonDown;
  877. property OnNCButtonUp: TNCButtonUpEvent read FOnNCButtonUp write FOnNCButtonUp;
  878. property OnNCMouseMove: TNCMouseMoveEvent read FOnNCMouseMove write FOnNCMouseMove;
  879. property OnNCButtonDblClk: TNCButtonDblClkEvent read FOnNCButtonDblClk write FOnNCButtonDblClk;
  880. property OnPaintDockGrabber: TPaintDockGrabberEvent read FOnPaintDockGrabber write FOnPaintDockGrabber;
  881. property OnPaintDockSplitter: TPaintDockSplitterEvent read FOnPaintDockSplitter write FOnPaintDockSplitter;
  882. property OnFormShowHint: TFormHintEvent read FOnFormShowHint write FOnFormShowHint;
  883. { ------------------------------------------------------------------------ }
  884. property LRDockWidth: Integer read GetLRDockWidth write SetLRDockWidth;
  885. property TBDockHeight: Integer read GetTBDockHeight write SetTBDockHeight;
  886. property NCPopupMenu: TPopupMenu read FNCPopupMenu write SetNCPopupMenu;
  887. property DirectDrag: Boolean read FDirectDrag write FDirectDrag;
  888. property ShowHint: Boolean read FShowHint write FShowHint;
  889. property CanFloat: Boolean read FCanFloat write SetCanFloat default True;
  890. property DockLevel: Integer read FDockLevel write SetDockLevel default 0;
  891. property EnableCloseBtn: Boolean read FEnableCloseBtn write SetEnableCloseBtn;
  892. property EnableDock;
  893. property LeftDock;
  894. property TopDock;
  895. property RightDock;
  896. property BottomDock;
  897. property EachOtherDock;
  898. property DockStyle;
  899. end;
  900. TCnConjoinPanel = class(TCnCustomDockPanel)
  901. private
  902. FDockClient: TCnDockClient;
  903. function GetParentForm: TCnConjoinDockHostForm;
  904. // procedure SetUnDockControl(const Value: TControl);
  905. procedure CMUnDockClient(var Message: TCMUnDockClient); message CM_UNDOCKCLIENT;
  906. protected
  907. procedure ReloadDockedControl(const AControlName: string;
  908. var AControl: TControl); override;
  909. { ------------------------------------------------------------------------ }
  910. procedure CustomStartDock(var Source: TCnDragDockObject); override;
  911. procedure CustomGetSiteInfo(Source: TCnDragDockObject;
  912. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  913. var CanDock: Boolean); override;
  914. procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer;
  915. State: TDragState; var Accept: Boolean); override;
  916. procedure CustomPositionDockRect(Source: TCnDragDockObject; X, Y: Integer); override;
  917. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  918. procedure CustomEndDock(Target: TObject; X, Y: Integer); override;
  919. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  920. { ------------------------------------------------------------------------ }
  921. procedure DoDockOver(Source: TDragDockObject; X, Y: Integer; State: TDragState;
  922. var Accept: Boolean); override;
  923. procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect;
  924. MousePos: TPoint; var CanDock: Boolean); override;
  925. function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
  926. public
  927. constructor Create(AOwner: TComponent); override;
  928. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  929. property DockClient: TCnDockClient read FDockClient write FDockClient;
  930. property ParentForm: TCnConjoinDockHostForm read GetParentForm;
  931. end;
  932. TCnAdvConjoinPanel = class(TCnConjoinPanel)
  933. private
  934. procedure CMUnDockClient(var Message: TCMUnDockClient); message CM_UNDOCKCLIENT;
  935. protected
  936. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  937. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  938. { ------------------------------------------------------------------------ }
  939. function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
  940. public
  941. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  942. end;
  943. TCnTabPageControl = class(TCnDockPageControl)
  944. private
  945. FDockClient: TCnDockClient;
  946. FVersion: Integer;
  947. function GetParentForm: TCnTabDockHostForm;
  948. protected
  949. { ------------------------------------------------------------------------ }
  950. procedure AdjustClientRect(var Rect: TRect); override;
  951. procedure ReloadDockedControl(const AControlName: string;
  952. var AControl: TControl); override;
  953. { ------------------------------------------------------------------------ }
  954. procedure CustomStartDock(var Source: TCnDragDockObject); override;
  955. procedure CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  956. var CanDock: Boolean); override;
  957. procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer;
  958. State: TDragState; var Accept: Boolean); override;
  959. procedure CustomPositionDockRect(Source: TCnDragDockObject; X, Y: Integer); override;
  960. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  961. procedure CustomEndDock(Target: TObject; X, Y: Integer); override;
  962. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  963. procedure CustomGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign); override;
  964. { ------------------------------------------------------------------------ }
  965. function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
  966. public
  967. constructor Create(AOwner: TComponent); override;
  968. destructor Destroy; override;
  969. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  970. procedure LoadFromStream(Stream: TStream); virtual;
  971. procedure SaveToStream(Stream: TStream); virtual;
  972. property DockClient: TCnDockClient read FDockClient write FDockClient;
  973. property ParentForm: TCnTabDockHostForm read GetParentForm;
  974. property TabPosition;
  975. end;
  976. TCnAdvTabPageControl = class(TCnTabPageControl)
  977. private
  978. procedure CMUnDockClient(var Message: TCMUnDockClient); message CM_UNDOCKCLIENT;
  979. protected
  980. procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); override;
  981. function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
  982. { ------------------------------------------------------------------------ }
  983. function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
  984. public
  985. destructor Destroy; override;
  986. procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
  987. end;
  988. // TCnDockableForm是TCnConjoinDockHostForm和TCnTabDockHostForm共同的父类
  989. // 处理一些这两个类共同的事件。
  990. // 她上面也有一个TCnDockClient控件,也就是说她也是一个可停靠控件。
  991. // 和一般的放了TCnDockClient控件的窗口有一样的特性。
  992. TCnDockableForm = class(TForm)
  993. private
  994. FDockClient: TCnDockClient;
  995. FDockableControl: TWinControl;
  996. FUnDockControl: TControl;
  997. FFloatingChild: TControl;
  998. function GetDockableControl: TWinControl;
  999. procedure SetDockableControl(const Value: TWinControl);
  1000. procedure SetUnDockControl(const Value: TControl);
  1001. protected
  1002. procedure DoClose(var Action: TCloseAction); override;
  1003. public
  1004. constructor Create(AOwner: TComponent); override;
  1005. destructor Destroy; override;
  1006. property DockClient: TCnDockClient read FDockClient write FDockClient;
  1007. property DockableControl: TWinControl read GetDockableControl write SetDockableControl;
  1008. property UnDockControl: TControl read FUnDockControl write SetUnDockControl;
  1009. property FloatingChild: TControl read FFloatingChild;
  1010. published
  1011. end;
  1012. { 平铺的服务窗体 }
  1013. TCnConjoinDockHostForm = class(TCnDockableForm)
  1014. protected
  1015. procedure DoClose(var Action: TCloseAction); override;
  1016. public
  1017. Panel: TCnConjoinPanel;
  1018. constructor Create(AOwner: TComponent); override;
  1019. property DockClient;
  1020. published
  1021. end;
  1022. { 分页的服务窗体 }
  1023. TCnTabDockHostForm = class(TCnDockableForm)
  1024. public
  1025. PageControl: TCnTabPageControl;
  1026. constructor Create(AOwner: TComponent); override;
  1027. destructor Destroy; override;
  1028. function GetActiveDockForm: TForm;
  1029. property DockClient;
  1030. published
  1031. end;
  1032. var
  1033. { 默认的TDockServer停靠Panel是TCnDockPanel }
  1034. DefaultDockPanelClass: TCnDockPanelClass = TCnDockPanel;
  1035. { 默认的停靠分割条是TCnDockSplitter }
  1036. DefaultDockSplitterClass: TCnDockSplitterClass = TCnDockSplitter;
  1037. { 默认的平铺停靠类是TCnConjoinPanel }
  1038. DefaultConjoinPanelClass: TCnConjoinPanelClass = TCnConjoinPanel;
  1039. { 默认的分页停靠类是TCnTabPageControl }
  1040. DefaultTabDockClass: TCnTabDockClass = TCnTabPageControl;
  1041. { 默认的停靠管理器节点是TCnDockZone }
  1042. DefaultDockZoneClass: TCnDockZoneClass = TCnDockZone;
  1043. { 默认的停靠管理器是TCnDockTree }
  1044. DefaultDockTreeClass: TCnDockTreeClass = TCnDockTree;
  1045. // FCnConjoinServerOptionClass: TCnBasicConjoinServerOptionClass;
  1046. // FCnTabServerOptionClass: TCnBasicTabServerOptionClass;
  1047. { 显示窗体 }
  1048. procedure ShowDockForm(DockWindow: TWinControl);
  1049. { 隐藏窗体 }
  1050. procedure HideDockForm(DockWindow: TControl);
  1051. { 使在Host上的TDockClient控件触发OnShowEvent或OnHideEvent,递归调用 }
  1052. procedure MakeDockClientEvent(Host: TControl; Visible: Boolean);
  1053. { 获得窗体的可见性 }
  1054. function GetFormVisible(DockWindow: TWinControl): Boolean;
  1055. { 设置分页的服务窗体中的PageControl的PopMenu }
  1056. procedure SetDockPageControlPopupMenu(Value: TPopupMenu);
  1057. { 设置分页的服务窗体中的PageControl的HotTrack }
  1058. procedure SetDockPageControlHotTrack(Value: Boolean);
  1059. { 设置分页的服务窗体的显示风格 }
  1060. procedure SetTabDockHostBorderStyle(Value: TFormBorderStyle);
  1061. { 设置平铺的服务窗体的显示风格 }
  1062. procedure SetConjoinDockHostBorderStyle(Value: TFormBorderStyle);
  1063. { 把停靠窗体的信息保存进文件 }
  1064. procedure SaveDockTreeToFile(FileName: string);
  1065. { 从文件里读出停靠窗体的信息 }
  1066. procedure LoadDockTreeFromFile(FileName: string);
  1067. { 把停靠窗体的信息保存进注册表 }
  1068. procedure SaveDockTreeToReg(RootKey: DWORD; RegPath: string);
  1069. { 从注册表里读出停靠窗体的信息 }
  1070. procedure LoadDockTreeFromReg(RootKey: DWORD; RegPath: string);
  1071. { 在窗体上查找TDockBaseControl控件 }
  1072. function FindDockBaseControl(Client: TControl): TCnDockBaseControl;
  1073. { 在窗体上查找TDockClient控件 }
  1074. function FindDockClient(Client: TControl): TCnDockClient;
  1075. { 在窗体上查找TDockServer控件 }
  1076. function FindDockServer(Client: TControl): TCnDockServer;
  1077. { 检查停靠服务器和客户端或者停靠客户端之间是否有停靠关系 }
  1078. function IsDockable(Sender: TWinControl; Client: TControl;
  1079. DropCtl: TControl = nil; DockAlign: TAlign = alNone): Boolean;
  1080. { 计算停靠的区域 }
  1081. function ComputeDockingRect(AControl: TControl;
  1082. var DockRect: TRect; MousePos: TPoint): TAlign;
  1083. { 使停靠窗体AControl从Sender中拖出来 }
  1084. procedure DoFloat(Sender, AControl: TControl);
  1085. { 设置控件的DockSite属性 }
  1086. procedure SetDockSite(Control: TWinControl; SiteValue: Boolean);
  1087. { 使DockForm控件浮动,包括它上面的DockClients }
  1088. procedure DoFloatForm(DockForm: TControl);
  1089. { 删除所有无用的TCnDockableForm窗体 }
  1090. procedure FreeAllDockableForm;
  1091. { 使应用程序的所有的窗体都浮动 }
  1092. procedure DoFloatAllForm;
  1093. { 得到AControl客户区中Align方向排列的子控件累加的大小到AControl边框的距离 }
  1094. function GetClientAlignControlArea(AControl: TWinControl; Align: TAlign; Exclude: TControl = nil): Integer;
  1095. procedure ResetDockClient(Control: TControl; NewTarget: TControl); overload;
  1096. procedure ResetDockClient(DockClient: TCnDockClient; NewTarget: TControl); overload;
  1097. procedure ReshowAllVisibleWindow;
  1098. { 释放所有没有客户的服务窗体 }
  1099. //procedure FreeAllHostOfNotClient;
  1100. implementation
  1101. uses Dialogs, Math, CnDockSupportProc, CnDockGlobal, CnDockInfo, CnVSNETDockStyle;//, CnVSNETDockStyle;
  1102. var { 停靠的PageConrol的弹出菜单,默认为没有 }
  1103. DockPageControlPopupMenu: TPopupMenu = nil;
  1104. { 停靠的PageConrol是否高亮显示,默认为False }
  1105. DockPageControlHotTrack: Boolean = False;
  1106. { 分页式窗口的风格,默认为bsSizeToolWin }
  1107. TabDockHostBorderStyle: TFormBorderStyle = bsSizeToolWin;
  1108. { 平铺式窗体的风格,默认为bsSizeToolWin }
  1109. ConjoinDockHostBorderStyle: TFormBorderStyle = bsSizeToolWin;
  1110. { 操作系统是否是WinXP }
  1111. IsWinXP: Boolean;
  1112. type
  1113. TCnControlAccess = class(TControl);
  1114. TCnWinControlAccess = class(TWinControl);
  1115. {$R CnDockableForm.DFM}
  1116. {$R CnConjoinDockHost.DFM}
  1117. {$R CnTabDockHost.DFM}
  1118. { 在窗体上查找TDockBaseControl控件 }
  1119. function FindDockBaseControl(Client: TControl): TCnDockBaseControl;
  1120. var i: Integer;
  1121. begin
  1122. Result := nil;
  1123. if Client <> nil then
  1124. begin
  1125. for i := 0 to Client.ComponentCount - 1 do
  1126. if (Client.Components[i] is TCnDockBaseControl) then
  1127. begin
  1128. Result := TCnDockBaseControl(Client.Components[i]);
  1129. Exit;
  1130. end;
  1131. end;
  1132. end;
  1133. { 在窗体上查找TDockServer控件 }
  1134. function FindDockServer(Client: TControl): TCnDockServer;
  1135. var ADockControl: TCnDockBaseControl;
  1136. begin
  1137. ADockControl := FindDockBaseControl(Client);
  1138. if ADockControl is TCnDockServer then
  1139. Result := TCnDockServer(ADockControl)
  1140. else Result := nil;
  1141. end;
  1142. { 在窗体上查找TDockClient控件 }
  1143. function FindDockClient(Client: TControl): TCnDockClient;
  1144. var ADockControl: TCnDockBaseControl;
  1145. begin
  1146. ADockControl := FindDockBaseControl(Client);
  1147. if ADockControl is TCnDockClient then
  1148. Result := TCnDockClient(ADockControl)
  1149. else Result := nil;
  1150. end;
  1151. { 检查停靠服务器和客户端或者停靠客户端之间是否有停靠关系 }
  1152. function IsDockable(Sender: TWinControl; Client: TControl; DropCtl: TControl = nil;
  1153. DockAlign: TAlign = alNone): Boolean;
  1154. var ADockClient: TCnDockClient;
  1155. i: Integer;
  1156. SenderDockStyle,
  1157. ClientDockStyle: TCnBasicDockStyle;
  1158. SenderStyleName,
  1159. ClientStyleName: string;
  1160. // Level_1: Integer;
  1161. Label JudgeRelation;
  1162. begin
  1163. ADockClient := FindDockClient(Client);
  1164. Result := False;
  1165. if (ADockClient <> nil) and (ADockClient.EnableDock) then
  1166. begin
  1167. if Sender is TCnDockPanel then
  1168. begin
  1169. with TCnDockPanel(Sender) do
  1170. begin
  1171. Result := DockServer.EnableDock and
  1172. // ((DockAlign <> alClient) or (ADockClient.EachOtherDock and (DockAlign = alClient))) and
  1173. (((Align = alLeft) and DockServer.LeftDock and (ADockClient.LeftDock)) or
  1174. ((Align = alTop) and DockServer.TopDock and (ADockClient.TopDock)) or
  1175. ((Align = alRight) and DockServer.RightDock and (ADockClient.RightDock)) or
  1176. ((Align = alBottom) and DockServer.BottomDock and (ADockClient.BottomDock)));
  1177. SenderDockStyle := DockServer.DockStyle;
  1178. end;
  1179. end else
  1180. begin
  1181. if (Sender <> nil) and (Sender.Parent is TCnDockableForm) then
  1182. begin
  1183. with TCnDockableForm(Sender.Parent).DockableControl do
  1184. for i := 0 to DockClientCount - 1 do
  1185. if DockClients[i] = Client then
  1186. Exit;
  1187. end;
  1188. Result := ADockClient.EachOtherDock;
  1189. if Sender <> nil then
  1190. ADockClient := FindDockClient(Sender.Parent);
  1191. if ADockClient <> nil then
  1192. Result := Result and ADockClient.EachOtherDock;
  1193. // else Result := False;
  1194. if ADockClient <> nil then
  1195. SenderDockStyle := ADockClient.DockStyle
  1196. else Exit;
  1197. end;
  1198. ADockClient := FindDockClient(Client);
  1199. if ADockClient <> nil then
  1200. ClientDockStyle := ADockClient.DockStyle
  1201. else Exit;
  1202. if SenderDockStyle = nil then
  1203. SenderStyleName := ''
  1204. else SenderStyleName := SenderDockStyle.ClassName;
  1205. if ClientDockStyle = nil then
  1206. ClientStyleName := ''
  1207. else ClientStyleName := ClientDockStyle.ClassName;
  1208. Result := Result and (SenderStyleName = ClientStyleName);
  1209. JudgeRelation:
  1210. { if Result and (GlobalDockClient <> nil) then
  1211. begin
  1212. ADockClient := nil;
  1213. Level_1 := GlobalDockClient.DockLevel;
  1214. if DropCtl <> nil then
  1215. ADockClient := FindDockClient(DropCtl);
  1216. if ADockClient = nil then
  1217. begin
  1218. if Sender.Parent is TCnDockableForm then
  1219. ADockClient := FindDockClient(Sender.Parent)
  1220. else
  1221. ADockClient := FindDockClient(Sender);
  1222. end;
  1223. if ADockClient <> nil then
  1224. Result := Level_1 = ADockClient.DockLevel;
  1225. end;}
  1226. (* ADockClient := GlobalDockClient;
  1227. if Result and (Sender <> nil) and (ADockClient <> nil) then
  1228. begin
  1229. ADockServer := FindDockServer(Sender.Parent);
  1230. if (ADockServer <> nil) and (ADockClient.RelativeServer <> nil) then
  1231. Result := Result and (ADockServer = ADockClient.RelativeServer)
  1232. else
  1233. begin
  1234. ADockServer := ADockClient.RelativeServer;
  1235. if Sender.Parent is TCnDockableForm then
  1236. ADockClient := FindDockClient(Sender.Parent)
  1237. else
  1238. ADockClient := FindDockClient(Sender);
  1239. if ((ADockClient <> nil) and (ADockClient.RelativeServer = nil)) or (ADockServer = nil) then
  1240. Exit;
  1241. if (ADockClient <> nil){ or (ADockServer <> nil) }then
  1242. Result := Result and (ADockServer = ADockClient.RelativeServer);
  1243. end;
  1244. end;*)
  1245. end;
  1246. end;
  1247. { 更新窗体的Caption,同时更新父窗口的Caption,递归调用 }
  1248. procedure UpdateCaption(Source: TWinControl; Exclude: TControl);
  1249. var i: Integer;
  1250. Host: TCnDockableForm;
  1251. begin
  1252. if (Source <> nil) and (Source.Parent is TCnDockableForm) then
  1253. begin
  1254. Host := TCnDockableForm(Source.Parent);
  1255. Host.Caption := '';
  1256. { 更新本身的Caption }
  1257. for I := 0 to Source.DockClientCount - 1 do
  1258. begin
  1259. if Source.DockClients[I].Visible and (Source.DockClients[I] <> Exclude) then
  1260. Host.Caption := Host.Caption + TCustomForm(Source.DockClients[I]).Caption + gs_CnStringSplitter;
  1261. end;
  1262. { 更新TCnTabPageControl的标签 }
  1263. if (Host.HostDockSite is TCnTabPageControl) then
  1264. begin
  1265. with TCnTabPageControl(Host.HostDockSite) do
  1266. if (ActivePage <> nil) and (ActivePage.Controls[0] = Source) then
  1267. ActivePage.Caption := Host.Caption;
  1268. end;
  1269. UpdateCaption(Host.HostDockSite, nil);
  1270. end;
  1271. end;
  1272. { 使停靠窗体AControl从Sender中拖出来 }
  1273. procedure DoFloat(Sender, AControl: TControl);
  1274. var
  1275. ARect: TRect;
  1276. CH{ CaptionHeight }, BW{ BorderWidth }: Integer;
  1277. begin
  1278. { 获得标题栏的高度和边框的宽度 }
  1279. BW := Cn_GetSysBorderWidth;
  1280. CH := Cn_GetSysCaptionHeight;
  1281. { 进行坐标转换 }
  1282. ARect.TopLeft := Sender.ClientToScreen(Point(
  1283. -(BW + 3), -(CH + BW + 1)));
  1284. ARect.BottomRight := Sender.ClientToScreen(Point(
  1285. Sender.UndockWidth - (BW + 3),
  1286. Sender.UndockHeight - (BW + CH + 1)));
  1287. // Cn_LockWindow(TWinControl(Sender));
  1288. try
  1289. { 使AControl浮动 }
  1290. AControl.ManualFloat(ARect);
  1291. finally
  1292. // Cn_UnLockWindow;
  1293. end;
  1294. if (AControl.Left <> ARect.Left) or (AControl.Top <> ARect.Top) then
  1295. begin
  1296. AControl.Left := ARect.Left;
  1297. AControl.Top := ARect.Top;
  1298. end;
  1299. // SetDockSite(AControl, True);
  1300. end;
  1301. { 计算停靠的区域 }
  1302. function ComputeDockingRect(AControl: TControl; var DockRect: TRect; MousePos: TPoint): TAlign;
  1303. var
  1304. DockTopRect,
  1305. DockLeftRect,
  1306. DockBottomRect,
  1307. DockRightRect,
  1308. DockCenterRect: TRect;
  1309. begin
  1310. Result := alNone;
  1311. // 划分停靠区域
  1312. if AControl = nil then Exit;
  1313. with AControl do
  1314. begin
  1315. DockLeftRect.TopLeft := Point(0, 0);
  1316. DockLeftRect.BottomRight := Point(ClientWidth div 5, ClientHeight);
  1317. DockTopRect.TopLeft := Point(ClientWidth div 5, 0);
  1318. DockTopRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5);
  1319. DockRightRect.TopLeft := Point(ClientWidth div 5 * 4, 0);
  1320. DockRightRect.BottomRight := Point(ClientWidth, ClientHeight);
  1321. DockBottomRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5 * 4);
  1322. DockBottomRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight);
  1323. DockCenterRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5);
  1324. DockCenterRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5 * 4);
  1325. // 发现鼠标在哪个停靠区域
  1326. if PtInRect(DockLeftRect, MousePos) then
  1327. begin
  1328. Result := alLeft;
  1329. DockRect := DockLeftRect;
  1330. DockRect.Right := ClientWidth div 2;
  1331. end else if PtInRect(DockTopRect, MousePos) then
  1332. begin
  1333. Result := alTop;
  1334. DockRect := DockTopRect;
  1335. DockRect.Left := 0;
  1336. DockRect.Right := ClientWidth;
  1337. DockRect.Bottom := ClientHeight div 2;
  1338. end else if PtInRect(DockRightRect, MousePos) then
  1339. begin
  1340. Result := alRight;
  1341. DockRect := DockRightRect;
  1342. DockRect.Left := ClientWidth div 2;
  1343. end else if PtInRect(DockBottomRect, MousePos) then
  1344. begin
  1345. Result := alBottom;
  1346. DockRect := DockBottomRect;
  1347. DockRect.Left := 0;
  1348. DockRect.Right := ClientWidth;
  1349. DockRect.Top := ClientHeight div 2;
  1350. end else if PtInRect(DockCenterRect, MousePos) then
  1351. begin
  1352. Result := alClient;
  1353. DockRect := DockCenterRect;
  1354. end;
  1355. if Result = alNone then Exit;
  1356. // DockRect是屏幕坐标
  1357. DockRect.TopLeft := ClientToScreen(DockRect.TopLeft);
  1358. DockRect.BottomRight := ClientToScreen(DockRect.BottomRight);
  1359. end;
  1360. end;
  1361. { 显示窗体,如果父窗口也是不可见的,就显示父窗口,递归调用 }
  1362. procedure ShowDockForm(DockWindow: TWinControl);
  1363. procedure ShowClient(Client, DockParent: TWinControl);
  1364. var ADockClient: TCnDockClient;
  1365. i: Integer;
  1366. begin
  1367. { 如果窗体上面还有停靠窗体,就分别调用她们的MakeDockClientEvent }
  1368. if (DockParent is TCnDockableForm) and (Client <> nil) then
  1369. begin
  1370. with TCnDockableForm(DockParent).DockableControl do
  1371. for i := 0 to DockClientCount - 1 do
  1372. begin
  1373. if DockClients[i] <> Client then
  1374. MakeDockClientEvent(DockClients[i], True);
  1375. end;
  1376. if Client.HostDockSite is TCnCustomDockControl then
  1377. TCnCustomDockControl(Client.HostDockSite).UpdateCaption(nil);
  1378. end else
  1379. begin
  1380. { 否则就调用自己的MakeShowEvent }
  1381. ADockClient := FindDockClient(DockParent);
  1382. if ADockClient <> nil then
  1383. begin
  1384. ADockClient.DockStyle.ShowDockForm(ADockClient);
  1385. if DockParent.CanFocus then
  1386. DockParent.SetFocus;
  1387. end;
  1388. end;
  1389. if DockParent.Parent = nil then
  1390. SetForegroundWindow(DockParent.Handle);
  1391. end;
  1392. { 显示TCnDockPanel }
  1393. function ShowDockPanel(Client: TWinControl): TWinControl;
  1394. begin
  1395. Result := Client;
  1396. if Client <> nil then
  1397. begin
  1398. if Client.HostDockSite is TCnDockPanel then
  1399. begin
  1400. { 根据具体情况显示TCnDockPanel }
  1401. TCnDockPanel(Client.HostDockSite).ShowDockPanel(True, Client, sdfDockPanel);
  1402. Result := nil;
  1403. end;
  1404. end;
  1405. end;
  1406. { 显示分页窗体 }
  1407. function ShowTabDockHost(Client: TWinControl): TWinControl;
  1408. var i: Integer;
  1409. begin
  1410. Result := Client;
  1411. if Client <> nil then
  1412. begin
  1413. ShowClient(nil, Client);
  1414. if Client.HostDockSite is TCnTabPageControl then
  1415. begin
  1416. with TCnTabPageControl(Client.HostDockSite) do
  1417. for i:=0 to PageCount - 1 do
  1418. begin
  1419. if Pages[i].Controls[0] = Client then
  1420. begin
  1421. Pages[i].Show;
  1422. Break;
  1423. end;
  1424. end;
  1425. if (Client.HostDockSite <> nil) and not (Client.HostDockSite is TCnDockPanel) then
  1426. begin
  1427. Result := Client.HostDockSite.Parent;
  1428. ShowClient(Client, Result);
  1429. if (Result <> nil) and (Result.HostDockSite is TCnTabPageControl) then
  1430. Result := ShowTabDockHost(Result);
  1431. end;
  1432. end;
  1433. end;
  1434. end;
  1435. { 显示平铺窗体 }
  1436. function ShowConjoinDockHost(Client: TWinControl): TWinControl;
  1437. begin
  1438. Result := Client;
  1439. if Client <> nil then
  1440. begin
  1441. ShowClient(nil, Client);
  1442. if (Client.HostDockSite <> nil) and not (Client.HostDockSite is TCnDockPanel) then
  1443. begin
  1444. if Client.HostDockSite.Parent <> nil then
  1445. begin
  1446. Result := Client.HostDockSite.Parent;
  1447. ShowClient(Client, Result);
  1448. if (Result <> nil) and (Result.HostDockSite is TCnConjoinPanel) then
  1449. Result := ShowConjoinDockHost(Result);
  1450. end;
  1451. end;
  1452. end;
  1453. end;
  1454. procedure ShowPopupPanel(Client: TWinControl);
  1455. begin
  1456. if Client.HostDockSite is TCnVSPopupPanel then
  1457. TCnVSPopupPanel(Client.HostDockSite).VSChannel.PopupDockForm(Client)
  1458. else if (Client.HostDockSite <> nil) and (Client.HostDockSite.Parent <> nil) then
  1459. begin
  1460. if (Client.HostDockSite.Parent.HostDockSite is TCnVSPopupPanel) then
  1461. TCnVSPopupPanel(Client.HostDockSite.Parent.HostDockSite).VSChannel.PopupDockForm(Client)
  1462. else if (Client.HostDockSite.Parent.HostDockSite is TCnDockPanel) then
  1463. Client.HostDockSite.Parent.HostDockSite.Invalidate;
  1464. end;
  1465. end;
  1466. var TmpDockWindow: TWinControl;
  1467. begin
  1468. TmpDockWindow := DockWindow;
  1469. repeat
  1470. DockWindow := ShowTabDockHost(DockWindow);
  1471. DockWindow := ShowConjoinDockHost(DockWindow);
  1472. DockWindow := ShowDockPanel(DockWindow);
  1473. until (DockWindow = nil) or (DockWindow.Parent = nil);
  1474. ShowPopupPanel(TmpDockWindow);
  1475. end;
  1476. { 隐藏窗体,递归调用 }
  1477. procedure HideDockForm(DockWindow: TControl);
  1478. { 隐藏停靠客户窗体 }
  1479. procedure HideDockChild(DockWindow: TControl);
  1480. var i: Integer;
  1481. DockClient: TCnDockClient;
  1482. begin
  1483. if DockWindow = nil then Exit;
  1484. if (DockWindow is TCnDockableForm) and (DockWindow.Visible) then
  1485. begin
  1486. { 如果窗体上还有子窗体并且窗体是可见的,就调用子窗体的DockStyle的HideDockForm }
  1487. with TCnDockableForm(DockWindow).DockableControl do
  1488. for i := 0 to DockClientCount - 1 do
  1489. HideDockChild(DockClients[i]);
  1490. end;
  1491. DockClient := FindDockClient(DockWindow);
  1492. if (DockWindow is TForm) and (TForm(DockWindow).FormStyle <> fsMDIChild) then
  1493. DockClient.DockStyle.HideDockForm(DockClient);
  1494. end;
  1495. { 隐藏停靠父窗体 }
  1496. procedure HideDockParent(DockWindow: TControl);
  1497. var
  1498. Host: TWinControl;
  1499. DockClient: TCnDockClient;
  1500. begin
  1501. if (DockWindow <> nil) and (DockWindow.HostDockSite <> nil) then
  1502. begin
  1503. Host := DockWindow.HostDockSite;
  1504. if Host.VisibleDockClientCount = 0 then
  1505. begin
  1506. { 如果停靠窗体的父的上面的可见停靠窗体的个数为0,就应该隐藏这个停靠窗体的父 }
  1507. if Host is TCnDockPanel then
  1508. { 调整TCnDockPanel的大小 }
  1509. TCnDockPanel(Host).ShowDockPanel(False, nil)
  1510. else begin
  1511. if Host.Parent <> nil then
  1512. begin
  1513. { 使停靠窗体的父隐藏,并且调用她上面的TCnDockClient的DockStyle的HideDockForm函数 }
  1514. DockClient := FindDockClient(Host.Parent);
  1515. DockClient.DockStyle.HideDockForm(DockClient);
  1516. HideDockParent(Host.Parent);
  1517. end;
  1518. end
  1519. end;
  1520. end;
  1521. end;
  1522. procedure HidePopupPanel(Client: TWinControl);
  1523. begin
  1524. if Client.HostDockSite is TCnVSPopupPanel then
  1525. TCnVSPopupPanel(Client.HostDockSite).VSChannel.HidePopupPanel(Client)
  1526. else if (Client.HostDockSite <> nil) and (Client.HostDockSite.Parent <> nil) then
  1527. begin
  1528. if (Client.HostDockSite.Parent.HostDockSite is TCnVSPopupPanel) then
  1529. TCnVSPopupPanel(Client.HostDockSite.Parent.HostDockSite).VSChannel.HidePopupPanel(Client)
  1530. else if (Client.HostDockSite.Parent.HostDockSite is TCnDockPanel) then
  1531. Client.HostDockSite.Parent.HostDockSite.Invalidate
  1532. end;
  1533. end;
  1534. var TmpDockWindow: TWinControl;
  1535. begin
  1536. TmpDockWindow := TWinControl(DockWindow);
  1537. HideDockChild(DockWindow);
  1538. HideDockParent(DockWindow);
  1539. if (DockWindow.HostDockSite is TCnCustomDockControl) then
  1540. TCnCustomDockControl(DockWindow.HostDockSite).UpdateCaption(DockWindow);
  1541. HidePopupPanel(TmpDockWindow);
  1542. end;
  1543. { 使在Host上的TDockClient控件触发OnShowEvent或OnHideEvent,递归调用 }
  1544. procedure MakeDockClientEvent(Host: TControl; Visible: Boolean);
  1545. var i: Integer;
  1546. ADockClient: TCnDockClient;
  1547. begin
  1548. ADockClient := FindDockClient(Host);
  1549. if ADockClient <> nil then
  1550. begin
  1551. if Visible then ADockClient.MakeShowEvent
  1552. else ADockClient.MakeHideEvent;
  1553. if (Host is TCnDockableForm) and (Host.Visible) then
  1554. begin
  1555. with TCnDockableForm(Host).DockableControl do
  1556. for i := 0 to DockClientCount - 1 do
  1557. MakeDockClientEvent(DockClients[i], Visible);
  1558. end;
  1559. end;
  1560. end;
  1561. { 获得窗体的可见性,递归调用 }
  1562. function GetFormVisible(DockWindow: TWinControl): Boolean;
  1563. var
  1564. ADockClient: TCnDockClient;
  1565. begin
  1566. Result := True;
  1567. ADockClient := FindDockClient(DockWindow);
  1568. if ADockClient <> nil then
  1569. begin
  1570. Result := ADockClient.DockStyle.GetDockFormVisible(ADockClient);
  1571. end;
  1572. end;
  1573. { 设置分页的服务窗体中的PageControl的PopMenu }
  1574. procedure SetDockPageControlPopupMenu(Value: TPopupMenu);
  1575. var i: Integer;
  1576. begin
  1577. DockPageControlPopupMenu := Value;
  1578. for i := 0 to Screen.FormCount - 1 do
  1579. begin
  1580. if Screen.CustomForms[i] is TCnTabDockHostForm then
  1581. TCnTabDockHostForm(Screen.CustomForms[i]).PageControl.PopupMenu := Value;
  1582. end;
  1583. end;
  1584. { 设置分页的服务窗体中的PageControl的HotTrack }
  1585. procedure SetDockPageControlHotTrack(Value: Boolean);
  1586. var i: Integer;
  1587. begin
  1588. DockPageControlHotTrack := Value;
  1589. for i := 0 to Screen.FormCount - 1 do
  1590. begin
  1591. if Screen.CustomForms[i] is TCnTabDockHostForm then
  1592. TCnTabDockHostForm(Screen.CustomForms[i]).PageControl.HotTrack := Value;
  1593. end;
  1594. end;
  1595. { 设置分页的服务窗体的显示风格 }
  1596. procedure SetTabDockHostBorderStyle(Value: TFormBorderStyle);
  1597. var i: Integer;
  1598. begin
  1599. TabDockHostBorderStyle := Value;
  1600. for i := 0 to Screen.FormCount - 1 do
  1601. begin
  1602. if (Screen.CustomForms[i] is TCnTabDockHostForm) and (Screen.CustomForms[i].HostDockSite = nil) then
  1603. TCnTabDockHostForm(Screen.CustomForms[i]).BorderStyle := Value;
  1604. end;
  1605. end;
  1606. { 设置平铺的服务窗体的显示风格 }
  1607. procedure SetConjoinDockHostBorderStyle(Value: TFormBorderStyle);
  1608. var i: Integer;
  1609. begin
  1610. ConjoinDockHostBorderStyle := Value;
  1611. for i := 0 to Screen.FormCount - 1 do
  1612. begin
  1613. if (Screen.CustomForms[i] is TCnConjoinDockHostForm) and (Screen.CustomForms[i].HostDockSite = nil) then
  1614. TCnConjoinDockHostForm(Screen.CustomForms[i]).BorderStyle := Value;
  1615. end;
  1616. end;
  1617. { 把停靠窗体的信息保存进文件 }
  1618. procedure SaveDockTreeToFile(FileName: string);
  1619. var CnDockInfoTree: TCnDockInfoTree;
  1620. i: Integer;
  1621. begin
  1622. HideAllPopupPanel(nil);
  1623. { 创建停靠信息树 }
  1624. CnDockInfoTree := TCnDockInfoTree.Create(TCnDockInfoZone);
  1625. try
  1626. { 遍历应用程序的所有窗口 }
  1627. for i := 0 to Screen.CustomFormCount - 1 do
  1628. begin
  1629. if (Screen.CustomForms[i].Parent = nil) and
  1630. ((FindDockClient(Screen.CustomForms[i]) <> nil) or (FindDockServer(Screen.CustomForms[i]) <> nil)) then
  1631. { 把符合条件的窗体的停靠信息保存到信息树中 }
  1632. CnDockInfoTree.CreateZoneAndAddInfoFromApp(Screen.CustomForms[i]);
  1633. end;
  1634. { 打开INI文件 }
  1635. CnDockInfoTree.DockInfoIni := TIniFile.Create(FileName);
  1636. try
  1637. { 把信息树中的停靠信息写到INI文件中 }
  1638. CnDockInfoTree.WriteInfoToIni;
  1639. finally
  1640. { 关闭INI文件 }
  1641. CnDockInfoTree.DockInfoIni.Free;
  1642. end;
  1643. finally
  1644. { 释放停靠信息树 }
  1645. CnDockInfoTree.Free;
  1646. end;
  1647. end;
  1648. procedure ReshowAllVisibleWindow;
  1649. var i: Integer;
  1650. begin
  1651. if IsWinXP then
  1652. begin
  1653. for i := 0 to Screen.FormCount - 1 do
  1654. begin
  1655. if Screen.Forms[i].Visible then
  1656. Windows.ShowWindow(Screen.Forms[i].Handle, SW_SHOW)
  1657. else
  1658. Windows.ShowWindow(Screen.Forms[i].Handle, SW_HIDE);
  1659. end;
  1660. end;
  1661. end;
  1662. { 从文件里读出停靠窗体的信息 }
  1663. procedure LoadDockTreeFromFile(FileName: string);
  1664. var CnDockInfoTree: TCnDockInfoTree;
  1665. Form: TForm;
  1666. begin
  1667. HideAllPopupPanel(nil);
  1668. // 创建一个没有边框,大小为0的窗体,这个窗体的作用是防止屏幕闪烁
  1669. Form := TForm.CreateNew(nil);
  1670. Form.BorderStyle := bsNone;
  1671. Form.BoundsRect := Rect(0,0,0,0);
  1672. Form.Visible := True;
  1673. Form.Name := 'A_B_C_D_E_F_G_H_I_J_K_L_M_N';
  1674. { 创建停靠信息树 }
  1675. CnDockInfoTree := TCnDockInfoTree.Create(TCnDockInfoZone);
  1676. { 锁住Windows桌面 }
  1677. Cn_LockWindow(nil);
  1678. try
  1679. { 打开INI文件 }
  1680. CnDockInfoTree.DockInfoIni := TIniFile.Create(FileName);
  1681. try
  1682. IsLoading := True;
  1683. { 从INI文件里读出数据并且还原停靠信息 }
  1684. CnDockInfoTree.ReadInfoFromIni;
  1685. finally
  1686. { 关闭INI文件 }
  1687. CnDockInfoTree.DockInfoIni.Free;
  1688. IsLoading := False;
  1689. end;
  1690. finally
  1691. Form.Release;
  1692. { 解锁Windows桌面 }
  1693. Cn_UnLockWindow;
  1694. { 释放停靠信息树 }
  1695. CnDockInfoTree.Free;
  1696. end;
  1697. ReshowAllVisibleWindow;
  1698. end;
  1699. { 把停靠窗体的信息保存进注册表 }
  1700. procedure SaveDockTreeToReg(RootKey: DWORD; RegPath: string);
  1701. var CnDockInfoTree: TCnDockInfoTree;
  1702. i: Integer;
  1703. begin
  1704. HideAllPopupPanel(nil);
  1705. { 创建停靠信息树 }
  1706. CnDockInfoTree := TCnDockInfoTree.Create(TCnDockInfoZone);
  1707. try
  1708. { 遍历应用程序的所有窗口 }
  1709. for i := 0 to Screen.CustomFormCount - 1 do
  1710. begin
  1711. if (Screen.CustomForms[i].Parent = nil) and
  1712. (FindDockClient(Screen.CustomForms[i]) <> nil) then
  1713. { 把符合条件的窗体的停靠信息保存到信息树中(接着是停靠客户) }
  1714. CnDockInfoTree.CreateZoneAndAddInfoFromApp(Screen.CustomForms[i]);
  1715. end;
  1716. for i := 0 to Screen.CustomFormCount - 1 do
  1717. begin
  1718. if (Screen.CustomForms[i].Parent = nil) and
  1719. (FindDockServer(Screen.CustomForms[i]) <> nil) then
  1720. { 把符合条件的窗体的停靠信息保存到信息树中(首先是停靠服务器) }
  1721. CnDockInfoTree.CreateZoneAndAddInfoFromApp(Screen.CustomForms[i]);
  1722. end;
  1723. { 打开TRegistry }
  1724. CnDockInfoTree.DockInfoReg := TRegistry.Create;
  1725. try
  1726. { 把信息树中的停靠信息写到注册表中 }
  1727. CnDockInfoTree.DockInfoReg.RootKey := RootKey;
  1728. CnDockInfoTree.WriteInfoToReg(RegPath);
  1729. finally
  1730. { 关闭注册表 }
  1731. CnDockInfoTree.DockInfoReg.Free;
  1732. end;
  1733. finally
  1734. { 释放停靠信息树 }
  1735. CnDockInfoTree.Free;
  1736. end;
  1737. end;
  1738. { 从注册表里读出停靠窗体的信息 }
  1739. procedure LoadDockTreeFromReg(RootKey: DWORD; RegPath: string);
  1740. var CnDockInfoTree: TCnDockInfoTree;
  1741. Form: TForm;
  1742. begin
  1743. HideAllPopupPanel(nil);
  1744. // 创建一个没有边框,大小为0的窗体,这个窗体的作用是防止屏幕闪烁
  1745. Form := TForm.CreateNew(nil);
  1746. Form.BorderStyle := bsNone;
  1747. Form.BoundsRect := Rect(0,0,0,0);
  1748. Form.Visible := True;
  1749. Form.Name := 'A_B_C_D_E_F_G_H_I_J_K_L_M_N';
  1750. { 创建停靠信息树 }
  1751. CnDockInfoTree := TCnDockInfoTree.Create(TCnDockInfoZone);
  1752. { 锁住Windows桌面 }
  1753. Cn_LockWindow(nil);
  1754. try
  1755. { 打开TRegistry }
  1756. CnDockInfoTree.DockInfoReg := TRegistry.Create;
  1757. try
  1758. IsLoading := True;
  1759. { 从注册表里读出数据并且还原停靠信息 }
  1760. CnDockInfoTree.DockInfoReg.RootKey := RootKey;
  1761. CnDockInfoTree.ReadInfoFromReg(RegPath);
  1762. finally
  1763. { 关闭TRegistry }
  1764. CnDockInfoTree.DockInfoReg.Free;
  1765. IsLoading := False;
  1766. end;
  1767. finally
  1768. { 解锁Windows桌面 }
  1769. Cn_UnLockWindow;
  1770. { 释放停靠信息树 }
  1771. CnDockInfoTree.Free;
  1772. Form.Release;
  1773. end;
  1774. ReshowAllVisibleWindow;
  1775. end;
  1776. { 设置控件的DockSite属性 }
  1777. procedure SetDockSite(Control: TWinControl; SiteValue: Boolean);
  1778. begin
  1779. TCnWinControlAccess(Control).DockSite := SiteValue;
  1780. if (not (csDesigning in Control.ComponentState)) and (CnGlobalDockPresident <> nil) then
  1781. CnGlobalDockPresident.RegisterDockSite(Control, SiteValue);
  1782. end;
  1783. { 使DockForm控件浮动,包括它上面的DockClients }
  1784. procedure DoFloatForm(DockForm: TControl);
  1785. var i, j: Integer;
  1786. ADockServer: TCnDockServer;
  1787. ARect: TRect;
  1788. begin
  1789. if (DockForm is TCnDockableForm) then
  1790. begin
  1791. {如果窗体是TCnDockableForm,就使她上面的停靠窗体浮动}
  1792. with TCnDockableForm(DockForm).DockableControl do
  1793. begin
  1794. for i := DockClientCount - 1 downto 0 do
  1795. begin
  1796. DoFloatForm(DockClients[i]);
  1797. end;
  1798. // DockForm.Hide;
  1799. DockForm.ManualDock(nil);
  1800. end;
  1801. end else
  1802. begin
  1803. ADockServer := FindDockServer(DockForm);
  1804. if ADockServer <> nil then
  1805. begin
  1806. {如果窗体上有TCnDockServer,就使她四个上面的TCnDockPanel上面的窗体浮动}
  1807. for i := 0 to 3 do
  1808. begin
  1809. for j := ADockServer.DockPanel[i].DockClientCount - 1 downto 0 do
  1810. DoFloatForm(ADockServer.DockPanel[i].DockClients[j]);
  1811. if ADockServer.DockPanel[i] is TCnVSNETDockPanel then
  1812. begin
  1813. with TCnVSNETDockPanel(ADockServer.DockPanel[i]).VSChannel do
  1814. begin
  1815. RemoveAllBlock;
  1816. HidePopupPanel(ActiveDockForm);
  1817. end;
  1818. end;
  1819. end;
  1820. end else
  1821. begin
  1822. if DockForm.HostDockSite <> nil then
  1823. begin
  1824. {如果窗体是停靠状态的,就转换坐标系}
  1825. if (DockForm.HostDockSite.Parent is TCnDockableForm) and
  1826. (DockForm.HostDockSite.DockClientCount <= 2) then
  1827. PostMessage(DockForm.HostDockSite.Parent.Handle, WM_CLOSE, 0, 0);
  1828. end else ARect := DockForm.BoundsRect;
  1829. // DockForm.Hide;
  1830. {使窗体浮动}
  1831. if DockForm.HostDockSite is TCnVSPopupPanel then
  1832. begin
  1833. TCnVSPopupPanel(DockForm.HostDockSite).VSNETDockPanel.VSChannel.RemoveDockControl(TWinControl(DockForm));
  1834. DockForm.Dock(nil, Bounds(DockForm.Left, DockForm.Top, DockForm.UndockWidth, DockForm.UndockHeight));
  1835. end else
  1836. DockForm.ManualDock(nil);
  1837. end;
  1838. end;
  1839. end;
  1840. { 删除所有无用的TCnDockableForm窗体 }
  1841. procedure FreeAllDockableForm;
  1842. var i: Integer;
  1843. begin
  1844. Assert(CnGlobalDockPresident <> nil);
  1845. for i := CnGlobalDockPresident.DockableFormList.Count - 1 downto 0 do
  1846. begin
  1847. if TCnDockableForm(CnGlobalDockPresident.DockableFormList[i]).DockableControl.DockClientCount = 0 then
  1848. TCnDockableForm(CnGlobalDockPresident.DockableFormList[i]).Free;
  1849. end;
  1850. end;
  1851. { 使应用程序的所有的窗体都浮动 }
  1852. procedure DoFloatAllForm;
  1853. var i: Integer;
  1854. TempList: TList;
  1855. begin
  1856. TempList := TList.Create;
  1857. try
  1858. for i := 0 to Screen.CustomFormCount - 1 do
  1859. begin
  1860. // 遍历整个应用程序的所有窗体,然后把一般的窗体保存到TempList中
  1861. if not (Screen.CustomForms[i] is TCnDockableForm) then
  1862. TempList.Add(Screen.CustomForms[i]);
  1863. end;
  1864. {遍历应用程序的窗口,使她们浮动}
  1865. for i := 0 to TempList.Count - 1 do
  1866. DoFloatForm(TempList[i]);
  1867. finally
  1868. TempList.Free;
  1869. end;
  1870. FreeAllDockableForm;
  1871. end;
  1872. { 得到AControl客户区中Align方向排列的子控件累加的大小到AControl边框的距离 }
  1873. function GetClientAlignControlArea(AControl: TWinControl; Align: TAlign; Exclude: TControl): Integer;
  1874. var i: Integer;
  1875. begin
  1876. Result := 0;
  1877. for i := 0 to AControl.ControlCount - 1 do
  1878. begin
  1879. if (AControl.Controls[i].Align = Align) and AControl.Controls[i].Visible and (AControl.Controls[i] <> Exclude) and
  1880. not ((AControl.Controls[i] is TCnDockSplitter) or (AControl.Controls[i] is TCnDockPanel)) then
  1881. begin
  1882. if Align in [alLeft, alRight] then
  1883. Inc(Result, AControl.Controls[i].Width)
  1884. else Inc(Result, AControl.Controls[i].Height);
  1885. end;
  1886. end;
  1887. end;
  1888. {******************************************************************************}
  1889. { 下面的函数和方法都是内部函数 }
  1890. {******************************************************************************}
  1891. function GetActiveControl(AForm: TCustomForm): TWinControl;
  1892. var AControl: TWinControl;
  1893. begin
  1894. Result := nil;
  1895. AControl := AForm.ActiveControl;
  1896. while AControl <> nil do
  1897. begin
  1898. if (AControl.HostDockSite <> nil) then
  1899. begin
  1900. Result := AControl;
  1901. Exit;
  1902. end;
  1903. AControl := AControl.Parent;
  1904. end;
  1905. end;
  1906. function GetHostDockParent(AControl: TWinControl): TWinControl;
  1907. begin
  1908. Result := nil;
  1909. while AControl <> nil do
  1910. begin
  1911. if (AControl.HostDockSite <> nil) then
  1912. begin
  1913. Result := AControl.HostDockSite;
  1914. Exit;
  1915. end;
  1916. AControl := AControl.Parent;
  1917. end;
  1918. end;
  1919. { 重新设置在Control上的TCnDockClint对象的属性 }
  1920. procedure ResetDockClient(Control: TControl; NewTarget: TControl);
  1921. begin
  1922. ResetDockClient(FindDockClient(Control), NewTarget);
  1923. end;
  1924. procedure ResetDockClient(DockClient: TCnDockClient; NewTarget: TControl);
  1925. var point: TPoint;
  1926. begin
  1927. if DockClient <> nil then
  1928. begin
  1929. if (DockClient.ParentForm.HostDockSite is TCnDockPanel) and (NewTarget is TCnDockPanel) then
  1930. begin
  1931. end else
  1932. begin
  1933. if (DockClient.LastDockSite is TCnDockPanel) and (NewTarget is TCnDockPanel) and (DockClient.LastDockSite <> NewTarget) then
  1934. begin
  1935. with TCnDockPanel(DockClient.LastDockSite) do
  1936. begin
  1937. if UseDockManager and (CnDockManager <> nil) then
  1938. CnDockManager.RemoveControl(DockClient.ParentForm);
  1939. end;
  1940. end;
  1941. if (DockClient.ParentForm.HostDockSite is TCnDockPanel) then
  1942. begin
  1943. // if (NewTarget is TCnTabPageControl) or (NewTarget is TCnConjoinPanel) then
  1944. // DockClient.LastDockSite := nil
  1945. // else
  1946. DockClient.LastDockSite := DockClient.ParentForm.HostDockSite;
  1947. end
  1948. else //if not (DockClient.LastDockSite is TCnDockPanel) then
  1949. DockClient.LastDockSite := nil;
  1950. if DockClient.ParentForm.HostDockSite = nil then
  1951. begin
  1952. DockClient.UnDockLeft := DockClient.ParentForm.BoundsRect.TopLeft.x;
  1953. DockClient.UnDockTop := DockClient.ParentForm.BoundsRect.TopLeft.y;
  1954. end else
  1955. begin
  1956. point := DockClient.ParentForm.BoundsRect.TopLeft;
  1957. point := DockClient.ParentForm.HostDockSite.ClientToScreen(point);
  1958. DockClient.UnDockLeft := point.x;
  1959. DockClient.UnDockTop := point.y;
  1960. end;
  1961. end;
  1962. end;
  1963. end;
  1964. { TCnDockPanel }
  1965. constructor TCnDockPanel.Create(AOwner: TComponent);
  1966. begin
  1967. inherited Create(AOwner);
  1968. DoubleBuffered := True;
  1969. BevelOuter := bvNone;
  1970. Width := 10;
  1971. Height := 10;
  1972. end;
  1973. destructor TCnDockPanel.Destroy;
  1974. begin
  1975. inherited Destroy;
  1976. end;
  1977. procedure TCnDockPanel.CustomDockDrop(Source: TCnDragDockObject; X,
  1978. Y: Integer);
  1979. begin
  1980. inherited CustomDockDrop(Source, X, Y);
  1981. // 如果Source.Control是TCnDockableForm,就有可能被释放掉,如果它已经被释放掉了,
  1982. // 就不要再调用ShowDockPanel函数了,不然会使TCnDockPanel宽度或者高度为0。
  1983. if Source.Control <> nil then
  1984. ShowDockPanel(True, Source.Control);
  1985. end;
  1986. procedure TCnDockPanel.CustomDockOver(Source: TCnDragDockObject; X,
  1987. Y: Integer; State: TDragState; var Accept: Boolean);
  1988. begin
  1989. Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
  1990. if Accept then
  1991. inherited CustomDockOver(Source, X, Y, State, Accept);
  1992. end;
  1993. procedure TCnDockPanel.CustomEndDock(Target: TObject; X, Y: Integer);
  1994. begin
  1995. inherited CustomEndDock(Target, X, Y);
  1996. end;
  1997. procedure TCnDockPanel.CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl;
  1998. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  1999. begin
  2000. inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock);
  2001. CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
  2002. end;
  2003. procedure TCnDockPanel.CustomPositionDockRect(Source: TCnDragDockObject; X, Y: Integer);
  2004. var
  2005. ARect: TRect;
  2006. // Tmp: Integer;
  2007. { function GetParentClientW(Control: TWinControl): Integer;
  2008. var i: Integer;
  2009. begin
  2010. Result := Control.ClientWidth;
  2011. for i := 0 to Control.ControlCount - 1 do
  2012. begin
  2013. if (Control.Controls[i].Align in [alLeft, alRight])
  2014. and (Control.Controls[i] <> Self)
  2015. and (Control.Controls[i].Visible) then
  2016. Result := Result - Control.Controls[i].Width;
  2017. end;
  2018. end;
  2019. function GetParentClientH(Control: TWinControl): Integer;
  2020. var i: Integer;
  2021. begin
  2022. Result := Control.ClientHeight;
  2023. for i := 0 to Control.ControlCount - 1 do
  2024. begin
  2025. if (Control.Controls[i].Align in [alTop, alBottom])
  2026. and (Control.Controls[i] <> Self)
  2027. and (Control.Controls[i].Visible) then
  2028. Result := Result - Control.Controls[i].Height;
  2029. end;
  2030. end;
  2031. var ParentClientW, ParentClientH: Integer;}
  2032. begin
  2033. inherited CustomPositionDockRect(Source, X, Y);
  2034. if VisibleDockClientCount = 0 then
  2035. begin
  2036. // 记住DockRect预览停靠区域.
  2037. if GlobalDockClient <> nil then
  2038. begin
  2039. case Align of
  2040. alTop:
  2041. begin
  2042. ARect.TopLeft := ClientToScreen(Point(0, 0));
  2043. ARect.BottomRight := ClientToScreen(
  2044. Point(Width, Source.Control.TBDockHeight));
  2045. end;
  2046. alBottom:
  2047. begin
  2048. ARect.TopLeft := ClientToScreen(
  2049. Point(0, -Source.Control.TBDockHeight));
  2050. ARect.BottomRight := ClientToScreen(
  2051. Point(Width, 0));
  2052. end;
  2053. alLeft:
  2054. begin
  2055. ARect.TopLeft := ClientToScreen(Point(0, 0));
  2056. ARect.BottomRight := ClientToScreen(
  2057. Point(Source.Control.LRDockWidth, Height));
  2058. end;
  2059. alRight:
  2060. begin
  2061. ARect.TopLeft := ClientToScreen(Point(-Source.Control.LRDockWidth, 0));
  2062. ARect.BottomRight := ClientToScreen(Point(Width, Height));
  2063. end;
  2064. end;
  2065. Source.DockRect := ARect;
  2066. end;
  2067. end;
  2068. end;
  2069. procedure TCnDockPanel.CustomStartDock(var Source: TCnDragDockObject);
  2070. begin
  2071. inherited CustomStartDock(Source);
  2072. end;
  2073. function TCnDockPanel.CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl;
  2074. Client: TControl): Boolean;
  2075. begin
  2076. ShowDockPanel(False, nil);
  2077. Result := inherited CustomUnDock(Source, NewTarget, Client);
  2078. if not (Client is TCnDockableForm) then
  2079. SetDockSite(TForm(Client), True);
  2080. end;
  2081. procedure TCnDockPanel.ReloadDockedControl(const AControlName: string;
  2082. var AControl: TControl);
  2083. begin
  2084. { 在整个应用程序中查找名字为AControlName的窗体 }
  2085. AControl := Cn_FindDockFormWithName(AControlName);
  2086. end;
  2087. procedure TCnDockPanel.ShowDockPanel(MakeVisible: Boolean;
  2088. Client: TControl; PanelSizeFrom: TSetDockPanelSizeFrom);
  2089. const
  2090. DefaultDockSize = 100; // 默认的宽度或者大小
  2091. var
  2092. DockHeight, DockWidth: Integer;
  2093. //Label Loop;
  2094. begin
  2095. if (not MakeVisible and (VisibleDockClientCount > 1)) or
  2096. (GlobalDockClient = nil){ or IsLoading }then Exit;
  2097. { 设置TCnDockSplitter的属性 }
  2098. DockServer.DockSplitter[Integer(Align) - 1].Visible := MakeVisible;
  2099. if (MakeVisible and (Client <> nil)) then// or ((not MakeVisible) and (Client <> nil)) then
  2100. begin
  2101. if (Width * Height = 0) then
  2102. begin
  2103. { 如果宽度和高度有一个是0 }
  2104. if (PanelSizeFrom = sdfDockPanel) or (Client = nil) then
  2105. begin
  2106. DockHeight := TBDockHeight;
  2107. DockWidth := LRDockWidth;
  2108. end else
  2109. begin
  2110. DockHeight := Client.TBDockHeight;
  2111. DockWidth := Client.LRDockWidth;
  2112. end;
  2113. { 不能等于0,不然显示会不正常 }
  2114. if DockHeight = 0 then
  2115. DockHeight := DefaultDockSize;
  2116. if DockWidth = 0 then
  2117. DockWidth := DefaultDockSize;
  2118. Parent.DisableAlign;
  2119. try
  2120. case Align of
  2121. alTop:
  2122. begin
  2123. { 如果主窗体的客户区的上边有别的控件,就把这个高度计算在内 }
  2124. Top := DockServer.GetClientAlignControl(alTop);
  2125. Height := DockHeight;
  2126. DockServer.TopSplitter.Top := Top + Height;
  2127. end;
  2128. alBottom:
  2129. begin
  2130. { 如果主窗体的客户区的下边有别的控件,就把这个高度计算在内 }
  2131. Top := Parent.ClientHeight - DockServer.GetClientAlignControl(alBottom) - DockHeight + 1;
  2132. Height := DockHeight;
  2133. DockServer.BottomSplitter.Top := Top + DockServer.BottomSplitter.Height;
  2134. end;
  2135. alLeft:
  2136. begin
  2137. { 如果主窗体的客户区的左边有别的控件,就把这个宽度计算在内 }
  2138. Left := DockServer.GetClientAlignControl(alLeft);
  2139. Width := DockWidth;
  2140. DockServer.LeftSplitter.Left := Left + Width;
  2141. end;
  2142. alRight:
  2143. begin
  2144. { 如果主窗体的客户区的右边有别的控件,就把这个宽度计算在内 }
  2145. Width := DockWidth;
  2146. Left := Parent.ClientWidth - DockServer.GetClientAlignControl(alRight) - DockWidth + 1;
  2147. DockServer.RightSplitter.Left := Left - DockServer.RightSplitter.Width;
  2148. end;
  2149. end;
  2150. finally
  2151. Parent.EnableAlign;
  2152. if UseDockManager and (CnDockManager <> nil) then
  2153. CnDockManager.ResetBounds(True);
  2154. end;
  2155. DockServer.DoFinishSetDockPanelSize(Self);
  2156. end;
  2157. end else
  2158. begin
  2159. // if (Client <> nil) and (not Client.Visible) then goto Loop;
  2160. if (PanelSizeFrom = sdfDockPanel) or (Client = nil) then
  2161. begin
  2162. if Height > 0 then
  2163. TBDockHeight := Height;
  2164. if Width > 0 then
  2165. LRDockWidth := Width;
  2166. end else
  2167. begin
  2168. if Height > 0 then
  2169. Client.TBDockHeight := Height;
  2170. if Width > 0 then
  2171. Client.LRDockWidth := Width;
  2172. end;
  2173. if Align in [alLeft, alRight] then
  2174. Width := 0
  2175. else Height := 0;
  2176. { 重新设置位置 }
  2177. ResetPosition;
  2178. end;
  2179. { 条件满足的话就显示Client }
  2180. //Loop:
  2181. if MakeVisible and (Client <> nil) then
  2182. begin
  2183. if (not Client.Visible) then
  2184. Client.Show;
  2185. if (not TWinControl(Client).Focused) and (TWinControl(Client).CanFocus) then
  2186. TWinControl(Client).SetFocus;
  2187. end;
  2188. end;
  2189. function TCnDockPanel.DoUnDock(NewTarget: TWinControl;
  2190. Client: TControl): Boolean;
  2191. begin
  2192. Result := IsDockable(Self, Client);
  2193. ShowDockPanel(False, nil);
  2194. Result := Result and (Perform(CM_UNDOCKCLIENT, Integer(NewTarget), Integer(Client)) = 0);
  2195. if Result then
  2196. begin
  2197. if not (Client is TCnDockableForm) then
  2198. SetDockSite(TForm(Client), True);
  2199. end;
  2200. end;
  2201. procedure TCnDockPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
  2202. begin
  2203. if Perform(CM_DOCKCLIENT, Integer(Source), Integer(SmallPoint(X, Y))) >= 0 then
  2204. begin
  2205. if Source.Control is TForm then
  2206. begin
  2207. TForm(Source.Control).ActiveControl := nil;
  2208. { ------------------------------------------------------------------------ }
  2209. SetDockSite(TForm(Source.Control), False);
  2210. end;
  2211. UpdateCaption(nil);
  2212. end;
  2213. ShowDockPanel(TWinControl(Source.DragTarget).VisibleDockClientCount > 0, Source.Control);
  2214. end;
  2215. function TCnDockPanel.GetPanelIndex: Integer;
  2216. begin
  2217. case Align of
  2218. alTop: Result := 0;
  2219. alBottom: Result := 1;
  2220. alLeft: Result := 2;
  2221. alRight: Result := 3;
  2222. else
  2223. Result := -1;
  2224. end;
  2225. end;
  2226. procedure TCnDockPanel.Resize;
  2227. begin
  2228. inherited;
  2229. end;
  2230. procedure TCnDockPanel.SetDockServer(const Value: TCnDockServer);
  2231. begin
  2232. FDockServer := Value;
  2233. end;
  2234. procedure TCnDockPanel.ResetPosition;
  2235. begin
  2236. { 调整TCnDockPanel的位置,使它总是在服务窗体的客户区的最内层 }
  2237. case Align of
  2238. alLeft:
  2239. Left := GetClientAlignControlArea(Parent, Align) + 1;
  2240. alRight:
  2241. Left := Parent.ClientWidth - GetClientAlignControlArea(Parent, Align) - Width - 1;
  2242. alTop:
  2243. Top := GetClientAlignControlArea(Parent, Align) + 1;
  2244. alBottom:
  2245. Top := Parent.ClientHeight - GetClientAlignControlArea(Parent, Align) - Height - 1;
  2246. end;
  2247. end;
  2248. { TCnAdvDockPanel }
  2249. //procedure TCnAdvDockPanel.CMDockClient(var Message: TCMDockClient);
  2250. //var DockClient: TCnDockClient;
  2251. //begin
  2252. { with Message do
  2253. begin
  2254. DockClient := FindDockClient(DockSource.Control);
  2255. if DockClient <> nil then
  2256. begin
  2257. if (DockClient.LastDockSite is TCnDockPanel) then
  2258. begin
  2259. with TCnDockPanel(DockClient.LastDockSite) do
  2260. begin
  2261. if UseDockManager and (CnDockManager <> nil) then
  2262. CnDockManager.RemoveControl(DockSource.Control);
  2263. end;
  2264. end else
  2265. begin
  2266. end;
  2267. end;
  2268. end;}
  2269. //end;
  2270. procedure TCnAdvDockPanel.CMUnDockClient(var Message: TCMUnDockClient);
  2271. var DockClient: TCnDockClient;
  2272. begin
  2273. if IsLoading then Exit;
  2274. with Message do
  2275. begin
  2276. Result := 0;
  2277. if UseDockManager and (CnDockManager <> nil) then
  2278. begin
  2279. DockClient := FindDockClient(Client);
  2280. if (NewTarget <> nil) or
  2281. ((Client <> nil) and (csDestroying in Client.ComponentState)) then
  2282. begin
  2283. if DockClient <> nil then
  2284. DockClient.LastDockSite := nil;
  2285. CnDockManager.RemoveControl(Client);
  2286. end else
  2287. begin
  2288. if (DockClient <> nil) then
  2289. DockClient.LastDockSite := Self;
  2290. CnDockManager.HideControl(Client);
  2291. end;
  2292. end;
  2293. end;
  2294. end;
  2295. procedure TCnAdvDockPanel.CustomDockDrop(Source: TCnDragDockObject; X,
  2296. Y: Integer);
  2297. begin
  2298. // 设置Client上的TCnDockClient控件的LastDockSite
  2299. if not IsLoading then
  2300. ResetDockClient(Source.Control, Source.TargetControl);
  2301. inherited;
  2302. end;
  2303. function TCnAdvDockPanel.CustomUnDock(Source: TCnDragDockObject;
  2304. NewTarget: TWinControl; Client: TControl): Boolean;
  2305. begin
  2306. // 设置Client上的TCnDockClient控件的LastDockSite
  2307. if not IsLoading then
  2308. ResetDockClient(Source.Control, NewTarget);
  2309. Result := inherited CustomUnDock(Source, NewTarget, Client)
  2310. end;
  2311. procedure TCnAdvDockPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
  2312. begin
  2313. // 设置Client上的TCnDockClient控件的LastDockSite
  2314. if not IsLoading then
  2315. ResetDockClient(Source.Control, TControl(Source.DragTarget));
  2316. inherited;
  2317. end;
  2318. function TCnAdvDockPanel.DoUnDock(NewTarget: TWinControl;
  2319. Client: TControl): Boolean;
  2320. begin
  2321. // 设置Client上的TCnDockClient控件的LastDockSite
  2322. if not IsLoading then
  2323. ResetDockClient(Client, NewTarget);
  2324. Result := inherited DoUnDock(NewTarget, Client);
  2325. end;
  2326. { TCnSplitterStyle }
  2327. procedure TCnSplitterStyle.Assign(Source: TPersistent);
  2328. begin
  2329. if Source is TCnSplitterStyle then
  2330. begin
  2331. Color := TCnSplitterStyle(Source).Color;
  2332. Cursor := TCnSplitterStyle(Source).Cursor;
  2333. ParentColor := TCnSplitterStyle(Source).ParentColor;
  2334. ResizeStyle := TCnSplitterStyle(Source).ResizeStyle;
  2335. Size := TCnSplitterStyle(Source).Size;
  2336. end;
  2337. inherited Assign(Source);
  2338. end;
  2339. procedure TCnSplitterStyle.AssignTo(Dest: TPersistent);
  2340. begin
  2341. if Dest is TCnSplitterStyle then
  2342. with TCnSplitterStyle(Dest) do
  2343. begin
  2344. Color := Self.Color;
  2345. Cursor := Self.Cursor;
  2346. ParentColor := Self.ParentColor;
  2347. ResizeStyle := Self.ResizeStyle;
  2348. Size := Self.Size;
  2349. end
  2350. else inherited AssignTo(Dest);
  2351. end;
  2352. procedure TCnSplitterStyle.AssignToSplitter(Dest: TCnDockSplitter);
  2353. begin
  2354. Dest.Color := Color;
  2355. Dest.Cursor := Cursor;
  2356. Dest.ParentColor := ParentColor;
  2357. Dest.ResizeStyle := ResizeStyle;
  2358. if Dest.Align in [alTop, alBottom] then
  2359. Dest.Height := Size
  2360. else Dest.Width := Size;
  2361. end;
  2362. constructor TCnSplitterStyle.Create(ASplitter: TCnDockSplitter; ACursor: TCursor);
  2363. begin
  2364. inherited Create;
  2365. FSplitter := ASplitter;
  2366. Color := clBtnFace;
  2367. Cursor := ACursor;
  2368. ParentColor := False;
  2369. ResizeStyle := rsPattern;
  2370. FSize := 3;
  2371. FMinSize := 30;
  2372. end;
  2373. procedure TCnSplitterStyle.SetColor(const Value: TColor);
  2374. begin
  2375. if FColor <> Value then
  2376. begin
  2377. FColor := Value;
  2378. ParentColor := False;
  2379. if Assigned(FSplitter) then
  2380. FSplitter.Color := Value;
  2381. end;
  2382. end;
  2383. procedure TCnSplitterStyle.SetCursor(const Value: TCursor);
  2384. begin
  2385. FCursor := Value;
  2386. if Assigned(FSplitter) then
  2387. FSplitter.Cursor := Value;
  2388. end;
  2389. procedure TCnSplitterStyle.SetMinSize(const Value: TCnSplitterSize);
  2390. begin
  2391. FMinSize := Value;
  2392. if Assigned(FSplitter) then
  2393. FSplitter.MinSize := Value;
  2394. end;
  2395. procedure TCnSplitterStyle.SetParentColor(const Value: Boolean);
  2396. begin
  2397. if FParentColor <> Value then
  2398. begin
  2399. FParentColor := Value;
  2400. if Value then FColor := FDockServer.ParentForm.Color;
  2401. if Assigned(FSplitter) then
  2402. FSplitter.ParentColor := Value;
  2403. end;
  2404. end;
  2405. procedure TCnSplitterStyle.SetResizeStyle(const Value: TResizeStyle);
  2406. begin
  2407. FResizeStyle := Value;
  2408. if Assigned(FSplitter) then
  2409. FSplitter.ResizeStyle := Value;
  2410. end;
  2411. procedure TCnSplitterStyle.SetSize(const Value: TCnSplitterSize);
  2412. begin
  2413. FSize := Value;
  2414. if Assigned(FSplitter) then
  2415. begin
  2416. if FSplitter.Align in [alTop, alBottom] then
  2417. FSplitter.Height := Value
  2418. else FSplitter.Width := Value;
  2419. end;
  2420. end;
  2421. procedure TCnSplitterStyle.SetSplitterStyle;
  2422. begin
  2423. AssignToSplitter(FSplitter);
  2424. end;
  2425. { TCnDockBaseControl }
  2426. destructor TCnDockBaseControl.Destroy;
  2427. begin
  2428. if not (csDesigning in ComponentState) then
  2429. begin
  2430. if @FOldWindowProc <> nil then
  2431. FParentForm.WindowProc := FOldWindowProc;
  2432. FOldWindowProc := nil;
  2433. if Assigned(FDockStyle) and not (FDockStyle is TCnBasicDockStyle) then
  2434. FDockStyle.SetDockBaseControl(False, Self);
  2435. end;
  2436. if FDockStyle <> nil then
  2437. FDockStyle.RemoveDockBaseControl(Self);
  2438. inherited Destroy;
  2439. end;
  2440. constructor TCnDockBaseControl.Create(AOwner: TComponent);
  2441. begin
  2442. inherited Create(AOwner);
  2443. FParentForm := TForm(AOwner);
  2444. FEnableDock := True;
  2445. FLeftDock := True;
  2446. FTopDock := True;
  2447. FRightDock := True;
  2448. FBottomDock := True;
  2449. FEachOtherDock := True;
  2450. FDockStyle := nil;
  2451. if not (csDesigning in ComponentState) then
  2452. begin
  2453. FOldOnClose := FParentForm.OnClose;
  2454. ParentForm.OnClose := DoFormOnClose;
  2455. FOldOnCreate := FParentForm.OnCreate;
  2456. ParentForm.OnCreate := DoFormOnCreate;
  2457. { 保存老的窗口过程 }
  2458. FOldWindowProc := FParentForm.WindowProc;
  2459. { 重载窗口过程 }
  2460. FParentForm.WindowProc := WindowProc;
  2461. end;
  2462. end;
  2463. procedure TCnDockBaseControl.SetBottomDock(const Value: Boolean);
  2464. begin
  2465. if CanSetBottomDocked then
  2466. FBottomDock := Value;
  2467. end;
  2468. procedure TCnDockBaseControl.SetEachotherDock(const Value: Boolean);
  2469. begin
  2470. if CanSetEachOtherDocked then
  2471. FEachotherDock := Value;
  2472. end;
  2473. procedure TCnDockBaseControl.SetEnableDock(const Value: Boolean);
  2474. begin
  2475. if CanSetEnableDocked then
  2476. FEnableDock := Value;
  2477. end;
  2478. procedure TCnDockBaseControl.SetLeftDock(const Value: Boolean);
  2479. begin
  2480. if CanSetLeftDocked then
  2481. FLeftDock := Value;
  2482. end;
  2483. procedure TCnDockBaseControl.SetRightDock(const Value: Boolean);
  2484. begin
  2485. if CanSetRightDocked then
  2486. FRightDock := Value;
  2487. end;
  2488. procedure TCnDockBaseControl.SetTopDock(const Value: Boolean);
  2489. begin
  2490. if CanSetTopDocked then
  2491. FTopDock := Value;
  2492. end;
  2493. procedure TCnDockBaseControl.Assign(Source: TPersistent);
  2494. begin
  2495. if Source is TCnDockBaseControl then
  2496. begin
  2497. FEnableDock := TCnDockBaseControl(Source).EnableDock;
  2498. FLeftDock := TCnDockBaseControl(Source).LeftDock;
  2499. FTopDock := TCnDockBaseControl(Source).TopDock;
  2500. FRightDock := TCnDockBaseControl(Source).RightDock;
  2501. FBottomDock := TCnDockBaseControl(Source).BottomDock;
  2502. FEachOtherDock := TCnDockBaseControl(Source).EachOtherDock;
  2503. FDockStyle := TCnDockBaseControl(Source).DockStyle;
  2504. if FDockStyle <> nil then
  2505. FDockStyle.AddDockBaseControl(Self);
  2506. end else inherited Assign(Source);
  2507. end;
  2508. procedure TCnDockBaseControl.SetDockStyle(const Value: TCnBasicDockStyle);
  2509. begin
  2510. { 根据原来的FDockStyle和输入的Value添加TCnDockBaseControl对象 }
  2511. if FDockStyle <> nil then
  2512. FDockStyle.RemoveDockBaseControl(Self);
  2513. if Value <> nil then
  2514. Value.AddDockBaseControl(Self);
  2515. if (csDesigning in ComponentState) or (csLoading in ComponentState) then
  2516. begin
  2517. // 当前是设计期,就修改FDockStyle的值。
  2518. if Value <> nil then
  2519. begin
  2520. Value.SetDockBaseControl(True, Self);
  2521. // 调用FreeNotification函数来使一个窗体的TCnDockBaseControl设置DockStyle
  2522. // 属性,这个DockStyle属性是另一个窗体上的控件,不会出现异常。
  2523. Value.FreeNotification(ParentForm);
  2524. end;
  2525. FDockStyle := Value;
  2526. end else
  2527. begin
  2528. // 在运行期不能设置DockStyle属性。
  2529. ShowMessage(gs_CannotChangeDockStyleProperty);
  2530. end;
  2531. end;
  2532. procedure TCnDockBaseControl.Notification(AComponent: TComponent;
  2533. Operation: TOperation);
  2534. begin
  2535. // 当DockStyle属性的控件插入或者释放的时候,会调用Notification函数。
  2536. inherited Notification(AComponent, Operation);
  2537. if Operation = opRemove then
  2538. // 如果是释放,就要把DockStyle属性设成nil。
  2539. if AComponent = FDockStyle then
  2540. begin
  2541. FDockStyle.SetDockBaseControl(False, Self);
  2542. FDockStyle := nil;
  2543. end;
  2544. end;
  2545. procedure TCnDockBaseControl.Loaded;
  2546. begin
  2547. if not (csDesigning in ComponentState) then
  2548. begin
  2549. // 默认的DockStyle属性是TCnBasicDockStyle类。
  2550. if not Assigned(DockStyle) then
  2551. DockStyle := TCnBasicDockStyle.Create(ParentForm);
  2552. if Assigned(DockStyle) then
  2553. begin
  2554. DockStyle.SetDockBaseControl(True, Self);
  2555. end;
  2556. end;
  2557. inherited Loaded;
  2558. end;
  2559. function TCnDockBaseControl.GetDockStyleVersion: string;
  2560. begin
  2561. Result := gs_CnDockManagerVersion;
  2562. end;
  2563. procedure TCnDockBaseControl.DoFormOnClose(Sender: TObject;
  2564. var Action: TCloseAction);
  2565. begin
  2566. if (Action = caFree) and (CnGlobalDockPresident <> nil) then
  2567. begin
  2568. { 把ParentForm添加到CnDockManager中 }
  2569. if Self is TCnDockServer then
  2570. CnGlobalDockPresident.RemoveDockServerFromDockManager(ParentForm)
  2571. else if Self is TCnDockClient then
  2572. CnGlobalDockPresident.RemoveDockClientFromDockManager(ParentForm);
  2573. end;
  2574. if Assigned(FOldOnClose) then
  2575. FOldOnClose(Sender, Action);
  2576. end;
  2577. procedure TCnDockBaseControl.DoFormOnCreate(Sender: TObject);
  2578. begin
  2579. if CnGlobalDockPresident <> nil then
  2580. begin
  2581. { 从CnDockManager清除ParentForm }
  2582. if Self is TCnDockServer then
  2583. CnGlobalDockPresident.AddDockServerToDockManager(ParentForm)
  2584. else if Self is TCnDockClient then
  2585. CnGlobalDockPresident.AddDockClientToDockManager(ParentForm);
  2586. end;
  2587. if Assigned(FOldOnCreate) then
  2588. FOldOnCreate(Sender);
  2589. end;
  2590. procedure TCnDockBaseControl.WindowProc(var Message: TMessage);
  2591. begin
  2592. if not (csDesigning in ComponentState) then
  2593. begin
  2594. if Assigned(FOldWindowProc) then
  2595. FOldWindowProc(Message);
  2596. end;
  2597. end;
  2598. procedure TCnDockBaseControl.SetParentComponent(Value: TComponent);
  2599. var ADockBaseControl: TCnDockBaseControl;
  2600. begin
  2601. ADockBaseControl := FindDockBaseControl(ParentForm);
  2602. if (Assigned(ADockBaseControl)) and (ADockBaseControl <> Self) then
  2603. raise EInvalidOperation.Create(Format(gs_CannotLayAnother, [ADockBaseControl.ClassName, ClassName]));
  2604. inherited SetParentComponent(Value);
  2605. end;
  2606. function TCnDockBaseControl.CanSetBottomDocked: Boolean;
  2607. begin
  2608. Result := True;
  2609. if DockStyle <> nil then
  2610. Result := DockStyle.CanSetBottomDocked(Self);
  2611. end;
  2612. function TCnDockBaseControl.CanSetEachOtherDocked: Boolean;
  2613. begin
  2614. Result := True;
  2615. if DockStyle <> nil then
  2616. Result := DockStyle.CanSetEachOtherDocked(Self);
  2617. end;
  2618. function TCnDockBaseControl.CanSetEnableDocked: Boolean;
  2619. begin
  2620. Result := True;
  2621. if DockStyle <> nil then
  2622. Result := DockStyle.CanSetEnableDocked(Self);
  2623. end;
  2624. function TCnDockBaseControl.CanSetLeftDocked: Boolean;
  2625. begin
  2626. Result := True;
  2627. if DockStyle <> nil then
  2628. Result := DockStyle.CanSetLeftDocked(Self);
  2629. end;
  2630. function TCnDockBaseControl.CanSetRightDocked: Boolean;
  2631. begin
  2632. Result := True;
  2633. if DockStyle <> nil then
  2634. Result := DockStyle.CanSetRightDocked(Self);
  2635. end;
  2636. function TCnDockBaseControl.CanSetTopDocked: Boolean;
  2637. begin
  2638. Result := True;
  2639. if DockStyle <> nil then
  2640. Result := DockStyle.CanSetTopDocked(Self);
  2641. end;
  2642. { TCnDockServer }
  2643. constructor TCnDockServer.Create(AOwner: TComponent);
  2644. begin
  2645. inherited Create(AOwner);
  2646. CreateSplitterStyle;
  2647. end;
  2648. destructor TCnDockServer.Destroy;
  2649. begin
  2650. // if not (csDesigning in ComponentState) then
  2651. // DestroyDockPanelAndSplitter;
  2652. DestroySplitterStyle;
  2653. inherited Destroy;
  2654. end;
  2655. procedure TCnDockServer.CreateDockPanelAndSplitter;
  2656. var ControlList: TList;
  2657. function CreatePanel(Align: TAlign; Name: string): TCnDockPanel;
  2658. begin
  2659. if (FDockPanelClass <> nil) and
  2660. (FDockPanelClass <> TCnDockPanelClass(ClassType)) then
  2661. begin
  2662. Result := FDockPanelClass.Create(Owner);
  2663. Result.Parent := ParentForm;
  2664. Result.Name := Name;
  2665. Result.Caption := '';
  2666. Result.Align := Align;
  2667. Result.DockServer := Self;
  2668. Result.ResetPosition;
  2669. if Align in [alTop, alBottom] then
  2670. Result.Height := 0
  2671. else
  2672. Result.Width := 0;
  2673. SetDockSite(Result, True);
  2674. { 调用DockStyle的AssignConjoinServerOption函数重新设置平铺属性 }
  2675. if DockStyle <> nil then
  2676. DockStyle.AssignConjoinServerOption(Result);
  2677. end else Result := nil;
  2678. end;
  2679. function CreateSplitter(Align: TAlign; Name: string): TCnDockSplitter;
  2680. begin
  2681. if (FDockSplitterClass <> nil) and
  2682. (FDockSplitterClass <> TCnDockSplitterClass(ClassType)) then
  2683. begin
  2684. Result := FDockSplitterClass.Create(Owner);
  2685. Result.Parent := ParentForm;
  2686. Result.Name := Name;
  2687. Result.Visible := False;
  2688. Result.Align := Align;
  2689. Result.DockServer := Self;
  2690. end else Result := nil;
  2691. end;
  2692. begin
  2693. ControlList := TList.Create;
  2694. try
  2695. FLeftDockPanel := CreatePanel(alLeft, 'LeftDockPanel_A_B_C_D_E_F_G');
  2696. FLeftSplitter := CreateSplitter(alLeft, 'LeftSplitter_A_B_C_D_E_F_G');
  2697. FRightDockPanel := CreatePanel(alRight, 'RightDockPanel_A_B_C_D_E_F_G');
  2698. FRightSplitter := CreateSplitter(alRight, 'RightSplitter_A_B_C_D_E_F_G');
  2699. FTopDockPanel := CreatePanel(alTop, 'TopDockPanel_A_B_C_D_E_F_G');
  2700. FTopSplitter := CreateSplitter(alTop, 'TopSplitter_A_B_C_D_E_F_G');
  2701. FBottomDockPanel := CreatePanel(alBottom, 'BottomDockPanel_A_B_C_D_E_F_G');
  2702. FBottomSplitter := CreateSplitter(alBottom, 'BottomSplitter_A_B_C_D_E_F_G');
  2703. finally
  2704. ControlList.Free;
  2705. end;
  2706. end;
  2707. procedure TCnDockServer.CreateSplitterStyle;
  2708. begin
  2709. FLeftSplitterStyle := TCnSplitterStyle.Create(FLeftSplitter, crHSplit);
  2710. FTopSplitterStyle := TCnSplitterStyle.Create(FTopSplitter, crVSplit);
  2711. FRightSplitterStyle := TCnSplitterStyle.Create(FRightSplitter, crHSplit);
  2712. FBottomSplitterStyle := TCnSplitterStyle.Create(FBottomSplitter, crVSplit);
  2713. FLeftSplitterStyle.FDockServer := Self;
  2714. FTopSplitterStyle.FDockServer := Self;
  2715. FRightSplitterStyle.FDockServer := Self;
  2716. FBottomSplitterStyle.FDockServer := Self;
  2717. end;
  2718. procedure TCnDockServer.DestroySplitterStyle;
  2719. begin
  2720. FLeftSplitterStyle.Free;
  2721. FTopSplitterStyle.Free;
  2722. FRightSplitterStyle.Free;
  2723. FBottomSplitterStyle.Free;
  2724. end;
  2725. procedure TCnDockServer.SetLeftSplitterStyle(
  2726. const Value: TCnSplitterStyle);
  2727. begin
  2728. FLeftSplitterStyle.Assign(Value);
  2729. end;
  2730. procedure TCnDockServer.SetTopSplitterStyle(
  2731. const Value: TCnSplitterStyle);
  2732. begin
  2733. FTopSplitterStyle.Assign(Value);
  2734. end;
  2735. procedure TCnDockServer.SetRightSplitterStyle(
  2736. const Value: TCnSplitterStyle);
  2737. begin
  2738. FRightSplitterStyle.Assign(Value);
  2739. end;
  2740. procedure TCnDockServer.SetBottomSplitterStyle(
  2741. const Value: TCnSplitterStyle);
  2742. begin
  2743. FBottomSplitterStyle.Assign(Value);
  2744. end;
  2745. procedure TCnDockServer.SetSplitterStyle;
  2746. begin
  2747. LeftSplitterStyle.Splitter := FLeftSplitter;
  2748. LeftSplitterStyle.SetSplitterStyle;
  2749. TopSplitterStyle.Splitter := FTopSplitter;
  2750. TopSplitterStyle.SetSplitterStyle;
  2751. RightSplitterStyle.Splitter := FRightSplitter;
  2752. RightSplitterStyle.SetSplitterStyle;
  2753. BottomSplitterStyle.Splitter := FBottomSplitter;
  2754. BottomSplitterStyle.SetSplitterStyle;
  2755. end;
  2756. procedure TCnDockServer.WindowProc(var Message: TMessage);
  2757. begin
  2758. { 执行FDockStyle的消息处理 }
  2759. if Assigned(FDockStyle) then
  2760. begin
  2761. if FDockStyle.DockServerWindowProc(Self, Message) then
  2762. { 如果DockStyle已经执行了消息处理,就不执行默认的处理 }
  2763. Exit;
  2764. end;
  2765. if not (csDesigning in ComponentState) then
  2766. begin
  2767. if Message.Msg = WM_ACTIVATE then
  2768. WMActivate(TWMActivate(Message));
  2769. end;
  2770. inherited WindowProc(Message);
  2771. end;
  2772. function TCnDockServer.GetDockPanel(Index: Integer): TCnDockPanel;
  2773. begin
  2774. Result := nil;
  2775. case Index of
  2776. 0: Result := FTopDockPanel;
  2777. 1: Result := FBottomDockPanel;
  2778. 2: Result := FLeftDockPanel;
  2779. 3: Result := FRightDockPanel;
  2780. end;
  2781. end;
  2782. function TCnDockServer.GetDockSplitter(Index: Integer): TCnDockSplitter;
  2783. begin
  2784. Result := nil;
  2785. case Index of
  2786. 0: Result := FTopSplitter;
  2787. 1: Result := FBottomSplitter;
  2788. 2: Result := FLeftSplitter;
  2789. 3: Result := FRightSplitter;
  2790. end;
  2791. end;
  2792. procedure TCnDockServer.SetBottomDock(const Value: Boolean);
  2793. begin
  2794. if not Value then
  2795. DoFloatDockClients(BottomDockPanel);
  2796. inherited SetBottomDock(Value);
  2797. end;
  2798. procedure TCnDockServer.SetEnableDock(const Value: Boolean);
  2799. begin
  2800. if not Value then
  2801. begin
  2802. DoFloatDockClients(TopDockPanel);
  2803. DoFloatDockClients(BottomDockPanel);
  2804. DoFloatDockClients(LeftDockPanel);
  2805. DoFloatDockClients(RightDockPanel);
  2806. end;
  2807. inherited SetEnableDock(Value);
  2808. end;
  2809. procedure TCnDockServer.SetLeftDock(const Value: Boolean);
  2810. begin
  2811. if not Value then
  2812. DoFloatDockClients(LeftDockPanel);
  2813. inherited SetLeftDock(Value);
  2814. end;
  2815. procedure TCnDockServer.SetRightDock(const Value: Boolean);
  2816. begin
  2817. if not Value then
  2818. DoFloatDockClients(RightDockPanel);
  2819. inherited SetRightDock(Value);
  2820. end;
  2821. procedure TCnDockServer.SetTopDock(const Value: Boolean);
  2822. begin
  2823. if not Value then
  2824. DoFloatDockClients(TopDockPanel);
  2825. inherited SetTopDock(Value);
  2826. end;
  2827. procedure TCnDockServer.DoFloatDockClients(DockPanel: TCnDockPanel);
  2828. var
  2829. i: Integer;
  2830. ADockClient: TCnDockClient;
  2831. begin
  2832. if not (csDesigning in ComponentState) and (DockPanel <> nil) then
  2833. begin
  2834. for i := DockPanel.DockClientCount - 1 downto 0 do
  2835. begin
  2836. ADockClient := FindDockClient(DockPanel.DockClients[i]);
  2837. if ADockClient <> nil then
  2838. ADockClient.RestoreChild;
  2839. end;
  2840. end;
  2841. end;
  2842. procedure TCnDockServer.GetComponentInfo(var AName, Author, Email, Comment: string);
  2843. begin
  2844. AName := SCnDockServerName;
  2845. Author := SCnPack_LuXiaoban;
  2846. Email := SCnPack_LuXiaobanEmail;
  2847. Comment := SCnDockServerComment;
  2848. end;
  2849. procedure TCnDockServer.Loaded;
  2850. begin
  2851. if Assigned(DockStyle) and Assigned(DockStyle.CnDockPanelClass) then
  2852. FDockPanelClass := DockStyle.CnDockPanelClass
  2853. else FDockPanelClass := DefaultDockPanelClass;
  2854. { ------------------------------------------------------------------------ }
  2855. if Assigned(DockStyle) and Assigned(DockStyle.CnDockSplitterClass) then
  2856. FDockSplitterClass := DockStyle.CnDockSplitterClass
  2857. else FDockSplitterClass := DefaultDockSplitterClass;
  2858. { ------------------------------------------------------------------------ }
  2859. if not (csDesigning in ComponentState) then
  2860. begin
  2861. CreateDockPanelAndSplitter;
  2862. SetSplitterStyle;
  2863. end;
  2864. inherited Loaded;
  2865. end;
  2866. procedure TCnDockServer.WMActivate(var Message: TWMActivate);
  2867. var i: Integer;
  2868. Control: TWinControl;
  2869. begin
  2870. if (Message.Active = WA_INACTIVE) then
  2871. begin
  2872. for i := 0 to 3 do
  2873. DockPanel[i].CnDockManager.ActiveControl := nil;
  2874. end else
  2875. begin
  2876. Control := GetActiveControl(ParentForm);
  2877. for i := 0 to 3 do
  2878. begin
  2879. if GetHostDockParent(Control) = DockPanel[i] then
  2880. begin
  2881. DockPanel[i].CnDockManager.ActiveControl := Control;
  2882. if Control.CanFocus then
  2883. Control.SetFocus;
  2884. end;
  2885. end;
  2886. end;
  2887. end;
  2888. procedure TCnDockServer.Notification(AComponent: TComponent;
  2889. Operation: TOperation);
  2890. begin
  2891. inherited Notification(AComponent, Operation);
  2892. end;
  2893. procedure TCnDockServer.DoGetClientAlignControl(Align: TAlign; var Value: Integer);
  2894. begin
  2895. if Assigned(FOnGetClientAlignSize) then
  2896. FOnGetClientAlignSize(Align, Value);
  2897. end;
  2898. procedure TCnDockServer.DoFinishSetDockPanelSize(DockPanel: TCnDockPanel);
  2899. begin
  2900. if Assigned(FOnFinishSetDockPanelSize) then
  2901. FOnFinishSetDockPanelSize(DockPanel);
  2902. end;
  2903. function TCnDockServer.GetClientAlignControl(Align: TAlign): Integer;
  2904. begin
  2905. Result := GetClientAlignControlArea(ParentForm, Align);
  2906. DoGetClientAlignControl(Align, Result);
  2907. end;
  2908. function TCnDockServer.GetDockPanelWithAlign(Index: TAlign): TCnDockPanel;
  2909. begin
  2910. Result := nil;
  2911. case Index of
  2912. alLeft: Result := FLeftDockPanel;
  2913. alRight: Result := FRightDockPanel;
  2914. alTop: Result := FTopDockPanel;
  2915. alBottom: Result := FBottomDockPanel;
  2916. end;
  2917. end;
  2918. function TCnDockServer.GetDockSplitterWithAlign(
  2919. Index: TAlign): TCnDockSplitter;
  2920. begin
  2921. Result := nil;
  2922. case Index of
  2923. alLeft: Result := FLeftSplitter;
  2924. alRight: Result := FRightSplitter;
  2925. alTop: Result := FTopSplitter;
  2926. alBottom: Result := FBottomSplitter;
  2927. end;
  2928. end;
  2929. { TCnDockClient }
  2930. constructor TCnDockClient.Create(AOwner: TComponent);
  2931. begin
  2932. inherited Create(AOwner);
  2933. FParentVisible := ParentForm.Visible;
  2934. ParentForm.DragKind := dkDock;
  2935. ParentForm.DragMode := dmAutomatic;
  2936. ParentForm.UseDockManager := False;
  2937. if not (ParentForm is TCnDockableForm) then
  2938. SetDockSite(ParentForm, True);
  2939. LRDockWidth := 100;
  2940. TBDockHeight := 100;
  2941. if GlobalDockClient = nil then
  2942. GlobalDockClient := Self;
  2943. FDirectDrag := False;
  2944. FShowHint := True;
  2945. FCanFloat := True;
  2946. FRelativeServer := nil;
  2947. FDockLevel := 0;
  2948. EnableCloseBtn := True;
  2949. end;
  2950. destructor TCnDockClient.Destroy;
  2951. begin
  2952. if not (ParentForm is TCnDockableForm) then
  2953. SetDockSite(ParentForm, False);
  2954. ParentForm.DragKind := dkDrag;
  2955. ParentForm.DragMode := dmManual;
  2956. inherited Destroy;
  2957. end;
  2958. procedure TCnDockClient.Assign(Source: TPersistent);
  2959. begin
  2960. if Source is TCnDockClient then
  2961. begin
  2962. FConjoinPanelClass := TCnDockClient(Source).FConjoinPanelClass;
  2963. FTabDockClass := TCnDockClient(Source).FTabDockClass;
  2964. FParentVisible := TCnDockClient(Source).FParentVisible;
  2965. FNCPopupMenu := TCnDockClient(Source).FNCPopupMenu;
  2966. FDirectDrag := TCnDockClient(Source).FDirectDrag;
  2967. FShowHint := TCnDockClient(Source).FShowHint;
  2968. FCanFloat := TCnDockClient(Source).FCanFloat;
  2969. FRelativeServer := TCnDockClient(Source).FRelativeServer;
  2970. FDockLevel := TCnDockClient(Source).DockLevel;
  2971. end;
  2972. inherited Assign(Source);
  2973. end;
  2974. procedure TCnDockClient.WindowProc(var Message: TMessage);
  2975. var OldOrient: TDockOrientation;
  2976. begin
  2977. { 执行FDockStyle的消息处理 }
  2978. if Assigned(FDockStyle) then
  2979. begin
  2980. if FDockStyle.DockClientWindowProc(Self, Message) then
  2981. { 如果DockStyle已经执行了消息处理,就不执行默认的处理 }
  2982. Exit;
  2983. end;
  2984. if not (csDesigning in ComponentState) then
  2985. begin
  2986. case Message.Msg of
  2987. CM_SHOWINGCHANGED:
  2988. begin
  2989. { 在WinXP中,当在装载的时候,会出现闪烁,在这里把显示改变的消息捕获掉。
  2990. 在98或者2000中是没有这种情况的,因为已经调用了LockWindowUpdate函数,
  2991. 但是在XP下面不知道是什么原因,还是会出现这种闪烁的情况,没办法,只能
  2992. 在装载的时候先过滤掉CM_SHOWINGCHANGED消息,然后在装载的最后把应该显示
  2993. 但是没有显示的客户窗体显示出来。}
  2994. if IsWinXP and IsLoading then
  2995. Exit;
  2996. end;
  2997. WM_NCLBUTTONDOWN:
  2998. begin
  2999. // 如果捕获到WM_NCLBUTTONDOWN消息,就调用WMNCLButtonDown函数。
  3000. WMNCLButtonDown(TWMNCHitMessage(Message));
  3001. if (Message.Result = 1) then
  3002. Exit;
  3003. end;
  3004. WM_NCLBUTTONUP:
  3005. WMNCLButtonUp(TWMNCHitMessage(Message));
  3006. WM_NCLBUTTONDBLCLK:
  3007. WMNCLButtonDblClk(TWMNCHitMessage(Message));
  3008. WM_NCMBUTTONDOWN:
  3009. WMNCMButtonDown(TWMNCHitMessage(Message));
  3010. WM_NCMBUTTONUP:
  3011. WMNCMButtonUp(TWMNCHitMessage(Message));
  3012. WM_NCMBUTTONDBLCLK:
  3013. WMNCMButtonDblClk(TWMNCHitMessage(Message));
  3014. WM_NCRBUTTONDOWN:
  3015. begin
  3016. WMNCRButtonDown(TWMNCHitMessage(Message));
  3017. { 如果有自定义的弹出菜单,就不要调用系统默认的弹出菜单,
  3018. 要实现这个功能,只要不把这个消息发送给Windows就可以办到。 }
  3019. if FNCPopupMenu <> nil then
  3020. Exit;
  3021. end;
  3022. WM_NCRBUTTONUP:
  3023. WMNCRButtonUp(TWMNCHitMessage(Message));
  3024. WM_NCRBUTTONDBLCLK:
  3025. WMNCRButtonDblClk(TWMNCHitMessage(Message));
  3026. WM_NCMOUSEMOVE:
  3027. WMNCMOUSEMOVE(TWMNCHitMessage(Message));
  3028. WM_SIZE:
  3029. WMSize(TWMSize(Message));
  3030. WM_ACTIVATE:
  3031. WMActivate(TWMActivate(Message));
  3032. WM_WINDOWPOSCHANGED:
  3033. begin
  3034. //下面一条代码的作用是使TControl.CalcDockSizes方法失效,
  3035. //请参看Controls.pas文件中的4462--4466行(D5版本),或者4816--4820行(D6版本)
  3036. ParentForm.ControlState := ParentForm.ControlState + [csDocking];
  3037. OldOrient := ParentForm.DockOrientation;
  3038. ParentForm.DockOrientation := doNoOrient;
  3039. try
  3040. inherited WindowProc(Message);
  3041. finally
  3042. ParentForm.ControlState := ParentForm.ControlState - [csDocking];
  3043. ParentForm.DockOrientation := OldOrient;
  3044. end;
  3045. Exit;
  3046. end;
  3047. CM_ENTER:
  3048. Activate;
  3049. CM_EXIT:
  3050. Deactivate;
  3051. CM_VISIBLECHANGED:
  3052. CMVisibleChanged(Message);
  3053. end;
  3054. end;
  3055. inherited WindowProc(Message);
  3056. end;
  3057. { 创建平铺的服务窗体并且把控件停靠进去 }
  3058. function TCnDockClient.CreateConjoinHostAndDockControl(
  3059. Control1, Control2: TControl; DockType: TAlign): TCnConjoinDockHostForm;
  3060. var APanel: TCnConjoinPanel;
  3061. OldDockWidth, OldDockHeight: Integer;
  3062. begin
  3063. { 创建一个TCnConjoinDockHostForm窗体作为TCnConjoinPanel的Parent }
  3064. Result := TCnConjoinDockHostForm.Create(Application);
  3065. { 创建一个TCnConjoinPanel,并且把它放在Result上 }
  3066. APanel := CreateConjoinPanelClass(Result);
  3067. { Result的位置大小和Control1的相同,所以在调用CreateConjoinHostAndDockControl
  3068. 的时候要注意:Control1为停靠目标窗体,Control2为停靠源窗体 }
  3069. Result.BoundsRect := Control1.BoundsRect;
  3070. { 调整Result的宽度和高度为UndockWidth和UndockHeight }
  3071. Result.Width := Control1.UndockWidth;
  3072. Result.Height := Control1.UndockHeight;
  3073. { 分别把Control1和Control2停靠进APage }
  3074. OldDockWidth := Control1.LRDockWidth;
  3075. OldDockHeight := Control1.TBDockHeight;
  3076. Control1.ManualDock(APanel, nil, alNone);
  3077. Control1.LRDockWidth := OldDockWidth;
  3078. Control1.TBDockHeight := OldDockHeight;
  3079. {============================================================================}
  3080. OldDockWidth := Control2.LRDockWidth;
  3081. OldDockHeight := Control2.TBDockHeight;
  3082. Control2.ManualDock(APanel, nil, DockType);
  3083. Control2.LRDockWidth := OldDockWidth;
  3084. Control2.TBDockHeight := OldDockHeight;
  3085. { 把Result的DockSite属性设置成False }
  3086. SetDockSite(Result, False);
  3087. end;
  3088. { 创建分页的服务窗体并且把控件停靠进去 }
  3089. function TCnDockClient.CreateTabHostAndDockControl(
  3090. Control1, Control2: TControl): TCnTabDockHostForm;
  3091. var APage: TCnTabPageControl;
  3092. OldDockWidth, OldDockHeight: Integer;
  3093. begin
  3094. { 创建一个TCnTabDockHostForm窗体作为TCnTabPageControl的Parent }
  3095. Result := TCnTabDockHostForm.Create(Application);
  3096. { 创建一个TCnTabPageControl,并且把它放在Result上 }
  3097. APage := CreateTabDockClass(Result);
  3098. { Result的位置大小和Control1的相同,所以在调用CreateTabHostAndDockControl
  3099. 的时候要注意:Control1为停靠目标窗体,Control2为停靠源窗体 }
  3100. Result.BoundsRect := Control1.BoundsRect;
  3101. { 调整Result的宽度和高度为UndockWidth和UndockHeight }
  3102. Result.Width := Control1.UndockWidth;
  3103. Result.Height := Control1.UndockHeight;
  3104. { 分别把Control1和Control2停靠进APage }
  3105. OldDockWidth := Control1.LRDockWidth;
  3106. OldDockHeight := Control1.TBDockHeight;
  3107. Control1.ManualDock(APage, nil, alClient);
  3108. Control1.LRDockWidth := OldDockWidth;
  3109. Control1.TBDockHeight := OldDockHeight;
  3110. {============================================================================}
  3111. OldDockWidth := Control2.LRDockWidth;
  3112. OldDockHeight := Control2.TBDockHeight;
  3113. Control2.ManualDock(APage, nil, alClient);
  3114. Control2.LRDockWidth := OldDockWidth;
  3115. Control2.TBDockHeight := OldDockHeight;
  3116. { 把Result的DockSite属性设置成False }
  3117. SetDockSite(Result, False);
  3118. end;
  3119. procedure TCnDockClient.MakeHideEvent;
  3120. begin
  3121. ParentVisible := False;
  3122. if Assigned(FOnFormHide) then
  3123. FOnFormHide(Self);
  3124. end;
  3125. procedure TCnDockClient.MakeShowEvent;
  3126. begin
  3127. if {(not ParentVisible) and }ParentForm.Visible then
  3128. begin
  3129. if Assigned(FOnFormShow) then
  3130. FOnFormShow(Self);
  3131. ParentVisible := True;
  3132. end;
  3133. end;
  3134. procedure TCnDockClient.SetParentVisible(const Value: Boolean);
  3135. begin
  3136. FParentVisible := Value;
  3137. end;
  3138. procedure TCnDockClient.DoFloatDockClients(PanelAlign: TAlign);
  3139. begin
  3140. if (ParentForm.HostDockSite is TCnDockPanel) and
  3141. (PanelAlign = ParentForm.HostDockSite.Align) then
  3142. RestoreChild;
  3143. end;
  3144. procedure TCnDockClient.SetBottomDock(const Value: Boolean);
  3145. begin
  3146. if not Value then
  3147. DoFloatDockClients(alBottom);
  3148. inherited SetBottomDock(Value);
  3149. end;
  3150. procedure TCnDockClient.SetEachotherDock(const Value: Boolean);
  3151. begin
  3152. if not Value then
  3153. DoFloatDockEachOther;
  3154. inherited SetEachotherDock(Value);
  3155. end;
  3156. procedure TCnDockClient.SetEnableDock(const Value: Boolean);
  3157. begin
  3158. if not Value then
  3159. begin
  3160. DoFloatDockClients(alTop);
  3161. DoFloatDockClients(alBottom);
  3162. DoFloatDockClients(alLeft);
  3163. DoFloatDockClients(alRight);
  3164. DoFloatDockEachOther;
  3165. end;
  3166. if ParentForm <> nil then
  3167. begin
  3168. if Value then
  3169. ParentForm.DragKind := dkDock
  3170. else
  3171. ParentForm.DragKind := dkDrag;
  3172. end;
  3173. inherited SetEnableDock(Value);
  3174. end;
  3175. procedure TCnDockClient.SetLeftDock(const Value: Boolean);
  3176. begin
  3177. if not Value then
  3178. DoFloatDockClients(alLeft);
  3179. inherited SetLeftDock(Value);
  3180. end;
  3181. procedure TCnDockClient.SetRightDock(const Value: Boolean);
  3182. begin
  3183. if not Value then
  3184. DoFloatDockClients(alRight);
  3185. inherited SetRightDock(Value);
  3186. end;
  3187. procedure TCnDockClient.SetTopDock(const Value: Boolean);
  3188. begin
  3189. if not Value then
  3190. DoFloatDockClients(alTop);
  3191. inherited SetTopDock(Value);
  3192. end;
  3193. procedure TCnDockClient.DoFloatDockEachOther;
  3194. begin
  3195. if (ParentForm.HostDockSite <> nil) and
  3196. (ParentForm.HostDockSite.Parent is TCnDockableForm) then
  3197. RestoreChild;
  3198. end;
  3199. procedure TCnDockClient.WMSize(var Message: TWMSize);
  3200. begin
  3201. { if (ParentForm.HostDockSite <> nil) and (Message.Width * Message.Height <> 0) then
  3202. begin
  3203. if ParentForm.DockOrientation = doVertical then // 垂直
  3204. ParentForm.LRDockWidth := Message.Width
  3205. else if ParentForm.DockOrientation = doHorizontal then
  3206. ParentForm.TBDockHeight := Message.Height
  3207. else
  3208. begin
  3209. if (ParentForm.HostDockSite is TCnDockPanel) and
  3210. (ParentForm.HostDockSite.FindChildControl(ParentForm.Name) <> nil) then
  3211. begin
  3212. if ParentForm.HostDockSite.Align in [alLeft, alRight] then
  3213. ParentForm.LRDockWidth := Message.Width
  3214. else
  3215. ParentForm.TBDockHeight := Message.Height;
  3216. end;
  3217. end;
  3218. end;}
  3219. inherited;
  3220. end;
  3221. procedure TCnDockClient.GetComponentInfo(var AName, Author, Email, Comment: string);
  3222. begin
  3223. AName := SCnDockClientName;
  3224. Author := SCnPack_LuXiaoban;
  3225. Email := SCnPack_LuXiaobanEmail;
  3226. Comment := SCnDockClientComment;
  3227. end;
  3228. procedure TCnDockClient.Loaded;
  3229. begin
  3230. { 设置FConjoinPanelClass }
  3231. if Assigned(DockStyle) and Assigned(DockStyle.CnConjoinPanelClass) then
  3232. FConjoinPanelClass := DockStyle.CnConjoinPanelClass
  3233. else FConjoinPanelClass := DefaultConjoinPanelClass;
  3234. { 设置FTabDockClass }
  3235. if Assigned(DockStyle) and Assigned(DockStyle.CnTabDockClass) then
  3236. FTabDockClass := DockStyle.CnTabDockClass
  3237. else FTabDockClass := DefaultTabDockClass;
  3238. inherited Loaded;
  3239. end;
  3240. function TCnDockClient.CreateConjoinPanelClass(
  3241. ConjoinHost: TForm): TCnConjoinPanel;
  3242. begin
  3243. Result := nil;
  3244. TCnConjoinDockHostForm(ConjoinHost).DockClient.Assign(Self);
  3245. if (FConjoinPanelClass <> nil) and
  3246. (FConjoinPanelClass <> TCnConjoinPanelClass(ClassType)) then
  3247. begin
  3248. Result := FConjoinPanelClass.Create(ConjoinHost);
  3249. Result.Align := alClient;
  3250. TCnConjoinDockHostForm(ConjoinHost).DockableControl := Result;
  3251. TCnConjoinDockHostForm(ConjoinHost).Panel := Result;
  3252. SetDockSite(Result, True);
  3253. { 调用DockStyle.AssignConjoinServerOption来设置一些在DockStyle中设置的属性 }
  3254. DockStyle.AssignConjoinServerOption(TCnConjoinDockHostForm(ConjoinHost).Panel);
  3255. end;
  3256. end;
  3257. function TCnDockClient.CreateTabDockClass(
  3258. TabHost: TForm): TCnTabPageControl;
  3259. begin
  3260. Result := nil;
  3261. TCnTabDockHostForm(TabHost).DockClient.Assign(Self);
  3262. if (FTabDockClass <> nil) and
  3263. (FTabDockClass <> TCnTabDockClass(ClassType)) then
  3264. begin
  3265. Result := FTabDockClass.Create(TabHost);
  3266. Result.Align := alClient;
  3267. TCnTabDockHostForm(TabHost).DockableControl := Result;
  3268. TCnTabDockHostForm(TabHost).PageControl := Result;
  3269. SetDockSite(Result, True);
  3270. { 调用DockStyle.AssignTabServerOption来设置一些在DockStyle中设置的属性 }
  3271. DockStyle.AssignTabServerOption(TCnTabDockHostForm(TabHost).PageControl);
  3272. end;
  3273. end;
  3274. procedure TCnDockClient.WMActivate(var Message: TWMActivate);
  3275. begin
  3276. if (ParentForm is TCnConjoinDockHostForm) then
  3277. begin
  3278. if (Message.Active = WA_INACTIVE) then
  3279. TCnConjoinPanel(TCnConjoinDockHostForm(ParentForm).Panel).CnDockManager.ActiveControl := nil
  3280. else
  3281. begin
  3282. TCnConjoinPanel(TCnConjoinDockHostForm(ParentForm).Panel).CnDockManager.ActiveControl :=
  3283. GetActiveControl(ParentForm);
  3284. end;
  3285. end;
  3286. end;
  3287. procedure TCnDockClient.Activate;
  3288. begin
  3289. if ParentForm.HostDockSite is TCnCustomDockPanel then
  3290. begin
  3291. TCnCustomDockPanel(
  3292. ParentForm.HostDockSite).CnDockManager.ActiveControl := ParentForm;
  3293. end;
  3294. end;
  3295. procedure TCnDockClient.Deactivate;
  3296. begin
  3297. if ParentForm.HostDockSite is TCnCustomDockPanel then
  3298. begin
  3299. if TCnCustomDockPanel(ParentForm.HostDockSite).CnDockManager <> nil then
  3300. TCnCustomDockPanel(ParentForm.HostDockSite).CnDockManager.ActiveControl := nil;
  3301. end;
  3302. end;
  3303. procedure TCnDockClient.DoFormOnClose(Sender: TObject;
  3304. var Action: TCloseAction);
  3305. begin
  3306. if Action = caHide then
  3307. begin
  3308. HideDockForm(ParentForm);
  3309. FParentVisible := True;
  3310. end;
  3311. end;
  3312. procedure TCnDockClient.FormDockDrop(Source: TCnDragDockObject; X,
  3313. Y: Integer);
  3314. begin
  3315. if Assigned(DockStyle) then
  3316. DockStyle.FormDockDrop(Self, Source, X, Y);
  3317. end;
  3318. procedure TCnDockClient.FormDockOver(Source: TCnDragDockObject; X,
  3319. Y: Integer; State: TDragState; var Accept: Boolean);
  3320. begin
  3321. FormPositionDockRect(Source);
  3322. if Assigned(DockStyle) then
  3323. DockStyle.FormDockOver(Self, Source, X, Y, State, Accept);
  3324. end;
  3325. procedure TCnDockClient.FormEndDock(Target: TObject; X, Y: Integer);
  3326. begin
  3327. if Assigned(DockStyle) then
  3328. DockStyle.FormEndDock(Self, Target, X, Y);
  3329. end;
  3330. procedure TCnDockClient.FormPositionDockRect(Source: TCnDragDockObject);
  3331. begin
  3332. if Assigned(DockStyle) then
  3333. DockStyle.FormPositionDockRect(Self, Source);
  3334. end;
  3335. procedure TCnDockClient.FormStartDock(var Source: TCnDragDockObject);
  3336. begin
  3337. if Assigned(DockStyle) then
  3338. DockStyle.FormStartDock(Self, Source);
  3339. end;
  3340. function TCnDockClient.FormUnDock(NewTarget: TWinControl;
  3341. Client: TControl): Boolean;
  3342. begin
  3343. if Assigned(DockStyle) then
  3344. Result := DockStyle.FormUnDock(Self, Newtarget, Client)
  3345. else Result := False;
  3346. end;
  3347. procedure TCnDockClient.FormGetSiteInfo(Source: TCnDragDockObject; Client: TControl;
  3348. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  3349. begin
  3350. GetWindowRect(ParentForm.Handle, InfluenceRect);
  3351. InflateRect(InfluenceRect, -4, -4);
  3352. if Assigned(DockStyle) then
  3353. DockStyle.FormGetSiteInfo(Source, Self, Client, InfluenceRect, MousePos, CanDock);
  3354. end;
  3355. function TCnDockClient.GetLRDockWidth: Integer;
  3356. begin
  3357. Result := ParentForm.LRDockWidth;
  3358. end;
  3359. function TCnDockClient.GetTBDockHeight: Integer;
  3360. begin
  3361. Result := ParentForm.TBDockHeight;
  3362. end;
  3363. procedure TCnDockClient.SetLRDockWidth(const Value: Integer);
  3364. begin
  3365. if ParentForm.LRDockWidth <> Value then
  3366. ParentForm.LRDockWidth := Value;
  3367. end;
  3368. procedure TCnDockClient.SetTBDockHeight(const Value: Integer);
  3369. begin
  3370. if ParentForm.TBDockHeight <> Value then
  3371. ParentForm.TBDockHeight := Value;
  3372. end;
  3373. procedure TCnDockClient.DoNCButtonDown(Message: TWMNCHitMessage;
  3374. Button: TMouseButton; MouseStation: TMouseStation);
  3375. begin
  3376. if Assigned(FOnNCButtonDown) then
  3377. FOnNCButtonDown(Self, Button, Message.XCursor, Message.YCursor,
  3378. Message.HitTest, MouseStation);
  3379. end;
  3380. procedure TCnDockClient.DoNCButtonUp(Message: TWMNCHitMessage;
  3381. Button: TMouseButton; MouseStation: TMouseStation);
  3382. begin
  3383. if Assigned(FOnNCButtonUp) then
  3384. FOnNCButtonUp(Self, Button, Message.XCursor, Message.YCursor,
  3385. Message.HitTest, MouseStation);
  3386. if Button = mbRight then
  3387. { 如果是鼠标右键,就弹出菜单 }
  3388. DoMenuPopup(Message.XCursor, Message.YCursor);
  3389. end;
  3390. procedure TCnDockClient.DoNCMouseMove(Message: TWMNCHitMessage;
  3391. MouseStation: TMouseStation);
  3392. begin
  3393. if Assigned(FOnNCMouseMove) then
  3394. FOnNCMouseMove(Self, Message.XCursor, Message.YCursor,
  3395. Message.HitTest, MouseStation);
  3396. end;
  3397. procedure TCnDockClient.DoNCButtonDblClk(Message: TWMNCHitMessage; Button: TMouseButton;
  3398. MouseStation: TMouseStation);
  3399. begin
  3400. if Assigned(FOnNCButtonDblClk) then
  3401. FOnNCButtonDblClk(Self, Button, Message.XCursor, Message.YCursor,
  3402. Message.HitTest, MouseStation);
  3403. end;
  3404. procedure TCnDockClient.WMNCLButtonDown(var Message: TWMNCHitMessage);
  3405. begin
  3406. DoNCButtonDown(Message, mbLeft, msFloat);
  3407. GlobalDockClient := Self;
  3408. if (Message.HitTest = HTCAPTION) and (ParentForm.DragKind = dkDock) and not
  3409. (csDesigning in ComponentState) and not IsIconic(ParentForm.Handle) then
  3410. begin
  3411. { Activate window since we override WM_NCLBUTTON behavior }
  3412. SetWindowPos(ParentForm.Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or SWP_NOMOVE or
  3413. SWP_NOSIZE);
  3414. PostMessage(ParentForm.Handle, WM_NCLBUTTONUP, TMessage(Message).WParam,
  3415. TMessage(Message).LParam);
  3416. if ParentForm.Active then
  3417. CnGlobalDockPresident.BeginDrag(ParentForm, DirectDrag, Integer(DirectDrag) * 2 - 1);
  3418. Message.Result := 1;
  3419. end else
  3420. Message.Result := 0;
  3421. end;
  3422. procedure TCnDockClient.WMNCLButtonUp(var Message: TWMNCHitMessage);
  3423. begin
  3424. DoNCButtonUp(Message, mbLeft, msFloat);
  3425. end;
  3426. procedure TCnDockClient.WMNCMButtonDown(var Message: TWMNCHitMessage);
  3427. begin
  3428. DoNCButtonDown(Message, mbMiddle, msFloat);
  3429. end;
  3430. procedure TCnDockClient.WMNCMButtonUp(var Message: TWMNCHitMessage);
  3431. begin
  3432. DoNCButtonUp(Message, mbMiddle, msFloat);
  3433. end;
  3434. procedure TCnDockClient.WMNCRButtonDown(var Message: TWMNCHitMessage);
  3435. begin
  3436. DoNCButtonDown(Message, mbRight, msFloat);
  3437. end;
  3438. procedure TCnDockClient.WMNCRButtonUp(var Message: TWMNCHitMessage);
  3439. begin
  3440. DoNCButtonUp(Message, mbRight, msFloat);
  3441. end;
  3442. procedure TCnDockClient.WMNCMOUSEMOVE(var Message: TWMNCHitMessage);
  3443. begin
  3444. DoNCMouseMove(Message, msFloat);
  3445. end;
  3446. procedure TCnDockClient.WMNCLButtonDblClk(var Message: TWMNCHitMessage);
  3447. begin
  3448. DoNCButtonDblClk(Message, mbLeft, msFloat);
  3449. end;
  3450. procedure TCnDockClient.WMNCMButtonDblClk(var Message: TWMNCHitMessage);
  3451. begin
  3452. DoNCButtonDblClk(Message, mbMiddle, msFloat);
  3453. end;
  3454. procedure TCnDockClient.WMNCRButtonDblClk(var Message: TWMNCHitMessage);
  3455. begin
  3456. DoNCButtonDblClk(Message, mbRight, msFloat);
  3457. end;
  3458. procedure TCnDockClient.SetNCPopupMenu(const Value: TPopupMenu);
  3459. begin
  3460. FNCPopupMenu := Value;
  3461. end;
  3462. procedure TCnDockClient.DoMenuPopup(X, Y: Integer);
  3463. begin
  3464. if FNCPopupMenu <> nil then
  3465. begin
  3466. FNCPopupMenu.PopupComponent := ParentForm;
  3467. FNCPopupMenu.Popup(X, Y);
  3468. end;
  3469. end;
  3470. procedure TCnDockClient.DoPaintDockGrabber(
  3471. Canvas: TCanvas; Control: TControl; const ARect: TRect);
  3472. begin
  3473. if Assigned(FOnPaintDockGrabber) then
  3474. FOnPaintDockGrabber(Canvas, Control, ARect);
  3475. end;
  3476. procedure TCnDockClient.DoPaintDockSplitter(Canvas: TCanvas;
  3477. Control: TControl; const ARect: TRect);
  3478. begin
  3479. if Assigned(FOnPaintDockSplitter) then
  3480. FOnPaintDockSplitter(Canvas, Control, ARect);
  3481. end;
  3482. procedure TCnDockClient.FormGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign);
  3483. begin
  3484. if Assigned(DockStyle) then
  3485. DockStyle.FormGetDockEdge(Self, Source, MousePos, DropAlign)
  3486. else DropAlign := alNone;
  3487. end;
  3488. procedure TCnDockClient.DoFormShowHint(HTFlag: Integer; var HintStr: string;
  3489. var CanShow: Boolean);
  3490. begin
  3491. if Assigned(FOnFormShowHint) then
  3492. FOnFormShowHint(HTFlag, HintStr, CanShow);
  3493. end;
  3494. procedure TCnDockClient.SetCurrentDockSite(const Value: TWinControl);
  3495. begin
  3496. FCurrentDockSite := Value;
  3497. end;
  3498. procedure TCnDockClient.SetLastDockSite(const Value: TWinControl);
  3499. begin
  3500. FLastDockSite := Value;
  3501. end;
  3502. procedure TCnDockClient.SetVSPaneWidth(const Value: Integer);
  3503. begin
  3504. FVSPaneWidth := Value;
  3505. end;
  3506. procedure TCnDockClient.RestoreChild;
  3507. begin
  3508. DockStyle.RestoreClient(Self);
  3509. end;
  3510. procedure TCnDockClient.SetUnDockLeft(const Value: Integer);
  3511. begin
  3512. FUnDockLeft := Value;
  3513. end;
  3514. procedure TCnDockClient.SetUnDockTop(const Value: Integer);
  3515. begin
  3516. FUnDockTop := Value;
  3517. end;
  3518. procedure TCnDockClient.HideParentForm;
  3519. begin
  3520. HideDockForm(ParentForm);
  3521. end;
  3522. procedure TCnDockClient.ShowParentForm;
  3523. begin
  3524. ShowDockForm(ParentForm);
  3525. end;
  3526. function TCnDockClient.GetDockState: Integer;
  3527. begin
  3528. Result := DS_Unknow;
  3529. if DockStyle <> nil then
  3530. Result := DockStyle.GetDockState(Self);
  3531. end;
  3532. procedure TCnDockClient.CMVisibleChanged(var Message: TMessage);
  3533. begin
  3534. end;
  3535. procedure TCnDockClient.SetCanFloat(const Value: Boolean);
  3536. begin
  3537. FCanFloat := Value;
  3538. end;
  3539. procedure TCnDockClient.SetRelativeServer(const Value: TCnDockServer);
  3540. begin
  3541. if (csDesigning in ComponentState){ or (csLoading in ComponentState) }then
  3542. begin
  3543. if Value <> nil then
  3544. Value.FreeNotification(ParentForm);
  3545. end;
  3546. FRelativeServer := Value;
  3547. end;
  3548. procedure TCnDockClient.Notification(AComponent: TComponent;
  3549. Operation: TOperation);
  3550. begin
  3551. inherited;
  3552. if (Operation = opRemove) and (AComponent = FRelativeServer) then
  3553. // 如果是释放,就要把FRelativeServer属性设成nil。
  3554. FRelativeServer := nil;
  3555. end;
  3556. procedure TCnDockClient.SetDockLevel(const Value: Integer);
  3557. begin
  3558. if not ParentForm.Floating then
  3559. begin
  3560. if FDockLevel <> Value then
  3561. DoFloatForm(ParentForm);
  3562. end;
  3563. FDockLevel := Value;
  3564. end;
  3565. procedure TCnDockClient.SetEnableCloseBtn(const Value: Boolean);
  3566. begin
  3567. FEnableCloseBtn := Value;
  3568. end;
  3569. { TCnDockableForm }
  3570. constructor TCnDockableForm.Create(AOwner: TComponent);
  3571. begin
  3572. inherited Create(AOwner);
  3573. DragKind := dkDock;
  3574. FDockClient := TCnDockClient.Create(self);
  3575. CnGlobalDockPresident.DockableFormList.Add(Self);
  3576. FFloatingChild := nil;
  3577. TBDockHeight := FDockClient.TBDockHeight;
  3578. LRDockWidth := FDockClient.LRDockWidth;
  3579. end;
  3580. destructor TCnDockableForm.Destroy;
  3581. var Index: Integer;
  3582. begin
  3583. if CnGlobalDockPresident <> nil then
  3584. begin
  3585. Index := CnGlobalDockPresident.DockableFormList.IndexOf(Self);
  3586. if Index <> -1 then
  3587. CnGlobalDockPresident.DockableFormList.Delete(Index);
  3588. end;
  3589. if DockClient.LastDockSite is TCnDockPanel then
  3590. TCnDockPanel(DockClient.LastDockSite).CnDockManager.RemoveControl(Self);
  3591. inherited Destroy;
  3592. FFloatingChild := nil;
  3593. end;
  3594. procedure TCnDockableForm.DoClose(var Action: TCloseAction);
  3595. var i: Integer;
  3596. begin
  3597. if DockableControl.DockClientCount = 1 then
  3598. begin
  3599. { 保存这个客户,可能以后还要重新停靠到服务器上面 }
  3600. FFloatingChild := DockableControl.DockClients[0];
  3601. { 如果HostDockSite不为空,说明以后要把它停靠到服务器上面,为了防止闪烁,先把
  3602. FFloatingChild隐藏掉,然后等到重新停靠后再显示出来,就可以防止闪烁,显示的
  3603. 函数见CnDockSupportControl.pas的TCnCustomDockPanel.WndProc函数 }
  3604. if HostDockSite <> nil then
  3605. FFloatingChild.Visible := False;
  3606. { 如果停靠客户的个数为1,就把她拖出,并且释放本身 }
  3607. DoFloat(Self, DockableControl.DockClients[0]);
  3608. Action := caFree;
  3609. end else if DockableControl.DockClientCount = 0 then
  3610. { 如果已经没有停靠客户,就把窗体释放掉 }
  3611. Action := caFree
  3612. else
  3613. begin
  3614. { 否则就隐藏 }
  3615. Action := caHide;
  3616. { 如果查找到DockableControl中的客户有一个是FUnDockControl,就不隐藏自己 }
  3617. if (FUnDockControl <> nil) and (DockableControl.DockClientCount = 2) then
  3618. begin
  3619. for i := 0 to DockableControl.DockClientCount - 1 do
  3620. if FUnDockControl = DockableControl.DockClients[i] then
  3621. begin
  3622. Action := caNone;
  3623. Break;
  3624. end;
  3625. end;
  3626. end;
  3627. if (HostDockSite is TCnDockPanel) and (HostDockSite.VisibleDockClientCount = 1) and
  3628. (FFloatingChild = nil) then
  3629. // 如果停靠服务器是TDockServer中的DockPanel,就调用ShowDockPanel函数。
  3630. TCnDockPanel(HostDockSite).ShowDockPanel(False, Self);
  3631. inherited DoClose(Action);
  3632. FUnDockControl := nil;
  3633. end;
  3634. function TCnDockableForm.GetDockableControl: TWinControl;
  3635. begin
  3636. Result := FDockableControl;
  3637. end;
  3638. procedure TCnDockableForm.SetDockableControl(const Value: TWinControl);
  3639. begin
  3640. FDockableControl := Value;
  3641. end;
  3642. procedure TCnDockableForm.SetUnDockControl(const Value: TControl);
  3643. begin
  3644. FUnDockControl := Value;
  3645. end;
  3646. { TCnConjoinDockHostForm }
  3647. constructor TCnConjoinDockHostForm.Create(AOwner: TComponent);
  3648. begin
  3649. inherited Create(AOwner);
  3650. BorderStyle := ConjoinDockHostBorderStyle;
  3651. end;
  3652. procedure TCnConjoinDockHostForm.DoClose(var Action: TCloseAction);
  3653. begin
  3654. inherited DoClose(Action);
  3655. end;
  3656. { TCnTabDockHostForm }
  3657. constructor TCnTabDockHostForm.Create(AOwner: TComponent);
  3658. begin
  3659. inherited Create(AOwner);
  3660. BorderStyle := TabDockHostBorderStyle;
  3661. end;
  3662. destructor TCnTabDockHostForm.Destroy;
  3663. begin
  3664. inherited;
  3665. end;
  3666. function TCnTabDockHostForm.GetActiveDockForm: TForm;
  3667. begin
  3668. if PageControl.ActivePage.ControlCount = 1 then
  3669. Result := TForm(PageControl.ActivePage.Controls[0])
  3670. else Result := nil;
  3671. end;
  3672. { TCnConjoinPanel }
  3673. constructor TCnConjoinPanel.Create(AOwner: TComponent);
  3674. begin
  3675. inherited Create(AOwner);
  3676. Parent := TWinControl(AOwner);
  3677. DockClient := TCnConjoinDockHostForm(AOwner).DockClient;
  3678. Align := alClient;
  3679. BevelOuter := bvNone;
  3680. DoubleBuffered := True;
  3681. ParentFont := False;
  3682. Caption := '';
  3683. end;
  3684. procedure TCnConjoinPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
  3685. begin
  3686. if Perform(CM_DOCKCLIENT, Integer(Source), Integer(SmallPoint(X, Y))) >= 0 then
  3687. begin
  3688. if Source.Control is TForm then
  3689. begin
  3690. { 下面两行代码是为了防止窗体的标题栏和窗体上面的控件的内容被清空 }
  3691. ParentForm.ActiveControl := nil;
  3692. TForm(Source.Control).ActiveControl := nil;
  3693. { ------------------------------------------------------------------------ }
  3694. SetDockSite(TForm(Source.Control), False);
  3695. if TForm(Source.Control).FormStyle = fsStayOnTop then
  3696. TForm(Parent).FormStyle := fsStayOnTop;
  3697. end;
  3698. UpdateCaption(nil);
  3699. end;
  3700. end;
  3701. procedure TCnConjoinPanel.DoDockOver(Source: TDragDockObject; X,
  3702. Y: Integer; State: TDragState; var Accept: Boolean);
  3703. begin
  3704. { 如果停靠客户是TDockableForm,并且停靠客户上面有TDockClient控件,就同意停靠 }
  3705. Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
  3706. end;
  3707. function TCnConjoinPanel.DoUnDock(NewTarget: TWinControl;
  3708. Client: TControl): Boolean;
  3709. begin
  3710. ParentForm.FUnDockControl := Client;
  3711. { 如果停靠客户是TDockableForm,就还原停靠客户的DockSite属性为True }
  3712. if not (Client is TCnDockableForm) then
  3713. SetDockSite(TForm(Client), True);
  3714. if (VisibleDockClientCount = 1) or
  3715. (DockClientCount <= 2){ and (NewTarget <> Self) }then
  3716. PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
  3717. UpdateCaption(Client);
  3718. Result := Perform(CM_UNDOCKCLIENT, Integer(NewTarget), Integer(Client)) = 0;
  3719. end;
  3720. function TCnConjoinPanel.GetParentForm: TCnConjoinDockHostForm;
  3721. begin
  3722. Result := TCnConjoinDockHostForm(Parent);
  3723. end;
  3724. procedure TCnConjoinPanel.GetSiteInfo(Client: TControl;
  3725. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  3726. begin
  3727. CanDock := IsDockable(Self, Client);
  3728. if CanDock then
  3729. begin
  3730. GetWindowRect(Handle, InfluenceRect);
  3731. end;
  3732. end;
  3733. procedure TCnConjoinPanel.CustomDockDrop(Source: TCnDragDockObject; X,
  3734. Y: Integer);
  3735. begin
  3736. inherited CustomDockDrop(Source, X, Y);
  3737. if Source.Control is TForm then
  3738. begin
  3739. { 下面代码是为了防止窗体的标题栏和窗体上面的控件的内容被清空 }
  3740. ParentForm.ActiveControl := nil;
  3741. if TForm(Source.Control).FormStyle = fsStayOnTop then
  3742. TForm(Parent).FormStyle := fsStayOnTop;
  3743. end;
  3744. UpdateCaption(nil);
  3745. end;
  3746. procedure TCnConjoinPanel.CustomDockOver(Source: TCnDragDockObject; X,
  3747. Y: Integer; State: TDragState; var Accept: Boolean);
  3748. begin
  3749. inherited CustomDockOver(Source, X, Y, State, Accept);
  3750. { 如果停靠客户是TDockableForm,并且停靠客户上面有TDockClient控件,就同意停靠 }
  3751. Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
  3752. end;
  3753. procedure TCnConjoinPanel.CustomEndDock(Target: TObject; X, Y: Integer);
  3754. begin
  3755. inherited CustomEndDock(Target, X, Y);;
  3756. end;
  3757. procedure TCnConjoinPanel.CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl;
  3758. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  3759. begin
  3760. CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
  3761. inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock);
  3762. end;
  3763. procedure TCnConjoinPanel.CustomPositionDockRect(Source: TCnDragDockObject; X, Y: Integer);
  3764. begin
  3765. inherited CustomPositionDockRect(Source, X, Y);
  3766. end;
  3767. procedure TCnConjoinPanel.CustomStartDock(var Source: TCnDragDockObject);
  3768. begin
  3769. ParentForm.FUnDockControl := nil;
  3770. inherited CustomStartDock(Source);
  3771. end;
  3772. function TCnConjoinPanel.CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl;
  3773. Client: TControl): Boolean;
  3774. begin
  3775. ParentForm.FUnDockControl := Client;
  3776. { 如果停靠客户是TDockableForm,就还原停靠客户的DockSite属性为True }
  3777. if not (Client is TCnDockableForm) then
  3778. SetDockSite(TForm(Client), True);
  3779. if ((VisibleDockClientCount = 1) or
  3780. (DockClientCount <= 2)) and (NewTarget <> ParentForm.DockableControl) then
  3781. begin
  3782. PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
  3783. end;
  3784. UpdateCaption(Client);
  3785. Result := inherited CustomUnDock(Source, NewTarget, Client);
  3786. end;
  3787. procedure TCnConjoinPanel.ReloadDockedControl(
  3788. const AControlName: string; var AControl: TControl);
  3789. begin
  3790. AControl := Cn_FindDockFormWithName(AControlName);
  3791. end;
  3792. procedure TCnConjoinPanel.CMUnDockClient(var Message: TCMUnDockClient);
  3793. begin
  3794. inherited;
  3795. { 如果有两个停靠客户,就要释放ParentForm }
  3796. if (DockClientCount = 2) and (VisibleDockClientCount = 1) then
  3797. PostMessage(ParentForm.Handle, WM_CLOSE, 0, 0);
  3798. if VisibleDockClientCount <= 2 then
  3799. CnDockFormControl.UpdateCaption(Self, Message.Client);
  3800. if UseDockManager and (CnDockManager <> nil) then
  3801. CnDockManager.ResetBounds(True);
  3802. end;
  3803. { TCnTabPageControl }
  3804. procedure TCnTabPageControl.AdjustClientRect(var Rect: TRect);
  3805. begin
  3806. inherited AdjustClientRect(Rect);
  3807. case TabPosition of
  3808. tpLeft:
  3809. Inc(Rect.Left, 2);
  3810. tpRight:
  3811. Dec(Rect.Right, 2);
  3812. tpBottom:
  3813. begin
  3814. Dec(Rect.Top, 1);
  3815. Dec(Rect.Bottom, 2);
  3816. end;
  3817. end;
  3818. end;
  3819. constructor TCnTabPageControl.Create(AOwner: TComponent);
  3820. begin
  3821. inherited Create(AOwner);
  3822. Parent := TWinControl(AOwner);
  3823. DockClient := FindDockClient(Parent);
  3824. SetDockSite(Self, True);
  3825. PopupMenu := DockPageControlPopupMenu;
  3826. HotTrack := DockPageControlHotTrack;
  3827. DoubleBuffered := True;
  3828. Caption := '';
  3829. FVersion := $00040000;
  3830. end;
  3831. var TabPageStreamEndFlag: Integer = -10;
  3832. destructor TCnTabPageControl.Destroy;
  3833. begin
  3834. SetDockSite(Self, False);
  3835. inherited Destroy;
  3836. end;
  3837. procedure TCnTabPageControl.DockDrop(Source: TDragDockObject; X,
  3838. Y: Integer);
  3839. begin
  3840. if Perform(CM_DOCKCLIENT, Integer(Source), Integer(SmallPoint(X, Y))) >= 0 then
  3841. begin
  3842. if Source.Control is TForm then
  3843. begin
  3844. { 下面一行代码是为了防止窗体的标题栏和窗体上面的控件的内容被清空 }
  3845. TForm(Source.Control).ActiveControl := nil;
  3846. SetDockSite(TWinControl(Source.Control), False);
  3847. if TForm(Source.Control).FormStyle = fsStayOnTop then
  3848. TForm(Parent).FormStyle := fsStayOnTop;
  3849. end;
  3850. UpdateCaption(nil);
  3851. end;
  3852. end;
  3853. function TCnTabPageControl.DoUnDock(NewTarget: TWinControl;
  3854. Client: TControl): Boolean;
  3855. begin
  3856. { 如果停靠客户是TDockableForm,就还原停靠客户的DockSite属性为True }
  3857. if not (Client is TCnDockableForm) then
  3858. SetDockSite(TForm(Client), True);
  3859. if (VisibleDockClientCount = 1) or
  3860. (DockClientCount <= 2){ and (NewTarget <> Self) }then
  3861. PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
  3862. UpdateCaption(Client);
  3863. Result := Perform(CM_UNDOCKCLIENT, Integer(NewTarget), Integer(Client)) = 0;
  3864. end;
  3865. function TCnTabPageControl.GetParentForm: TCnTabDockHostForm;
  3866. begin
  3867. Result := TCnTabDockHostForm(Parent);
  3868. end;
  3869. procedure TCnTabPageControl.LoadFromStream(Stream: TStream);
  3870. var i, Count, NameLen, SheetVisible, ActiveSheetIndex: Integer;
  3871. ControlName: string;
  3872. AControl: TControl;
  3873. begin
  3874. try
  3875. Stream.Read(i, Sizeof(i));
  3876. { 从流中读出标签的个数,并且依次从流中读出她们的信息 }
  3877. Stream.Read(Count, Sizeof(Count));
  3878. for i := 0 to Count - 1 do
  3879. begin
  3880. ControlName := '';
  3881. { 读出名字的长度 }
  3882. Stream.Read(NameLen, SizeOf(NameLen));
  3883. if NameLen > 0 then
  3884. begin
  3885. { 读出名字的字符串 }
  3886. SetLength(ControlName, NameLen);
  3887. Stream.Read(Pointer(ControlName)^, NameLen * SizeOf(Char));
  3888. end;
  3889. if ControlName <> '' then
  3890. begin
  3891. { 找到名字为ControlName的停靠窗体,并且把她停靠进TCnTabPageControl }
  3892. ReloadDockedControl(ControlName, AControl);
  3893. if AControl <> nil then
  3894. AControl.ManualDock(Self, nil, alClient);
  3895. end;
  3896. { 读出标签的Visible }
  3897. Stream.Read(SheetVisible, SizeOf(SheetVisible));
  3898. DockClients[i].Visible := Boolean(SheetVisible);
  3899. end;
  3900. { 读出被激活的标签 }
  3901. Stream.Read(ActiveSheetIndex, SizeOf(ActiveSheetIndex));
  3902. ActivePageIndex := ActiveSheetIndex;
  3903. finally
  3904. end;
  3905. end;
  3906. procedure TCnTabPageControl.SaveToStream(Stream: TStream);
  3907. var i, Count, NameLen, SheetVisible, ActiveSheetIndex: Integer;
  3908. ControlName: string;
  3909. CurrentControl: TControl;
  3910. begin
  3911. { 写入流的版本 }
  3912. Stream.Write(FVersion, SizeOf(FVersion));
  3913. Count := PageCount;
  3914. { 写入TabSheet的个数 }
  3915. Stream.Write(Count, SizeOf(Count));
  3916. for i := 0 to PageCount - 1 do
  3917. begin
  3918. CurrentControl := Pages[i].Controls[0];
  3919. ControlName := CurrentControl.Name;
  3920. NameLen := Length(ControlName);
  3921. { 写入名字的长度 }
  3922. Stream.Write(NameLen, SizeOf(NameLen));
  3923. { 写入名字 }
  3924. if NameLen > 0 then Stream.Write(Pointer(ControlName)^, NameLen * SizeOf(Char));
  3925. SheetVisible := 0;
  3926. if (Self is TCnVSNETTabPageControl) and (ParentForm.HostDockSite is TCnDockPanel) then
  3927. SheetVisible := Integer(TCnVSNETDockTabSheet(Pages[i]).OldVisible)
  3928. else
  3929. SheetVisible := SheetVisible + Integer(CurrentControl.Visible);
  3930. { 写入是否可见 }
  3931. Stream.Write(SheetVisible, SizeOf(SheetVisible));
  3932. end;
  3933. ActiveSheetIndex := ActivePageIndex;
  3934. { 写入激活的TabSheet的索引 }
  3935. Stream.Write(ActiveSheetIndex, SizeOf(ActiveSheetIndex));
  3936. { 写入结束标志 }
  3937. Stream.Write(TabPageStreamEndFlag, SizeOf(TabPageStreamEndFlag));
  3938. end;
  3939. procedure TCnTabPageControl.CustomDockDrop(Source: TCnDragDockObject; X,
  3940. Y: Integer);
  3941. var DragDockObject: TDragDockObject;
  3942. begin
  3943. if Source.DropAlign in [alClient, alNone] then
  3944. begin
  3945. DragDockObject := TDragDockObject.Create(Source.Control);
  3946. try
  3947. DragDockObject.DockRect := Source.DockRect;
  3948. DragDockObject.Control := Source.Control;
  3949. Perform(CM_DOCKCLIENT, Integer(DragDockObject), Integer(SmallPoint(X, Y)));
  3950. UpdateCaption(nil);
  3951. finally
  3952. DragDockObject.Free;
  3953. end;
  3954. end else
  3955. begin
  3956. inherited CustomDockDrop(Source, X, Y);
  3957. end;
  3958. if Source.Control is TForm then
  3959. begin
  3960. { 下面一行代码是为了防止窗体的标题栏和窗体上面的控件的内容被清空 }
  3961. TForm(Source.Control).ActiveControl := nil;
  3962. { ------------------------------------------------------------------------ }
  3963. SetDockSite(TForm(Source.Control), False);
  3964. end;
  3965. end;
  3966. procedure TCnTabPageControl.CustomDockOver(Source: TCnDragDockObject; X,
  3967. Y: Integer; State: TDragState; var Accept: Boolean);
  3968. var ARect: TRect;
  3969. begin
  3970. inherited CustomDockOver(Source, X, Y, State, Accept);
  3971. { 如果停靠客户上面有TDockClient控件,就同意停靠 }
  3972. Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
  3973. // 画停靠客户的预览停靠位置
  3974. if Accept then
  3975. begin
  3976. ComputeDockingRect(self, ARect,
  3977. Point(ClientWidth div 2, ClientHeight div 2));
  3978. Source.DockRect := ARect;
  3979. end;
  3980. end;
  3981. procedure TCnTabPageControl.CustomEndDock(Target: TObject; X, Y: Integer);
  3982. begin
  3983. inherited CustomEndDock(Target, X, Y);
  3984. end;
  3985. procedure TCnTabPageControl.CustomGetSiteInfo(Source: TCnDragDockObject; Client: TControl;
  3986. var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
  3987. begin
  3988. inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock);
  3989. CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
  3990. end;
  3991. procedure TCnTabPageControl.CustomPositionDockRect(
  3992. Source: TCnDragDockObject; X, Y: Integer);
  3993. begin
  3994. inherited CustomPositionDockRect(Source, X, Y);
  3995. end;
  3996. procedure TCnTabPageControl.CustomStartDock(var Source: TCnDragDockObject);
  3997. begin
  3998. inherited CustomStartDock(Source);
  3999. end;
  4000. function TCnTabPageControl.CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl;
  4001. Client: TControl): Boolean;
  4002. begin
  4003. { 如果停靠客户是TDockableForm,就还原停靠客户的DockSite属性为True }
  4004. if not (Client is TCnDockableForm) then
  4005. SetDockSite(TForm(Client), True);
  4006. if (VisibleDockClientCount = 1) or
  4007. (DockClientCount <= 2) then
  4008. PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
  4009. UpdateCaption(Client);
  4010. Result := Perform(CM_UNDOCKCLIENT, Integer(NewTarget), Integer(Client)) = 0;
  4011. end;
  4012. procedure TCnTabPageControl.ReloadDockedControl(
  4013. const AControlName: string; var AControl: TControl);
  4014. begin
  4015. AControl := Cn_FindDockFormWithName(AControlName);
  4016. end;
  4017. procedure TCnTabPageControl.CustomGetDockEdge(Source: TCnDragDockObject;
  4018. MousePos: TPoint; var DropAlign: TAlign);
  4019. var ARect: TRect;
  4020. begin
  4021. ARect := Source.DockRect;
  4022. DropAlign := ComputeDockingRect(Source.Control, ARect, MousePos);
  4023. end;
  4024. { TCnBasicDockStyle }
  4025. constructor TCnBasicDockStyle.Create(AOwner: TComponent);
  4026. begin
  4027. inherited Create(AOwner);
  4028. { 设置一些默认的类的引用 }
  4029. CnDockPanelClass := DefaultDockPanelClass;
  4030. CnDockSplitterClass := DefaultDockSplitterClass;
  4031. CnConjoinPanelClass := DefaultConjoinPanelClass;
  4032. CnTabDockClass := DefaultTabDockClass;
  4033. CnDockPanelTreeClass := DefaultDockTreeClass;
  4034. CnDockPanelZoneClass := DefaultDockZoneClass;
  4035. CnConjoinPanelTreeClass := DefaultDockTreeClass;
  4036. CnConjoinPanelZoneClass := DefaultDockZoneClass;
  4037. FCnConjoinServerOptionClass := TCnBasicConjoinServerOption;
  4038. FCnTabServerOptionClass := TCnBasicTabServerOption;
  4039. FDockBaseControlList := TList.Create;
  4040. if AOwner is TCustomForm then
  4041. FParentForm := TForm(AOwner)
  4042. else FParentForm := nil;
  4043. if not (csDesigning in ComponentState) then
  4044. begin
  4045. { 保存老的窗口过程 }
  4046. FOldWindowProc := FParentForm.WindowProc;
  4047. { 重载窗口过程 }
  4048. FParentForm.WindowProc := ParentFormWindowProc;
  4049. end;
  4050. end;
  4051. function TCnBasicDockStyle.GetControlName: string;
  4052. begin
  4053. Result := gs_CnDockStyleName;
  4054. end;
  4055. function TCnBasicDockStyle.GetDockStyleVersion: string;
  4056. begin
  4057. Result := gs_CnDockStyleVersion;
  4058. end;
  4059. procedure TCnBasicDockStyle.SetDockBaseControl(IsCreate: Boolean;
  4060. DockBaseControl: TCnDockBaseControl);
  4061. begin
  4062. { 没有事做 }
  4063. end;
  4064. procedure TCnBasicDockStyle.FormDockDrop(DockClient: TCnDockClient; Source: TCnDragDockObject; X,
  4065. Y: Integer);
  4066. var
  4067. ARect,DRect: TRect;
  4068. DockType: TAlign;
  4069. Host: TCustomForm;
  4070. APanelDock: TWinControl;
  4071. begin
  4072. if IsDockable(DockClient.ParentForm, Source.Control, Source.DropOnControl, Source.DropAlign) then
  4073. begin
  4074. Host := nil;
  4075. { 锁住Windows桌面 }
  4076. if not IsLoading then
  4077. Cn_LockWindow(nil);
  4078. try
  4079. // 调用ComputeDockingRect函数知道停靠的类型
  4080. with DockClient do
  4081. begin
  4082. DockType := ComputeDockingRect(DockClient.ParentForm, ARect, Point(X, Y));
  4083. if (ParentForm.HostDockSite is TCnDockPanel) then
  4084. begin
  4085. // 如果停靠服务器是TDockPanel,就停靠在TDockServer的DockPanel上。
  4086. if DockType = alClient then
  4087. begin
  4088. // 如果停靠类型是alClient
  4089. if Source.Control is TCnTabDockHostForm then
  4090. begin
  4091. // 如果停靠客户是TCnTabDockHostForm,
  4092. // 就先把Parent停靠到TCnTabDockHostForm中,
  4093. // 再把TCnTabDockHostForm停靠到TCnDockPanel中。
  4094. APanelDock := ParentForm.HostDockSite;
  4095. ARect := ParentForm.BoundsRect;
  4096. ParentForm.ManualDock(TCnTabDockHostForm(Source.Control).PageControl, nil, alClient);
  4097. TCnTabDockHostForm(Source.Control).PageControl.ActivePage.PageIndex := 0;
  4098. Source.Control.BoundsRect := ARect;
  4099. Source.Control.ManualDock(APanelDock, nil, alClient);
  4100. if ParentForm.FormStyle = fsStayOnTop then
  4101. TForm(Source.Control).FormStyle := fsStayOnTop;
  4102. end else
  4103. begin
  4104. // 否则就创建TCnTabDockHostForm,
  4105. // 把把Parent停靠到TCnTabDockHostForm中,
  4106. // 再把TCnTabDockHostForm停靠到TCnDockPanel中。
  4107. APanelDock := ParentForm.HostDockSite;
  4108. DRect.TopLeft := ParentForm.HostDockSite.ClientToScreen(Point(0, 0));
  4109. Host := CreateTabHostAndDockControl(ParentForm, Source.Control);
  4110. SetDockSite(ParentForm, False);
  4111. SetDockSite(TWinControl(Source.Control), False);
  4112. Host.Top := DRect.Top;
  4113. Host.Left := DRect.Left;
  4114. Host.ManualDock(APanelDock, nil, alClient);
  4115. Host.Visible := True;
  4116. end;
  4117. end
  4118. else
  4119. begin
  4120. // 如果停靠类型不是alClient,
  4121. // 就把停靠窗体停靠到TCnDockPanel.
  4122. DRect := ParentForm.HostDockSite.BoundsRect;
  4123. Source.Control.ManualDock(ParentForm.HostDockSite, nil, DockType);
  4124. ParentForm.HostDockSite.BoundsRect := DRect;
  4125. end;
  4126. Exit;
  4127. end;
  4128. // 创建分页的服务窗体
  4129. if DockType = alClient then
  4130. begin
  4131. Host := CreateTabHostAndDockControl(ParentForm, Source.Control);
  4132. SetDockSite(ParentForm, False);
  4133. SetDockSite(TWinControl(Source.Control), False);
  4134. Host.Visible := True;
  4135. end
  4136. // 创建平铺的服务窗体
  4137. else if DockType <> alNone then
  4138. begin
  4139. Host := CreateConjoinHostAndDockControl(ParentForm, Source.Control, DockType);
  4140. SetDockSite(ParentForm, False);
  4141. SetDockSite(TWinControl(Source.Control), False);
  4142. Host.Visible := True;
  4143. end;
  4144. if Host <> nil then
  4145. begin
  4146. Host.LRDockWidth := Source.Control.LRDockWidth;
  4147. Host.TBDockHeight := Source.Control.TBDockHeight;
  4148. end;
  4149. end;
  4150. finally
  4151. { 解锁Windows桌面 }
  4152. if not IsLoading then
  4153. Cn_UnLockWindow;
  4154. end;
  4155. end;
  4156. end;
  4157. procedure TCnBasicDockStyle.FormDockOver(DockClient: TCnDockClient; Source: TCnDragDockObject; X,
  4158. Y: Integer; State: TDragState; var Accept: Boolean);
  4159. var
  4160. ARect: TRect;
  4161. begin
  4162. with DockClient do
  4163. begin
  4164. Accept := EnableDock and EachOtherDock and
  4165. IsDockable(ParentForm.HostDockSite, Source.Control, Source.DropOnControl, Source.DropAlign);
  4166. if Accept and (State = dsDragMove) and
  4167. (ComputeDockingRect(ParentForm, ARect, Point(X, Y)) <> alNone) then
  4168. Source.DockRect := ARect;
  4169. end;
  4170. end;
  4171. procedure TCnBasicDockStyle.FormEndDock(DockClient: TCnDockClient; Target: TObject; X, Y: Integer);
  4172. begin
  4173. { 没事做 }
  4174. end;
  4175. procedure TCnBasicDockStyle.FormPositionDockRect(DockClient: TCnDockClient;
  4176. Source: TCnDragDockObject);
  4177. var
  4178. NewWidth, NewHeight: Integer;
  4179. TempX, TempY: Double;
  4180. begin
  4181. with Source do
  4182. begin
  4183. if (DragTarget = nil) or (not TCnWinControlAccess(DragTarget).UseDockManager) then
  4184. begin
  4185. NewWidth := Control.UndockWidth;
  4186. NewHeight := Control.UndockHeight;
  4187. // Drag position for dock rect is scaled relative to control's click point.
  4188. TempX := DragPos.X - ((NewWidth) * MouseDeltaX);
  4189. TempY := DragPos.Y - ((NewHeight) * MouseDeltaY);
  4190. with DockRect do
  4191. begin
  4192. Left := Round(TempX);
  4193. Top := Round(TempY);
  4194. Right := Left + NewWidth;
  4195. Bottom := Top + NewHeight;
  4196. end;
  4197. { Allow DragDockObject final say on this new dock rect }
  4198. AdjustDockRect(DockRect);
  4199. end
  4200. else begin
  4201. GetWindowRect(TargetControl.Handle, DockRect);
  4202. if TCnWinControlAccess(DragTarget).UseDockManager then
  4203. begin
  4204. if TargetControl is TCnCustomDockPanel then
  4205. begin
  4206. if (TCnCustomDockPanel(DragTarget).CnDockManager <> nil) then
  4207. TCnCustomDockPanel(DragTarget).CnDockManager.PositionDockRect(Control,
  4208. DropOnControl, DropAlign, DockRect);
  4209. end;
  4210. end;
  4211. end;
  4212. end;
  4213. end;
  4214. procedure TCnBasicDockStyle.GetComponentInfo(var AName, Author, Email, Comment: string);
  4215. begin
  4216. // 基类不干
  4217. end;
  4218. procedure TCnBasicDockStyle.FormStartDock(DockClient: TCnDockClient; var Source: TCnDragDockObject);
  4219. begin
  4220. { 没事做 }
  4221. end;
  4222. function TCnBasicDockStyle.FormUnDock(DockClient: TCnDockClient; NewTarget: TWinControl;
  4223. Client: TControl): Boolean;
  4224. begin
  4225. Result := True;
  4226. end;
  4227. procedure TCnBasicDockStyle.FormGetSiteInfo(Source: TCnDragDockObject;
  4228. DockClient: TCnDockClient;
  4229. Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
  4230. var CanDock: Boolean);
  4231. begin
  4232. with DockClient do
  4233. CanDock := EnableDock and EachOtherDock and
  4234. IsDockable(ParentForm, Client, Source.DropOnControl, Source.DropAlign);
  4235. end;
  4236. function TCnBasicDockStyle.DockClientWindowProc(DockClient: TCnDockClient; var Message: TMessage): Boolean;
  4237. begin
  4238. { 默认要执行原来的消息过程 }
  4239. Result := False;
  4240. end;
  4241. procedure TCnBasicDockStyle.FormGetDockEdge(DockClient: TCnDockClient;
  4242. Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign);
  4243. begin
  4244. DropAlign := TCnControlAccess(DockClient.ParentForm).GetDockEdge(MousePos);
  4245. end;
  4246. procedure TCnBasicDockStyle.SetConjoinServerOption(
  4247. const Value: TCnBasicConjoinServerOption);
  4248. begin
  4249. FCnConjoinServerOption.Assign(Value);
  4250. end;
  4251. procedure TCnBasicDockStyle.SetTabServerOption(
  4252. const Value: TCnBasicTabServerOption);
  4253. begin
  4254. FCnTabServerOption.Assign(Value);
  4255. end;
  4256. procedure TCnBasicDockStyle.CreateConjoinServerOption(
  4257. var Option: TCnBasicConjoinServerOption);
  4258. begin
  4259. Option := TCnBasicConjoinServerOption.Create(Self);
  4260. end;
  4261. procedure TCnBasicDockStyle.CreateTabServerOption(
  4262. var Option: TCnBasicTabServerOption);
  4263. begin
  4264. Option := TCnBasicTabServerOption.Create(Self);
  4265. end;
  4266. procedure TCnBasicDockStyle.CreateServerOption;
  4267. begin
  4268. if FCnConjoinServerOption = nil then
  4269. FCnConjoinServerOption := FCnConjoinServerOptionClass.Create(Self);
  4270. if FCnTabServerOption = nil then
  4271. FCnTabServerOption := FCnTabServerOptionClass.Create(Self);
  4272. end;
  4273. function TCnBasicDockStyle.GetConjoinServerOption: TCnBasicConjoinServerOption;
  4274. begin
  4275. Result := FCnConjoinServerOption;
  4276. end;
  4277. function TCnBasicDockStyle.GetTabServerOption: TCnBasicTabServerOption;
  4278. begin
  4279. Result := FCnTabServerOption;
  4280. end;
  4281. procedure TCnBasicDockStyle.FreeServerOption;
  4282. begin
  4283. if FCnConjoinServerOption <> nil then
  4284. FCnConjoinServerOption.Free;
  4285. if FCnTabServerOption <> nil then
  4286. FCnTabServerOption.Free;
  4287. end;
  4288. destructor TCnBasicDockStyle.Destroy;
  4289. begin
  4290. if not (csDesigning in ComponentState) then
  4291. begin
  4292. if @FOldWindowProc <> nil then
  4293. FParentForm.WindowProc := FOldWindowProc;
  4294. FOldWindowProc := nil;
  4295. end;
  4296. FDockBaseControlList.Free;
  4297. FreeServerOption;
  4298. inherited Destroy;
  4299. end;
  4300. procedure TCnBasicDockStyle.AssignConjoinServerOption(
  4301. APanel: TCnCustomDockPanel);
  4302. begin
  4303. APanel.CnDockManager.GrabberSize := ConjoinServerOption.GrabbersSize;
  4304. APanel.CnDockManager.SplitterWidth := ConjoinServerOption.SplitterWidth;
  4305. end;
  4306. procedure TCnBasicDockStyle.AssignTabServerOption(
  4307. APage: TCnTabPageControl);
  4308. begin
  4309. APage.HotTrack := TabServerOption.HotTrack;
  4310. APage.TabPosition := TabServerOption.TabPosition;
  4311. end;
  4312. procedure TCnBasicDockStyle.Loaded;
  4313. begin
  4314. inherited;
  4315. end;
  4316. procedure TCnBasicDockStyle.AfterConstruction;
  4317. begin
  4318. inherited AfterConstruction;
  4319. CreateServerOption;
  4320. end;
  4321. procedure TCnBasicDockStyle.ParentFormWindowProc(var Message: TMessage);
  4322. begin
  4323. if not (csDesigning in ComponentState) then
  4324. begin
  4325. if Assigned(FOldWindowProc) then
  4326. FOldWindowProc(Message);
  4327. end;
  4328. end;
  4329. procedure TCnBasicDockStyle.AddDockBaseControl(
  4330. ADockBaseControl: TCnDockBaseControl);
  4331. begin
  4332. if ADockBaseControl = nil then Exit;
  4333. if FDockBaseControlList.IndexOf(ADockBaseControl) = -1 then
  4334. begin
  4335. FDockBaseControlList.Add(ADockBaseControl);
  4336. ConjoinServerOption.ResetDockControlOption;
  4337. TabServerOption.ResetDockControlOption;
  4338. end;
  4339. end;
  4340. procedure TCnBasicDockStyle.RemoveDockBaseControl(
  4341. ADockBaseControl: TCnDockBaseControl);
  4342. begin
  4343. if ADockBaseControl = nil then Exit;
  4344. FDockBaseControlList.Remove(ADockBaseControl);
  4345. end;
  4346. procedure TCnBasicDockStyle.ResetDockControlConjoinOption;
  4347. begin
  4348. end;
  4349. procedure TCnBasicDockStyle.ResetDockControlTabOption;
  4350. begin
  4351. end;
  4352. function TCnBasicDockStyle.GetDockBaseControlListCount: Integer;
  4353. begin
  4354. Result := FDockBaseControlList.Count;
  4355. end;
  4356. function TCnBasicDockStyle.GetDockBaseControlLists(
  4357. Index: Integer): TCnDockBaseControl;
  4358. begin
  4359. Result := FDockBaseControlList[Index];
  4360. end;
  4361. function TCnBasicDockStyle.DockServerWindowProc(DockServer: TCnDockServer;
  4362. var Message: TMessage): Boolean;
  4363. begin
  4364. { 默认要执行原来的消息过程 }
  4365. Result := False;
  4366. end;
  4367. function TCnBasicDockStyle.GetDockState(
  4368. DockClient: TCnDockClient): Integer;
  4369. begin
  4370. Result := DS_Unknow;
  4371. if (DockClient <> nil) and (DockClient.ParentForm <> nil) then
  4372. begin
  4373. if DockClient.ParentForm.Floating then
  4374. Result := DS_Floating
  4375. else Result := DS_Docking;
  4376. end;
  4377. end;
  4378. function TCnBasicDockStyle.CanSetBottomDocked(ADockBaseControl: TCnDockBaseControl): Boolean;
  4379. begin
  4380. Result := True;
  4381. end;
  4382. function TCnBasicDockStyle.CanSetEachOtherDocked(ADockBaseControl: TCnDockBaseControl): Boolean;
  4383. begin
  4384. Result := True;
  4385. end;
  4386. function TCnBasicDockStyle.CanSetEnableDocked(ADockBaseControl: TCnDockBaseControl): Boolean;
  4387. begin
  4388. Result := True;
  4389. end;
  4390. function TCnBasicDockStyle.CanSetLeftDocked(ADockBaseControl: TCnDockBaseControl): Boolean;
  4391. begin
  4392. Result := True;
  4393. end;
  4394. function TCnBasicDockStyle.CanSetRightDocked(ADockBaseControl: TCnDockBaseControl): Boolean;
  4395. begin
  4396. Result := True;
  4397. end;
  4398. function TCnBasicDockStyle.CanSetTopDocked(ADockBaseControl: TCnDockBaseControl): Boolean;
  4399. begin
  4400. Result := True;
  4401. end;
  4402. procedure TCnBasicDockStyle.ResetCursor(Source: TCnDragDockObject);
  4403. begin
  4404. if (Source.TargetControl = nil) and (Source.Control <> nil) and (Source.Control.Floating) then
  4405. Windows.SetCursor(Screen.Cursors[crDefault])
  4406. else if (Source.TargetControl = nil) and (not GlobalDockClient.CanFloat) then
  4407. Windows.SetCursor(Screen.Cursors[crNo])
  4408. else
  4409. Windows.SetCursor(Screen.Cursors[crDefault]);
  4410. end;
  4411. procedure TCnBasicDockStyle.HideDockForm(ADockClient: TCnDockClient);
  4412. begin
  4413. { 调用窗体上的TCnDockClient的MakeHideEvent函数 }
  4414. if ADockClient <> nil then
  4415. begin
  4416. ADockClient.ParentForm.Visible := False;
  4417. ADockClient.MakeHideEvent;
  4418. end;
  4419. end;
  4420. procedure TCnBasicDockStyle.ShowDockForm(ADockClient: TCnDockClient);
  4421. begin
  4422. { 调用窗体上的TCnDockClient的MakeShowEvent函数 }
  4423. if ADockClient <> nil then
  4424. begin
  4425. ADockClient.ParentForm.Visible := True;
  4426. ADockClient.MakeShowEvent;
  4427. end;
  4428. end;
  4429. function TCnBasicDockStyle.GetDockFormVisible(ADockClient: TCnDockClient): Boolean;
  4430. begin
  4431. Result := True;
  4432. if ADockClient <> nil then
  4433. begin
  4434. if ADockClient.ParentForm.Visible then
  4435. begin
  4436. if ADockClient.ParentForm.HostDockSite <> nil then
  4437. begin
  4438. if ADockClient.ParentForm.HostDockSite is TCnDockPanel then
  4439. Result := ADockClient.ParentForm.HostDockSite.Width * ADockClient.ParentForm.HostDockSite.Height > 0
  4440. else
  4441. Result := GetFormVisible(ADockClient.ParentForm.HostDockSite.Parent);
  4442. end;
  4443. end else Result := False;
  4444. end;
  4445. end;
  4446. procedure TCnBasicDockStyle.RestoreClient(DockClient: TCnDockClient);
  4447. var TmpLastDockSite: TWinControl;
  4448. TmpUnDockLeft, TmpUnDockTop: Integer;
  4449. i: Integer;
  4450. ADockClient: TCnDockClient;
  4451. ADockServer: TCnDockServer;
  4452. ARect: TRect;
  4453. procedure DoFloatParentForm;
  4454. begin
  4455. with DockClient do
  4456. begin
  4457. if (ParentForm.HostDockSite <> nil) then
  4458. begin
  4459. ARect := Bounds(TmpUnDockLeft, TmpUnDockTop, ParentForm.UndockWidth, ParentForm.UndockHeight);
  4460. ParentForm.ManualFloat(ARect);
  4461. if (ParentForm.Left <> ARect.Left) or (ParentForm.Top <> ARect.Top) then
  4462. begin
  4463. ParentForm.Left := ARect.Left;
  4464. ParentForm.Top := ARect.Top;
  4465. end;
  4466. end;
  4467. end;
  4468. end;
  4469. begin
  4470. if DockClient = nil then Exit;
  4471. if not DockClient.CanFloat then Exit;
  4472. with DockClient do
  4473. begin
  4474. { 必须是能够符合停靠条件的才行 }
  4475. if not EnableDock then Exit;
  4476. if LastDockSite is TCnDockPanel then
  4477. begin
  4478. with TCnDockPanel(LastDockSite) do
  4479. begin
  4480. { 对于停靠客户 }
  4481. if ((not LeftDock) and (Align = alLeft)) or
  4482. ((not RightDock) and (Align = alRight)) or
  4483. ((not TopDock) and (Align = alTop)) or
  4484. ((not BottomDock) and (Align = alBottom)) then
  4485. begin
  4486. DoFloatParentForm;
  4487. Exit;
  4488. end;
  4489. { 对于停靠服务器 }
  4490. ADockServer := DockServer;
  4491. if ADockServer <> nil then
  4492. if (not ADockServer.EnableDock) or
  4493. ((not ADockServer.LeftDock) and (Align = alLeft)) or
  4494. ((not ADockServer.RightDock) and (Align = alRight)) or
  4495. ((not ADockServer.TopDock) and (Align = alTop)) or
  4496. ((not ADockServer.BottomDock) and (Align = alBottom)) then
  4497. begin
  4498. DoFloatParentForm;
  4499. Exit;
  4500. end;
  4501. end;
  4502. end;
  4503. if ParentForm is TCnConjoinDockHostForm then
  4504. begin
  4505. with TCnConjoinDockHostForm(ParentForm).Panel do
  4506. begin
  4507. for i := DockClientCount - 1 downto 0 do
  4508. begin
  4509. ADockClient := FindDockClient(DockClients[i]);
  4510. if (ADockClient <> nil) and (ADockClient.LastDockSite is TCnDockPanel) then
  4511. ADockClient.RestoreChild;
  4512. end;
  4513. end;
  4514. Exit;
  4515. end;
  4516. { 保存原先的LastDockSite,因为在调用一些函数后会覆盖掉原先的LastDockSite }
  4517. TmpLastDockSite := LastDockSite;
  4518. TmpUnDockLeft := UnDockLeft;
  4519. TmpUnDockTop := UnDockTop;
  4520. { 重新设置DockClient的一些属性 }
  4521. ResetDockClient(DockClient, nil);
  4522. DoFloatParentForm;
  4523. if TmpLastDockSite is TCnDockPanel then
  4524. begin
  4525. with TCnDockPanel(TmpLastDockSite) do
  4526. begin
  4527. if UseDockManager and (CnDockManager <> nil) then
  4528. begin
  4529. if not CnDockManager.HasZoneWithControl(ParentForm) then Exit;
  4530. DisableAlign;
  4531. try
  4532. { 调用ParentForm的Dock函数把ParentForm停靠到LastDockSite中 }
  4533. ParentForm.Dock(TmpLastDockSite, Rect(0,0,0,0));
  4534. { 由于在LastDockSite的CnDockManager接口中已经有一个ParentForm的Zone,
  4535. 所以只要把它show出来就可以了 }
  4536. CnDockManager.ShowControl(ParentForm);
  4537. { 下面一行代码是为了防止窗体的标题栏和窗体上面的控件的内容被清空 }
  4538. ParentForm.ActiveControl := nil;
  4539. SetDockSite(ParentForm, False);
  4540. { 使ParentForm获得焦点 }
  4541. if ParentForm.Visible and ParentForm.CanFocus then
  4542. ParentForm.SetFocus;
  4543. ShowDockPanel(True, ParentForm, sdfDockPanel);
  4544. finally
  4545. EnableAlign;
  4546. end;
  4547. end;
  4548. end;
  4549. end;
  4550. end;
  4551. end;
  4552. { TCnAdvDockStyle }
  4553. function TCnAdvDockStyle.DockClientWindowProc(DockClient: TCnDockClient;
  4554. var Message: TMessage): Boolean;
  4555. begin
  4556. if (DockClient <> nil) and (Message.Msg = WM_NCLBUTTONDBLCLK) then
  4557. if DockClient.CanFloat then
  4558. DockClient.RestoreChild;
  4559. Result := inherited DockClientWindowProc(DockClient, Message);
  4560. end;
  4561. { TCnDockSplitter }
  4562. constructor TCnDockSplitter.Create(AOwner: TComponent);
  4563. begin
  4564. inherited Create(AOwner);
  4565. AutoSnap := False;
  4566. end;
  4567. function TCnDockSplitter.FindControl: TControl;
  4568. begin
  4569. if DockServer <> nil then
  4570. Result := DockServer.GetDockPanelWithAlign(Align)
  4571. else
  4572. Result := inherited FindControl;
  4573. end;
  4574. function TCnDockSplitter.GetSplitterIndex: Integer;
  4575. begin
  4576. case Align of
  4577. alTop: Result := 0;
  4578. alBottom: Result := 1;
  4579. alLeft: Result := 2;
  4580. alRight: Result := 3;
  4581. else
  4582. Result := -1;
  4583. end;
  4584. end;
  4585. { TCnBasicServerOption }
  4586. procedure TCnBasicServerOption.Assign(Source: TPersistent);
  4587. begin
  4588. if Source is TCnBasicServerOption then
  4589. begin
  4590. end;
  4591. inherited Assign(Source);
  4592. end;
  4593. constructor TCnBasicServerOption.Create(ADockStyle: TCnBasicDockStyle);
  4594. begin
  4595. FDockStyle := ADockStyle;
  4596. end;
  4597. destructor TCnBasicServerOption.Destroy;
  4598. begin
  4599. inherited Destroy;
  4600. end;
  4601. procedure TCnBasicServerOption.ResetDockClientOption(
  4602. ADockClient: TCnDockClient);
  4603. begin
  4604. // 本来这个函数是一个纯虚函数,但是不知道怎么回事编译要出错,只好改成一般的虚函数
  4605. end;
  4606. procedure TCnBasicServerOption.ResetDockServerOption(
  4607. ADockServer: TCnDockServer);
  4608. begin
  4609. // 本来这个函数是一个纯虚函数,但是不知道怎么回事编译要出错,只好改成一般的虚函数
  4610. end;
  4611. { TCnBasicTabServerOption }
  4612. procedure TCnBasicTabServerOption.Assign(Source: TPersistent);
  4613. begin
  4614. if Source is TCnBasicTabServerOption then
  4615. begin
  4616. FTabPosition := TCnBasicTabServerOption(Source).FTabPosition;
  4617. FHotTrack := TCnBasicTabServerOption(Source).FHotTrack;
  4618. end;
  4619. inherited Assign(Source);
  4620. end;
  4621. constructor TCnBasicTabServerOption.Create(ADockStyle: TCnBasicDockStyle);
  4622. begin
  4623. inherited Create(ADockStyle);
  4624. FHotTrack := False;
  4625. FTabPosition := tpTop;
  4626. end;
  4627. destructor TCnBasicTabServerOption.Destroy;
  4628. begin
  4629. inherited Destroy;
  4630. end;
  4631. procedure TCnBasicTabServerOption.ResetDockClientOption(
  4632. ADockClient: TCnDockClient);
  4633. var PageControl: TCnTabPageControl;
  4634. begin
  4635. if ADockClient = nil then Exit;
  4636. { 得到这个ADockClient所在的窗体的PageControl }
  4637. PageControl := TCnTabPageControl(TCnTabDockHostForm(ADockClient.ParentForm).PageControl);
  4638. ResetTabPageControl(PageControl);
  4639. if PageControl <> nil then
  4640. PageControl.Invalidate;
  4641. end;
  4642. procedure TCnBasicTabServerOption.ResetDockControlOption;
  4643. var i: Integer;
  4644. ADockClient: TCnDockClient;
  4645. begin
  4646. { 循环DockStyle的DockBaseControlList列表,然后把每一个
  4647. TCnDockClient取出来,然后调用各自的函数重新设置它们的选项 }
  4648. for i := 0 to DockStyle.DockBaseControlListCount - 1 do
  4649. begin
  4650. if DockStyle.DockBaseControlLists[i] is TCnDockClient then
  4651. begin
  4652. ADockClient := TCnDockClient(DockStyle.DockBaseControlLists[i]);
  4653. if ADockClient.ParentForm is TCnTabDockHostForm then
  4654. begin
  4655. { 重新设置TCnDockClient的选项 }
  4656. ResetDockClientOption(ADockClient);
  4657. end;
  4658. end;
  4659. end;
  4660. end;
  4661. procedure TCnBasicTabServerOption.ResetDockServerOption(
  4662. ADockServer: TCnDockServer);
  4663. begin
  4664. { do nothing }
  4665. end;
  4666. procedure TCnBasicTabServerOption.ResetTabPageControl(
  4667. APage: TCnTabPageControl);
  4668. begin
  4669. if APage = nil then Exit;
  4670. APage.HotTrack := FHotTrack;
  4671. APage.TabPosition := FTabPosition;
  4672. end;
  4673. procedure TCnBasicTabServerOption.SetHotTrack(const Value: Boolean);
  4674. begin
  4675. if FHotTrack <> Value then
  4676. begin
  4677. FHotTrack := Value;
  4678. ResetDockControlOption;
  4679. end;
  4680. end;
  4681. procedure TCnBasicTabServerOption.SetTabPosition(
  4682. const Value: TTabPosition);
  4683. begin
  4684. if FTabPosition <> Value then
  4685. begin
  4686. FTabPosition := Value;
  4687. ResetDockControlOption;
  4688. end;
  4689. end;
  4690. { TCnBasicConjoinServerOption }
  4691. procedure TCnBasicConjoinServerOption.Assign(Source: TPersistent);
  4692. begin
  4693. if Source is TCnBasicConjoinServerOption then
  4694. begin
  4695. FGrabbersSize := TCnBasicConjoinServerOption(Source).FGrabbersSize;
  4696. FSplitterWidth := TCnBasicConjoinServerOption(Source).FSplitterWidth;
  4697. end;
  4698. inherited Assign(Source);
  4699. end;
  4700. constructor TCnBasicConjoinServerOption.Create(
  4701. ADockStyle: TCnBasicDockStyle);
  4702. begin
  4703. inherited Create(ADockStyle);
  4704. GrabbersSize := 12;
  4705. SplitterWidth := 4;
  4706. end;
  4707. destructor TCnBasicConjoinServerOption.Destroy;
  4708. begin
  4709. inherited Destroy;
  4710. end;
  4711. procedure TCnBasicConjoinServerOption.ResetConjoinPanel(
  4712. APanel: TCnConjoinPanel);
  4713. begin
  4714. APanel.CnDockManager.GrabberSize := FGrabbersSize;
  4715. APanel.CnDockManager.SplitterWidth := FSplitterWidth;
  4716. end;
  4717. procedure TCnBasicConjoinServerOption.ResetDockClientOption(
  4718. ADockClient: TCnDockClient);
  4719. var
  4720. ConjoinPanel: TCnConjoinPanel;
  4721. begin
  4722. if ADockClient = nil then Exit;
  4723. { 得到这个ADockClient所在的窗体的Panel }
  4724. ConjoinPanel := TCnConjoinPanel(TCnConjoinDockHostForm(ADockClient.ParentForm).Panel);
  4725. ResetConjoinPanel(ConjoinPanel);
  4726. ConjoinPanel.Invalidate;
  4727. end;
  4728. procedure TCnBasicConjoinServerOption.ResetDockControlOption;
  4729. var
  4730. i: Integer;
  4731. ADockServer: TCnDockServer;
  4732. ADockClient: TCnDockClient;
  4733. begin
  4734. if DockStyle = nil then Exit;
  4735. { 循环DockStyle的DockBaseControlList列表,然后把每一个TCnDockServer或者
  4736. TCnDockClient取出来,然后调用各自的函数重新设置它们的选项 }
  4737. for i := 0 to DockStyle.DockBaseControlListCount - 1 do
  4738. begin
  4739. if DockStyle.DockBaseControlLists[i] is TCnDockServer then
  4740. begin
  4741. { 重新设置TCnDockServer的选项 }
  4742. ADockServer := TCnDockServer(DockStyle.DockBaseControlLists[i]);
  4743. ResetDockServerOption(ADockServer);
  4744. end else if DockStyle.DockBaseControlLists[i] is TCnDockClient then
  4745. begin
  4746. ADockClient := TCnDockClient(DockStyle.DockBaseControlLists[i]);
  4747. if ADockClient.ParentForm.HostDockSite is TCnConjoinPanel then
  4748. begin
  4749. { 重新设置TCnDockClient的选项 }
  4750. ADockClient := FindDockClient(ADockClient.ParentForm.HostDockSite.Parent);
  4751. ResetDockClientOption(ADockClient);
  4752. end;
  4753. end;
  4754. end;
  4755. end;
  4756. procedure TCnBasicConjoinServerOption.ResetDockPanel(APanel: TCnDockPanel);
  4757. begin
  4758. APanel.CnDockManager.GrabberSize := FGrabbersSize;
  4759. APanel.CnDockManager.SplitterWidth := FSplitterWidth;
  4760. end;
  4761. procedure TCnBasicConjoinServerOption.ResetDockServerOption(
  4762. ADockServer: TCnDockServer);
  4763. var
  4764. i: Integer;
  4765. begin
  4766. // Panel必须不能为空
  4767. if ADockServer = nil then Exit;
  4768. for i := 0 to 3 do
  4769. begin
  4770. if ADockServer.DockPanel[i] = nil then
  4771. break;
  4772. ResetDockPanel(ADockServer.DockPanel[i]);
  4773. ADockServer.DockPanel[i].Invalidate;
  4774. end;
  4775. end;
  4776. procedure TCnBasicConjoinServerOption.SetGrabbersSize(
  4777. const Value: TGrabbersSize);
  4778. begin
  4779. if FGrabbersSize <> Value then
  4780. begin
  4781. FGrabbersSize := Value;
  4782. ResetDockControlOption;
  4783. end;
  4784. end;
  4785. procedure TCnBasicConjoinServerOption.SetGrabbersSize_WithoutChangeSystemInfo(
  4786. const Value: TGrabbersSize);
  4787. begin
  4788. FGrabbersSize := Value;
  4789. end;
  4790. procedure TCnBasicConjoinServerOption.SetSplitterWidth(
  4791. const Value: TSplitterWidth);
  4792. begin
  4793. if FSplitterWidth <> Value then
  4794. begin
  4795. FSplitterWidth := Value;
  4796. ResetDockControlOption;
  4797. end;
  4798. end;
  4799. procedure TCnBasicConjoinServerOption.SetSplitterWidth_WithoutChangeSystemInfo(
  4800. const Value: TSplitterWidth);
  4801. begin
  4802. FSplitterWidth := Value;
  4803. end;
  4804. { TCnAdvTabPageControl }
  4805. procedure TCnAdvTabPageControl.CMUnDockClient(
  4806. var Message: TCMUnDockClient);
  4807. begin
  4808. inherited;
  4809. end;
  4810. procedure TCnAdvTabPageControl.CustomDockDrop(Source: TCnDragDockObject; X,
  4811. Y: Integer);
  4812. begin
  4813. // 设置Client上的TCnDockClient控件的LastDockSite
  4814. if not IsLoading then
  4815. ResetDockClient(Source.Control, Source.TargetControl);
  4816. inherited;
  4817. end;
  4818. function TCnAdvTabPageControl.CustomUnDock(Source: TCnDragDockObject;
  4819. NewTarget: TWinControl; Client: TControl): Boolean;
  4820. begin
  4821. // 设置Client上的TCnDockClient控件的LastDockSite
  4822. if not IsLoading then
  4823. ResetDockClient(Source.Control, NewTarget);
  4824. Result := inherited CustomUnDock(Source, NewTarget, Client)
  4825. end;
  4826. destructor TCnAdvTabPageControl.Destroy;
  4827. var DockClient: TCnDockClient;
  4828. begin
  4829. DockClient := FindDockClient(Parent);
  4830. if (DockClient <> nil) and (DockClient.LastDockSite is TCnDockPanel) then
  4831. begin
  4832. with TCnDockPanel(DockClient.LastDockSite) do
  4833. begin
  4834. if UseDockManager and (CnDockManager <> nil) then
  4835. CnDockManager.RemoveControl(Self.Parent);
  4836. end;
  4837. end;
  4838. inherited;
  4839. end;
  4840. procedure TCnAdvTabPageControl.DockDrop(Source: TDragDockObject; X,
  4841. Y: Integer);
  4842. begin
  4843. // 设置Client上的TCnDockClient控件的LastDockSite
  4844. if not IsLoading then
  4845. ResetDockClient(Source.Control, TControl(Source.DragTarget));
  4846. inherited;
  4847. end;
  4848. function TCnAdvTabPageControl.DoUnDock(NewTarget: TWinControl;
  4849. Client: TControl): Boolean;
  4850. begin
  4851. // 设置Client上的TCnDockClient控件的LastDockSite
  4852. if not IsLoading then
  4853. ResetDockClient(Client, NewTarget);
  4854. Result := inherited DoUnDock(NewTarget, Client);
  4855. end;
  4856. { TCnAdvConjoinPanel }
  4857. procedure TCnAdvConjoinPanel.CMUnDockClient(var Message: TCMUnDockClient);
  4858. begin
  4859. inherited;
  4860. end;
  4861. procedure TCnAdvConjoinPanel.CustomDockDrop(Source: TCnDragDockObject; X,
  4862. Y: Integer);
  4863. begin
  4864. // 设置Client上的TCnDockClient控件的LastDockSite
  4865. if not IsLoading then
  4866. ResetDockClient(Source.Control, Source.TargetControl);
  4867. inherited;
  4868. end;
  4869. function TCnAdvConjoinPanel.CustomUnDock(Source: TCnDragDockObject;
  4870. NewTarget: TWinControl; Client: TControl): Boolean;
  4871. begin
  4872. // 设置Client上的TCnDockClient控件的LastDockSite
  4873. if not IsLoading then
  4874. ResetDockClient(Source.Control, NewTarget);
  4875. Result := inherited CustomUnDock(Source, NewTarget, Client)
  4876. end;
  4877. procedure TCnAdvConjoinPanel.DockDrop(Source: TDragDockObject; X,
  4878. Y: Integer);
  4879. begin
  4880. // 设置Client上的TCnDockClient控件的LastDockSite
  4881. if not IsLoading then
  4882. ResetDockClient(Source.Control, TControl(Source.DragTarget));
  4883. inherited;
  4884. end;
  4885. function TCnAdvConjoinPanel.DoUnDock(NewTarget: TWinControl;
  4886. Client: TControl): Boolean;
  4887. begin
  4888. // 设置Client上的TCnDockClient控件的LastDockSite
  4889. if not IsLoading then
  4890. ResetDockClient(Client, NewTarget);
  4891. Result := inherited DoUnDock(NewTarget, Client);
  4892. end;
  4893. { Initialization and cleanup }
  4894. procedure InitDockPresident;
  4895. var OSVERSIONINFO: TOSVERSIONINFO;
  4896. begin
  4897. { 创建一个TCnDockPresident的实例 }
  4898. if CnGlobalDockPresident <> nil then
  4899. CnGlobalDockPresident.Free;
  4900. CnGlobalDockPresident := TCnDockPresident.Create;
  4901. { 判断当前操作系统的版本, 是WindowsXP还是其他, 以后会用到的 }
  4902. OSVERSIONINFO.dwOSVersionInfoSize := sizeof(TOSVERSIONINFO);
  4903. GetVersionEx(OSVERSIONINFO);
  4904. IsWinXP := (OSVERSIONINFO.dwMajorVersion = 5) and (OSVERSIONINFO.dwMinorVersion = 1);
  4905. end;
  4906. procedure DoneDockPresident;
  4907. begin
  4908. { 释放这个TCnDockPresident的实例 }
  4909. if CnGlobalDockPresident <> nil then
  4910. begin
  4911. CnGlobalDockPresident.Free;
  4912. CnGlobalDockPresident := nil;
  4913. end;
  4914. end;
  4915. initialization
  4916. InitDockPresident;
  4917. finalization
  4918. DoneDockPresident;
  4919. end.