| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- {*******************************************************}
- { }
- { 停靠的基础控件 }
- { CnDockSupportControl 单元 }
- { }
- { 版权 (C) 2002,2003 鲁小班 }
- { }
- {*******************************************************}
- unit CnDockSupportControl;
- {* |<PRE>
- ================================================================================
- * 软件名称:不可视工具组件包停靠单元
- * 单元名称:停靠的基础控件单元
- * 单元作者:CnPack开发组 周益波(鲁小班)
- * 备 注:本单元由原作者授权CnPack开发组移植,已保留原作者版权信息
- * 开发平台:
- * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
- * 本 地 化:该单元中的字符串均符合本地化处理方式
- * 单元标识:$Id$
- * 修改记录:2007.07.13 V1.0
- * 移植单元
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses Messages, Windows, SysUtils, CommCtrl, Controls, Forms, Classes, ComCtrls,
- Graphics, ImgList, ExtCtrls, CnDockHashTable, CnDockTree;
- type
- TCnDragDockObject = class(TObject)
- private
- FMouseDeltaX: Double;
- FMouseDeltaY: Double;
- FControl: TControl;
- FDragTarget: Pointer;
- FDragPos: TPoint;
- FDropOnControl: TControl;
- FDropAlign: TAlign;
- FDragHandle: HWND;
- FDragTargetPos: TPoint;
- FCancelling: Boolean;
- FFloating: Boolean;
- FFrameWidth: Integer;
- FBrush: TBrush;
- FCtrlDown: Boolean;
- procedure SetBrush(const Value: TBrush);
- procedure SetDropAlign(const Value: TAlign);
- procedure SetDropOnControl(const Value: TControl);
- function GetTargetControl: TWinControl;
- procedure SetTargetControl(const Value: TWinControl);
- protected
- procedure DefaultDockImage(Erase: Boolean); virtual;
- procedure DrawDragRect(DoErase: Boolean); virtual;
- procedure GetBrush_PenSize_DrawRect(
- var ABrush: TBrush; var PenSize: Integer; var DrawRect: TRect; Erase: Boolean); virtual;
- function GetFrameWidth: Integer; virtual;
- procedure SetFrameWidth(const Value: Integer); virtual;
- procedure MouseMsg(var Msg: TMessage); virtual;
- function CanLeave(NewTarget: TWinControl): Boolean; virtual;
- public
- DockRect: TRect;
- EraseDockRect: TRect;
- constructor Create(AControl: TControl); virtual;
- destructor Destroy; override;
- procedure AdjustDockRect(var ARect: TRect); virtual;
- { ------------------------------------------------------------------------ }
- function Capture: HWND;
- { 查找鼠标位置的控件句柄 }
- function DragFindWindow(const Pos: TPoint): HWND; virtual;
- procedure ReleaseCapture(Handle: HWND);
- procedure EndDrag(Target: TObject; X, Y: Integer); virtual;
- procedure Finished(Target: TObject; X, Y: Integer; Accepted: Boolean); virtual;
- function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; virtual;
- function GetDragImages: TDragImageList; virtual;
- { ------------------------------------------------------------------------ }
- procedure DrawDragDockImage; virtual;
- procedure EraseDragDockImage; virtual;
- function GetDropCtl: TControl; virtual;
- property MouseDeltaX: Double read FMouseDeltaX write FMouseDeltaX;
- property MouseDeltaY: Double read FMouseDeltaY write FMouseDeltaY;
- property Control: TControl read FControl write FControl;
- property DragTarget: Pointer read FDragTarget write FDragTarget;
- property DragPos: TPoint read FDragPos write FDragPos;
- property DropOnControl: TControl read FDropOnControl write SetDropOnControl;
- property DropAlign: TAlign read FDropAlign write SetDropAlign;
- property DragHandle: HWND read FDragHandle write FDragHandle;
- property DragTargetPos: TPoint read FDragTargetPos write FDragTargetPos;
- property Cancelling: Boolean read FCancelling write FCancelling;
- property Floating: Boolean read FFloating write FFloating;
- property FrameWidth: Integer read GetFrameWidth write SetFrameWidth;
- property Brush: TBrush read FBrush write SetBrush;
- property CtrlDown: Boolean read FCtrlDown write FCtrlDown;
- property TargetControl: TWinControl read GetTargetControl write SetTargetControl;
- end;
- TCnCustomDockControl = class(TCustomControl)
- private
- function GetCnDockManager: ICnDockManager;
- procedure SetCnDockManager(const Value: ICnDockManager);
- protected
- procedure WndProc(var Message: TMessage); override;
- { ------------------------------------------------------------------------ }
- procedure CustomStartDock(var Source: TCnDragDockObject); virtual;
- procedure CustomGetSiteInfo(Source: TCnDragDockObject;
- Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
- var CanDock: Boolean); virtual;
- procedure CustomDockOver(Source: TCnDragDockObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean); virtual;
- procedure CustomPositionDockRect(Source: TCnDragDockObject; X, Y: Integer); virtual;
- procedure CustomDockDrop(Source: TCnDragDockObject; X, Y: Integer); virtual;
- procedure CustomEndDock(Target: TObject; X, Y: Integer); virtual;
- function CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; virtual;
- { ------------------------------------------------------------------------ }
- procedure CustomGetDockEdge(Source: TCnDragDockObject; MousePos: TPoint; var DropAlign: TAlign); virtual;
- public
- procedure UpdateCaption(Exclude: TControl); virtual;
- property DockManager;
- property CnDockManager: ICnDockManager read GetCnDockManager write SetCnDockManager;
- end;
- TCnCustomDockPanel = class(TCnCustomDockControl)
- protected
- function CreateDockManager: IDockManager; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- property DockSite;
- end;
- TCnDockCustomTabControl = class;
- TCnDockDrawTabEvent = procedure(Control: TCnDockCustomTabControl; TabIndex: Integer;
- const Rect: TRect; Active: Boolean) of object;
- TCnDockPageControl = class;
- TCnDockCustomTabControl = class(TCnCustomDockControl)
- private
- FHotTrack: Boolean;
- FImageChangeLink: TChangeLink;
- FImages: TCustomImageList;
- FMultiLine: Boolean;
- FMultiSelect: Boolean;
- FOwnerDraw: Boolean;
- FRaggedRight: Boolean;
- FSaveTabIndex: Integer;
- FSaveTabs: TStringList;
- FScrollOpposite: Boolean;
- FStyle: TTabStyle;
- FTabPosition: TTabPosition;
- FTabs: TStrings;
- FTabSize: TSmallPoint;
- FUpdating: Boolean;
- FSavedAdjustRect: TRect;
- FOnChange: TNotifyEvent;
- FOnChanging: TTabChangingEvent;
- FOnDrawTab: TCnDockDrawTabEvent;
- FOnGetImageIndex: TTabGetImageEvent;
- function GetDisplayRect: TRect;
- function GetTabIndex: Integer;
- procedure ImageListChange(Sender: TObject);
- function InternalSetMultiLine(Value: Boolean): Boolean;
- procedure SetMultiLine(Value: Boolean);
- procedure SetMultiSelect(Value: Boolean);
- procedure SetOwnerDraw(Value: Boolean);
- procedure SetRaggedRight(Value: Boolean);
- procedure SetScrollOpposite(Value: Boolean);
- procedure SetStyle(Value: TTabStyle);
- procedure SetTabIndex(Value: Integer);
- procedure SetTabs(Value: TStrings);
- procedure SetTabWidth(Value: Smallint);
- procedure TabsChanged;
- procedure UpdateTabSize;
- procedure CMFontChanged(var Message); message CM_FONTCHANGED;
- procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE;
- procedure CMTabStopChanged(var Message: TMessage); message CM_TABSTOPCHANGED;
- procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
- procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
- procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
- procedure TCMAdjustRect(var Message: TMessage); message TCM_ADJUSTRECT;
- procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
- procedure WMNotifyFormat(var Message: TMessage); message WM_NOTIFYFORMAT;
- procedure WMSize(var Message: TMessage); message WM_SIZE;
- protected
- procedure AdjustClientRect(var Rect: TRect); override;
- function CanChange: Boolean; dynamic;
- function CanShowTab(TabIndex: Integer): Boolean; virtual;
- procedure Change; dynamic;
- procedure CreateParams(var Params: TCreateParams); override;
- procedure CreateWnd; override;
- procedure DrawTab(TabIndex: Integer; const Rect: TRect; Active: Boolean); virtual;
- function GetImageIndex(TabIndex: Integer): Integer; virtual;
- procedure Loaded; override;
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure PaintWindow(DC: HDC); override;
- procedure SetHotTrack(Value: Boolean); virtual;
- procedure SetImages(Value: TCustomImageList); virtual;
- procedure SetTabHeight(Value: Smallint); virtual;
- procedure SetTabPosition(Value: TTabPosition); virtual;
- procedure UpdateTabImages;
- property DisplayRect: TRect read GetDisplayRect;
- property HotTrack: Boolean read FHotTrack write SetHotTrack default False;
- property Images: TCustomImageList read FImages write SetImages;
- property MultiLine: Boolean read FMultiLine write SetMultiLine default False;
- property MultiSelect: Boolean read FMultiSelect write SetMultiSelect default False;
- property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw default False;
- property RaggedRight: Boolean read FRaggedRight write SetRaggedRight default False;
- property ScrollOpposite: Boolean read FScrollOpposite
- write SetScrollOpposite default False;
- property Style: TTabStyle read FStyle write SetStyle default tsTabs;
- property TabHeight: Smallint read FTabSize.Y write SetTabHeight default 0;
- property TabIndex: Integer read GetTabIndex write SetTabIndex default -1;
- property TabPosition: TTabPosition read FTabPosition write SetTabPosition
- default tpTop;
- property Tabs: TStrings read FTabs write SetTabs;
- property TabWidth: Smallint read FTabSize.X write SetTabWidth default 0;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnChanging: TTabChangingEvent read FOnChanging write FOnChanging;
- property OnDrawTab: TCnDockDrawTabEvent read FOnDrawTab write FOnDrawTab;
- property OnGetImageIndex: TTabGetImageEvent read FOnGetImageIndex write FOnGetImageIndex;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function IndexOfTabAt(X, Y: Integer): Integer;
- function GetHitTestInfoAt(X, Y: Integer): THitTests;
- function TabRect(Index: Integer): TRect;
- function RowCount: Integer;
- procedure ScrollTabs(Delta: Integer);
- property TabStop default True;
- end;
- TCnDockTabSheet = class(TWinControl)
- private
- FImageIndex: TImageIndex;
- FPageControl: TCnDockPageControl;
- FTabVisible: Boolean;
- FTabShowing: Boolean;
- FHighlighted: Boolean;
- FOnHide: TNotifyEvent;
- FOnShow: TNotifyEvent;
- function GetPageIndex: Integer;
- function GetTabIndex: Integer;
- procedure SetHighlighted(Value: Boolean);
- procedure SetImageIndex(Value: TImageIndex);
- procedure SetPageIndex(Value: Integer);
- procedure SetTabShowing(Value: Boolean);
- procedure SetTabVisible(Value: Boolean);
- procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
- procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
- protected
- procedure CreateParams(var Params: TCreateParams); override;
- procedure SetPageControl(APageControl: TCnDockPageControl); virtual;
- procedure ReadState(Reader: TReader); override;
- procedure DoHide; dynamic;
- procedure DoShow; dynamic;
- procedure UpdateTabShowing; dynamic;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- property PageControl: TCnDockPageControl read FPageControl write SetPageControl;
- property TabIndex: Integer read GetTabIndex;
- published
- property Caption;
- property Height stored False;
- property Highlighted: Boolean read FHighlighted write SetHighlighted default False;
- property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default 0;
- property Left stored False;
- property PageIndex: Integer read GetPageIndex write SetPageIndex stored False;
- property TabVisible: Boolean read FTabVisible write SetTabVisible default True;
- property Top stored False;
- property Visible stored False;
- property Width stored False;
- property OnHide: TNotifyEvent read FOnHide write FOnHide;
- property OnShow: TNotifyEvent read FOnShow write FOnShow;
- end;
- TCnDockTabSheetClass = class of TCnDockTabSheet;
- TCnDockPageControl = class(TCnDockCustomTabControl)
- private
- FPages: TList;
- FActivePage: TCnDockTabSheet;
- FNewDockSheet: TCnDockTabSheet;
- FUndockingPage: TCnDockTabSheet;
- FCnDockTabSheetClass: TCnDockTabSheetClass;
- procedure ChangeActivePage(Page: TCnDockTabSheet);
- procedure DeleteTab(Page: TCnDockTabSheet; Index: Integer);
- function GetActivePageIndex: Integer;
- function GetPage(Index: Integer): TCnDockTabSheet;
- function GetPageCount: Integer;
- procedure InsertPage(Page: TCnDockTabSheet);
- procedure InsertTab(Page: TCnDockTabSheet);
- procedure MoveTab(CurIndex, NewIndex: Integer);
- procedure RemovePage(Page: TCnDockTabSheet);
- procedure SetActivePageIndex(const Value: Integer);
- procedure UpdateTab(Page: TCnDockTabSheet);
- procedure UpdateTabHighlights;
- procedure CMDesignHitTest(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
- procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
- procedure CMDockClient(var Message: TCMDockClient); message CM_DOCKCLIENT;
- procedure CMDockNotification(var Message: TCMDockNotification); message CM_DOCKNOTIFICATION;
- procedure CMUnDockClient(var Message: TCMUnDockClient); message CM_UNDOCKCLIENT;
- procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
- procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
- procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
- procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
- procedure WMRButtonDblClk(var Message: TWMRButtonDblClk); message WM_RBUTTONDBLCLK;
- procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
- procedure WMMButtonDown(var Message: TWMMButtonDown); message WM_MBUTTONDOWN;
- procedure WMMButtonDblClk(var Message: TWMMButtonDblClk); message WM_MBUTTONDBLCLK;
- procedure WMMButtonUp(var Message: TWMMButtonUp); message WM_MBUTTONUP;
- protected
- function CanShowTab(TabIndex: Integer): Boolean; override;
- procedure Change; override;
- procedure DoAddDockClient(Client: TControl; const ARect: TRect); override;
- procedure DockOver(Source: TDragDockObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean); override;
- function DoMouseEvent(var Message: TWMMouse; Control: TControl): TWMNCHitMessage; virtual;
- procedure DoRemoveDockClient(Client: TControl); override;
- function GetDockClientFromMousePos(MousePos: TPoint): TControl; virtual;
- function GetImageIndex(TabIndex: Integer): Integer; override;
- function GetPageFromDockClient(Client: TControl): TCnDockTabSheet;
- procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect;
- MousePos: TPoint; var CanDock: Boolean); override;
- procedure Loaded; override;
- procedure SetActivePage(Page: TCnDockTabSheet); virtual;
- procedure ShowControl(AControl: TControl); override;
- procedure UpdateActivePage; virtual;
- public
- procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function FindNextPage(CurPage: TCnDockTabSheet;
- GoForward, CheckTabVisible: Boolean): TCnDockTabSheet;
- procedure SelectNextPage(GoForward: Boolean; CheckTabVisible: Boolean = True);
- procedure SetChildOrder(Child: TComponent; Order: Integer); override;
- property ActivePage: TCnDockTabSheet read FActivePage write SetActivePage;
- property ActivePageIndex: Integer read GetActivePageIndex
- write SetActivePageIndex;
- property PageCount: Integer read GetPageCount;
- property Pages[Index: Integer]: TCnDockTabSheet read GetPage;
- property PageSheets: TList read FPages;
- property CnDockTabSheetClass: TCnDockTabSheetClass read FCnDockTabSheetClass
- write FCnDockTabSheetClass;
- end;
- TCnDockTabStrings = class(TStrings)
- private
- FTabControl: TCnDockCustomTabControl;
- protected
- function Get(Index: Integer): string; override;
- function GetCount: Integer; override;
- function GetObject(Index: Integer): TObject; override;
- procedure Put(Index: Integer; const S: string); override;
- procedure PutObject(Index: Integer; AObject: TObject); override;
- procedure SetUpdateState(Updating: Boolean); override;
- public
- procedure Clear; override;
- procedure Delete(Index: Integer); override;
- procedure Insert(Index: Integer; const S: string); override;
- end;
- TDragOperation = (dopNone, dopDrag, dopDock);
- PSiteInfoRec = ^TSiteInfoRec;
- TSiteInfoRec = record
- Site: TWinControl;
- TopParent: HWND;
- end;
- TSiteList = class(TList)
- public
- procedure AddSite(ASite: TWinControl);
- procedure Clear; override;
- function Find(ParentWnd: Hwnd; var Index: Integer): Boolean;
- function GetTopSite: TWinControl;
- end;
- TCnDockPresident = class(TObject)
- private
- FDockServersList: TList; //存放停靠服务器的列表
- FDockClientsList: TList; //存放停靠客户的列表
- FDockServersHash: TCnDockControlHashTable; //存放停靠服务器的散列
- FDockClientsHash: TCnDockControlHashTable; //存放停靠客户的散列
- FDockableFormList: TList; //所有停靠服务器的列表
- FLoadCount: Integer;
- FSaveCount: Integer;
- procedure BeginLoad;
- procedure EndLoad;
- procedure BeginSave;
- procedure EndSave;
- public
- { ------------------------------------------------------------------------ }
- DragControl: TControl;
- DragObject: TCnDragDockObject;
- DragFreeObject: Boolean;
- DragCapture: HWND;
- DragStartPos: TPoint;
- DragSaveCursor: HCURSOR;
- DragThreshold: Integer;
- ActiveDrag: TDragOperation;
- DragImageList: TDragImageList;
- DockSiteList: TList;
- QualifyingSites: TSiteList;
- { ------------------------------------------------------------------------ }
- procedure CalcDockSizes(Control: TControl);
- // constructor Create(AOwner: TComponent); override;
- constructor Create; virtual;
- destructor Destroy; override;
- procedure AddDockServerToDockManager(AControl: TControl);
- procedure AddDockClientToDockManager(AControl: TControl);
- procedure RemoveDockServerFromDockManager(AControl: TControl);
- procedure RemoveDockClientFromDockManager(AControl: TControl);
- function FindDockServerForm(AName: string): TControl;
- function FindDockClientForm(AName: string): TControl;
- function FindDockControlForm(AName: string): TControl;
- function IsLoading: Boolean;
- function IsSaving: Boolean;
- { 显示窗体 }
- procedure ShowDockForm(DockWindow: TWinControl);
- { 隐藏窗体 }
- procedure HideDockForm(DockWindow: TControl);
- { 获得窗体的可见性 }
- function GetFormVisible(DockWindow: TWinControl): Boolean;
- { 设置分页的服务窗体的显示风格 }
- procedure SetTabDockHostBorderStyle(Value: TFormBorderStyle);
- { 设置平铺的服务窗体的显示风格 }
- procedure SetConjoinDockHostBorderStyle(Value: TFormBorderStyle);
- { 把停靠窗体的信息保存进文件 }
- procedure SaveDockTreeToFile(FileName: string);
- { 从文件里读出停靠窗体的信息 }
- procedure LoadDockTreeFromFile(FileName: string);
- { 把停靠窗体的信息保存进注册表 }
- procedure SaveDockTreeToReg(RootKey: DWORD; RegPath: string);
- { 从注册表里读出停靠窗体的信息 }
- procedure LoadDockTreeFromReg(RootKey: DWORD; RegPath: string);
- { 当鼠标左键按下的时候,开始拖动 }
- procedure BeginDrag(Control: TControl;
- Immediate: Boolean; Threshold: Integer = -1); virtual;
- { 初始化停靠控件 }
- procedure DragInitControl(Control: TControl;
- Immediate: Boolean; Threshold: Integer); virtual;
- { 初始化拖动 }
- procedure DragInit(ADragObject: TCnDragDockObject;
- Immediate: Boolean; Threshold: Integer); virtual;
- { 当鼠标移动的时候,调用DragTo }
- procedure DragTo(const Pos: TPoint); virtual;
- { 当鼠标释放的时候,调用DragDone }
- procedure DragDone(Drop: Boolean); virtual;
- { 取消拖动操作 }
- procedure CancelDrag; virtual;
- { 重新设置光标的形状 }
- procedure ResetCursor; virtual;
- { 查找可能的停靠服务器,Handle是这个服务器的句柄 }
- function DragFindTarget(const Pos: TPoint; var Handle: HWND;
- DragKind: TDragKind; Client: TControl): Pointer; virtual;
- { 调用控件的OnxxxGetSiteInfo方法 }
- procedure DoGetSiteInfo(Target, Client: TControl; var InfluenceRect: TRect;
- MousePos: TPoint; var CanDock: Boolean); virtual;
- { 调用控件的OnxxxDockOver方法 }
- function DoDockOver(DragState: TDragState): Boolean; virtual;
- { 调用控件的OnxxxDockDrop方法 }
- procedure DoDockDrop(Source: TCnDragDockObject; Pos: TPoint); virtual;
- { 调用控件的OnxxxUnDock方法 }
- function DoUnDock(Source: TCnDragDockObject; Target: TWinControl; Client: TControl): Boolean; virtual;
- { 调用控件的OnxxxEndDock方法 }
- procedure DoEndDrag(Target: TObject; X, Y: Integer); virtual;
- { 查找鼠标位置的控件句柄 }
- function DragFindWindow(const Pos: TPoint): HWND; virtual;
- { 获得鼠标位置的控件对象 }
- function GetDockSiteAtPos(MousePos: TPoint; Client: TControl): TWinControl; virtual;
- { 获得鼠标位置的控件的排列位置 }
- procedure DoGetDockEdge(Target: TControl; MousePos: TPoint; var DropAlign: TAlign); virtual;
- { 注册停靠服务器 }
- procedure RegisterDockSite(Site: TWinControl; DoRegister: Boolean); virtual;
- property DockServersList: TList read FDockServersList;
- property DockClientsList: TList read FDockClientsList;
- property DockServersHash: TCnDockControlHashTable
- read FDockServersHash;
- property DockClientsHash: TCnDockControlHashTable
- read FDockClientsHash;
- property DockableFormList: TList read FDockableFormList;
- end;
- TCustomDockPanelSplitter = class(TCustomControl)
- private
- FActiveControl: TWinControl;
- FAutoSnap: Boolean;
- FBeveled: Boolean;
- FBrush: TBrush;
- FControl: TControl;
- FDownPos: TPoint;
- FLineDC: HDC;
- FLineVisible: Boolean;
- FMinSize: NaturalNumber;
- FMaxSize: Integer;
- FNewSize: Integer;
- FOldKeyDown: TKeyEvent;
- FOldSize: Integer;
- FPrevBrush: HBrush;
- FResizeStyle: TResizeStyle;
- FSplit: Integer;
- FOnCanResize: TCanResizeEvent;
- FOnMoved: TNotifyEvent;
- FOnPaint: TNotifyEvent;
- procedure AllocateLineDC;
- procedure CalcSplitSize(X, Y: Integer; var NewSize, Split: Integer);
- procedure DrawLine;
- procedure FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
- procedure ReleaseLineDC;
- procedure SetBeveled(Value: Boolean);
- procedure UpdateControlSize;
- procedure UpdateSize(X, Y: Integer);
- protected
- function CanResize(var NewSize: Integer): Boolean; reintroduce; virtual;
- function DoCanResize(var NewSize: Integer): Boolean; virtual;
- function FindControl: TControl; virtual;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer); override;
- procedure Paint; override;
- procedure RequestAlign; override;
- procedure StopSizing; dynamic;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- property Canvas;
- published
- property Align default alLeft;
- property AutoSnap: Boolean read FAutoSnap write FAutoSnap default True;
- property Beveled: Boolean read FBeveled write SetBeveled default False;
- property Color;
- property Constraints;
- property MinSize: NaturalNumber read FMinSize write FMinSize default 30;
- property ParentColor;
- property ResizeStyle: TResizeStyle read FResizeStyle write FResizeStyle
- default rsPattern;
- property Visible;
- property OnCanResize: TCanResizeEvent read FOnCanResize write FOnCanResize;
- property OnMoved: TNotifyEvent read FOnMoved write FOnMoved;
- property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
- end;
- implementation
- uses
- Consts, ComStrs, CnDockGlobal, CnDockFormControl, CnDockSupportProc;
- type
- TCnNCButtonProc = procedure(Message: TWMNCHitMessage; Button: TMouseButton;
- MouseStation: TMouseStation) of object;
- function ButtonEvent(Page: TCnDockPageControl; Message: TWMMouse;
- Button: TMouseButton; MouseStation: TMouseStation; Proc: TCnNCButtonProc): TControl;
- begin
- { 查找到鼠标所在位置的TCnDockTabSheet上的Control }
- Result := Page.GetDockClientFromMousePos(SmallPointToPoint(Message.Pos));
- if (Result <> nil) and Assigned(Proc) then
- begin
- { 查找到DockCtl上的TCnDockClient,然后把她赋值给全局变量GlobalDockClient }
- GlobalDockClient := FindDockClient(Result);
- { 调用全局变量GlobalDockClient的DoNCButtonDown方法 }
- Proc(Page.DoMouseEvent(Message, Page), Button, MouseStation);
- end;
- end;
- type
- TCnControlAccess = class(TControl);
- TCnWinControlAccess = class(TWinControl);
- PCheckTargetInfo = ^TCheckTargetInfo;
- TCheckTargetInfo = record
- ClientWnd, TargetWnd: HWnd;
- CurrentWnd: HWnd;
- MousePos: TPoint;
- Found: Boolean;
- end;
- procedure TabControlError(const S: string);
- begin
- raise EListError.Create(S);
- end;
- procedure SetComCtlStyle(Ctl: TWinControl; Value: Integer; UseStyle: Boolean);
- var
- Style: Integer;
- begin
- if Ctl.HandleAllocated then
- begin
- Style := GetWindowLong(Ctl.Handle, GWL_STYLE);
- if not UseStyle then Style := Style and not Value
- else Style := Style or Value;
- SetWindowLong(Ctl.Handle, GWL_STYLE, Style);
- end;
- end;
- function IsBeforeTargetWindow(Window: HWnd; Data: Longint): Bool; stdcall;
- var
- R: TRect;
- begin
- if Window = PCheckTargetInfo(Data)^.TargetWnd then
- Result := False
- else
- begin
- if PCheckTargetInfo(Data)^.CurrentWnd = 0 then
- begin
- GetWindowRect(Window, R);
- if PtInRect(R, PCheckTargetInfo(Data)^.MousePos) then
- PCheckTargetInfo(Data)^.CurrentWnd := Window;
- end;
- if Window = PCheckTargetInfo(Data)^.CurrentWnd then
- begin
- Result := False;
- PCheckTargetInfo(Data)^.Found := True;
- end
- else if Window = PCheckTargetInfo(Data)^.ClientWnd then
- begin
- Result := True;
- PCheckTargetInfo(Data)^.CurrentWnd := 0; // Look for next window
- end
- else
- Result := True;
- end;
- end;
- { TCnDragDockObject }
- procedure TCnDragDockObject.AdjustDockRect(var ARect: TRect);
- var
- DeltaX, DeltaY: Integer;
- function AbsMin(Value1, Value2: Integer): Integer;
- begin
- if Abs(Value1) < Abs(Value2) then Result := Value1
- else Result := Value2;
- end;
- begin
- { Make sure dock rect is touching mouse point }
- if (ARect.Left > FDragPos.x) or (ARect.Right < FDragPos.x) then
- DeltaX := AbsMin(ARect.Left - FDragPos.x, ARect.Right - FDragPos.x)
- else DeltaX := 0;
- if (ARect.Top > FDragPos.y) or (ARect.Bottom < FDragPos.y) then
- DeltaY := AbsMin(ARect.Top - FDragPos.y, ARect.Bottom - FDragPos.y)
- else DeltaY := 0;
- if (DeltaX <> 0) or (DeltaY <> 0) then
- OffsetRect(DockRect, -DeltaX, -DeltaY);
- end;
- function TCnDragDockObject.CanLeave(NewTarget: TWinControl): Boolean;
- begin
- Result := NewTarget <> TWinControl(FDragTarget);
- end;
- function TCnDragDockObject.Capture: HWND;
- begin
- Result := AllocateHWND(MouseMsg);
- SetCapture(Result);
- end;
- constructor TCnDragDockObject.Create(AControl: TControl);
- begin
- FControl := AControl;
- FBrush := TBrush.Create;
- FBrush.Bitmap := AllocPatternBitmap(clBlack, clWhite);
- FFrameWidth := 4;
- FCtrlDown := False;
- end;
- procedure TCnDragDockObject.DefaultDockImage(Erase: Boolean);
- var
- DesktopWindow: HWND;
- DC: HDC;
- OldBrush: HBrush;
- DrawRect: TRect;
- PenSize: Integer;
- ABrush: TBrush;
- begin
- { 获得画刷句柄,画笔宽度和绘画区域 }
- GetBrush_PenSize_DrawRect(ABrush, PenSize, DrawRect, Erase);
- DesktopWindow := GetDesktopWindow;
- DC := GetDCEx(DesktopWindow, 0, DCX_CACHE or DCX_LOCKWINDOWUPDATE);
- try
- OldBrush := SelectObject(DC, ABrush.Handle);
- with DrawRect do
- begin
- PatBlt(DC, Left + PenSize, Top, Right - Left - PenSize, PenSize, PATINVERT);
- PatBlt(DC, Right - PenSize, Top + PenSize, PenSize, Bottom - Top - PenSize, PATINVERT);
- PatBlt(DC, Left, Bottom - PenSize, Right - Left - PenSize, PenSize, PATINVERT);
- PatBlt(DC, Left, Top, PenSize, Bottom - Top - PenSize, PATINVERT);
- end;
- SelectObject(DC, OldBrush);
- finally
- ReleaseDC(DesktopWindow, DC);
- end;
- end;
- destructor TCnDragDockObject.Destroy;
- begin
- if FBrush <> nil then
- begin
- FBrush.Free;
- FBrush := nil;
- end;
- inherited;
- end;
- function TCnDragDockObject.DragFindWindow(const Pos: TPoint): HWND;
- var WinControl: TWinControl;
- begin
- { Result := WindowFromPoint(Pos);
- while Result <> 0 do
- if not IsDelphiHandle(Result) then Result := GetParent(Result)
- else Exit;}
- // FindControl
- WinControl := FindVCLWindow(Pos);
- if WinControl <> nil then
- Result := WinControl.Handle
- else Result := 0;
- end;
- procedure TCnDragDockObject.DrawDragDockImage;
- begin
- DefaultDockImage(False);
- end;
- procedure TCnDragDockObject.DrawDragRect(DoErase: Boolean);
- begin
- if not CompareMem(@DockRect, @EraseDockRect, SizeOf(TRect)) then
- begin
- if DoErase then EraseDragDockImage;
- DrawDragDockImage;
- EraseDockRect := DockRect;
- end;
- end;
- procedure TCnDragDockObject.EndDrag(Target: TObject; X, Y: Integer);
- begin
- CnGlobalDockPresident.DoEndDrag(Target, X, Y);
- end;
- procedure TCnDragDockObject.EraseDragDockImage;
- begin
- DefaultDockImage(True);
- end;
- procedure TCnDragDockObject.Finished(Target: TObject; X, Y: Integer;
- Accepted: Boolean);
- begin
- if not Accepted then
- begin
- Target := nil;
- end;
- EndDrag(Target, X, Y);
- end;
- procedure TCnDragDockObject.GetBrush_PenSize_DrawRect(
- var ABrush: TBrush; var PenSize: Integer; var DrawRect: TRect; Erase: Boolean);
- begin
- ABrush := Brush;
- PenSize := FrameWidth;
- if Erase then DrawRect := EraseDockRect
- else DrawRect := DockRect;
- end;
- function TCnDragDockObject.GetDragCursor(Accepted: Boolean; X,
- Y: Integer): TCursor;
- begin
- Result := crDefault;
- end;
- function TCnDragDockObject.GetDragImages: TDragImageList;
- begin
- Result := nil;
- end;
- function TCnDragDockObject.GetDropCtl: TControl;
- var
- NextCtl: TControl;
- TargetCtl: TWinControl;
- CtlIdx: Integer;
- function GetDockClientsIndex: Integer;
- begin
- for Result := 0 to TCnWinControlAccess(TargetCtl).DockClientCount - 1 do
- begin
- if TCnWinControlAccess(TargetCtl).DockClients[Result] = NextCtl then
- Exit;
- end;
- Result := -1;
- end;
- begin
- Result := nil;
- TargetCtl := DragTarget;
- if (TargetCtl = nil) or not TCnWinControlAccess(TargetCtl).UseDockManager or
- (TargetCtl.DockClientCount = 0) or
- ((TargetCtl.DockClientCount = 1) and
- (TCnWinControlAccess(TargetCtl).DockClients[0] = Control)) then
- Exit;
- NextCtl := FindDragTarget(DragPos, False);
- while (NextCtl <> nil) and (NextCtl <> TargetCtl) do
- begin
- CtlIdx := GetDockClientsIndex;
- if CtlIdx <> -1 then
- begin
- Result := TargetCtl.DockClients[CtlIdx];
- Exit;
- end
- else
- NextCtl := NextCtl.Parent;
- end;
- end;
- function TCnDragDockObject.GetFrameWidth: Integer;
- begin
- Result := FFrameWidth;
- end;
- function TCnDragDockObject.GetTargetControl: TWinControl;
- begin
- if FDragTarget <> nil then
- Result := TWinControl(FDragTarget)
- else Result := nil;
- end;
- procedure TCnDragDockObject.MouseMsg(var Msg: TMessage);
- var
- P: TPoint;
- begin
- try
- case Msg.Msg of
- WM_MOUSEMOVE:
- begin
- P := SmallPointToPoint(TWMMouse(Msg).Pos);
- ClientToScreen(CnGlobalDockPresident.DragCapture, P);
- CnGlobalDockPresident.DragTo(P);
- end;
- WM_CAPTURECHANGED:
- begin
- CnGlobalDockPresident.DragDone(False);
- end;
- WM_LBUTTONUP, WM_RBUTTONUP:
- if not GlobalDockClient.CanFloat then
- begin
- if (TargetControl = nil) and (GlobalDockClient.ParentForm.HostDockSite = nil) then
- CnGlobalDockPresident.DragDone(True)
- else
- CnGlobalDockPresident.DragDone(TargetControl <> nil);
- end
- else
- CnGlobalDockPresident.DragDone(True);
- { Forms.IsKeyMsg sends WM_KEYxxx messages here (+CN_BASE) when a
- TPUtilWindow has the mouse capture. }
- CN_KEYUP:
- if Msg.WParam = VK_CONTROL then
- begin
- FCtrlDown := False;
- CnGlobalDockPresident.DragTo(CnGlobalDockPresident.DragObject.DragPos);
- end;
- CN_KEYDOWN:
- begin
- case Msg.WParam of
- VK_CONTROL: // 当按下了Ctrl键的后,窗体不允许停靠
- begin
- FCtrlDown := True;
- CnGlobalDockPresident.DragTo(CnGlobalDockPresident.DragObject.DragPos);
- end;
- VK_ESCAPE:
- begin
- { Consume keystroke and cancel drag operation }
- Msg.Result := 1;
- CnGlobalDockPresident.DragDone(False);
- end;
- end;
- end;
- end;
- except
- if CnGlobalDockPresident.DragControl <> nil then
- CnGlobalDockPresident.DragDone(False);
- raise;
- end;
- end;
- procedure TCnDragDockObject.ReleaseCapture(Handle: HWND);
- begin
- Windows.ReleaseCapture;
- DeallocateHWND(Handle);
- end;
- procedure TCnDragDockObject.SetBrush(const Value: TBrush);
- begin
- FBrush.Assign(Value);
- end;
- procedure TCnDragDockObject.SetDropAlign(const Value: TAlign);
- begin
- if FDropAlign <> Value then
- FDropAlign := Value;
- end;
- procedure TCnDragDockObject.SetDropOnControl(const Value: TControl);
- begin
- FDropOnControl := Value;
- end;
- procedure TCnDragDockObject.SetFrameWidth(const Value: Integer);
- begin
- FFrameWidth := Value;
- end;
- procedure TCnDragDockObject.SetTargetControl(const Value: TWinControl);
- begin
- FDragTarget := Value;
- end;
- { TCnCustomDockControl }
- function TCnCustomDockControl.GetCnDockManager: ICnDockManager;
- begin
- Result := ICnDockManager(DockManager);
- end;
- procedure TCnCustomDockControl.SetCnDockManager(const Value: ICnDockManager);
- begin
- DockManager := Value;
- end;
- procedure TCnCustomDockControl.CustomDockDrop(Source: TCnDragDockObject; X,
- Y: Integer);
- var
- DestRect: TRect;
- Form: TCustomForm;
- begin
- { Map DockRect to dock site's client coordinates }
- DestRect := Source.DockRect;
- MapWindowPoints(0, Handle, DestRect, 2);
- DisableAlign;
- try
- Source.Control.Dock(Self, DestRect);
- if UseDockManager and (DockManager <> nil) then
- begin
- DockManager.InsertControl(Source.Control,
- Source.DropAlign, Source.DropOnControl);
- end;
- finally
- EnableAlign;
- end;
- Form := GetParentForm(Self);
- if Form <> nil then Form.BringToFront;
- { -------------------------------------------------------------------------- }
- if Source.Control is TForm then
- begin
- { 下面一行代码是为了防止窗体的标题栏和窗体上面的控件的内容被清空 }
- TForm(Source.Control).ActiveControl := nil;
- { ------------------------------------------------------------------------ }
- SetDockSite(TForm(Source.Control), False);
- end;
- end;
- procedure TCnCustomDockControl.CustomDockOver(Source: TCnDragDockObject; X,
- Y: Integer; State: TDragState; var Accept: Boolean);
- begin
- CustomPositionDockRect(Source, X, Y);
- end;
- procedure TCnCustomDockControl.CustomEndDock(Target: TObject; X,
- Y: Integer);
- begin
- end;
- procedure TCnCustomDockControl.CustomGetDockEdge(Source: TCnDragDockObject;
- MousePos: TPoint; var DropAlign: TAlign);
- begin
- DropAlign := GetDockEdge(MousePos);
- end;
- procedure TCnCustomDockControl.CustomGetSiteInfo(Source: TCnDragDockObject;
- Client: TControl; var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
- begin
- GetWindowRect(Handle, InfluenceRect);
- InflateRect(InfluenceRect, DefExpandoRect, DefExpandoRect);
- end;
- procedure TCnCustomDockControl.CustomPositionDockRect(
- Source: TCnDragDockObject; X, Y: Integer);
- var
- NewWidth, NewHeight: Integer;
- TempX, TempY: Double;
- begin
- with Source do
- begin
- if (DragTarget = nil) or (not TCnWinControlAccess(DragTarget).UseDockManager) then
- begin
- NewWidth := Control.UndockWidth;
- NewHeight := Control.UndockHeight;
- // Drag position for dock rect is scaled relative to control's click point.
- TempX := DragPos.X - ((NewWidth) * MouseDeltaX);
- TempY := DragPos.Y - ((NewHeight) * MouseDeltaY);
- with DockRect do
- begin
- Left := Round(TempX);
- Top := Round(TempY);
- Right := Left + NewWidth;
- Bottom := Top + NewHeight;
- end;
- { Allow DragDockObject final say on this new dock rect }
- AdjustDockRect(DockRect);
- end
- else begin
- GetWindowRect(TargetControl.Handle, DockRect);
- if TCnWinControlAccess(DragTarget).UseDockManager then
- begin
- if TargetControl is TCnCustomDockPanel then
- begin
- if (TCnCustomDockPanel(DragTarget).CnDockManager <> nil) then
- TCnCustomDockPanel(DragTarget).CnDockManager.PositionDockRect(Control,
- DropOnControl, DropAlign, DockRect);
- end;
- end;
- end;
- end;
- end;
- procedure TCnCustomDockControl.CustomStartDock(
- var Source: TCnDragDockObject);
- begin
- end;
- function TCnCustomDockControl.CustomUnDock(Source: TCnDragDockObject; NewTarget: TWinControl;
- Client: TControl): Boolean;
- begin
- Result := (Perform(CM_UNDOCKCLIENT, Integer(NewTarget), Integer(Client)) = 0);
- end;
- procedure TCnCustomDockControl.UpdateCaption(Exclude: TControl);
- var i: Integer;
- Host: TCnDockableForm;
- begin
- if Parent is TCnDockableForm then
- begin
- Host := TCnDockableForm(Parent);
- Host.Caption := '';
- { 更新本身的Caption }
- for I := 0 to Host.DockableControl.DockClientCount - 1 do
- begin
- if Host.DockableControl.DockClients[I].Visible and (Host.DockableControl.DockClients[I] <> Exclude) then
- Host.Caption := Host.Caption + TCustomForm(Host.DockableControl.DockClients[I]).Caption + gs_CnStringSplitter;
- end;
- { 更新TCnTabPageControl的标签 }
- if (Host.HostDockSite is TCnTabPageControl) then
- begin
- with TCnTabPageControl(Host.HostDockSite) do
- if (ActivePage <> nil) and (ActivePage.Controls[0] = Self) then
- ActivePage.Caption := Host.Caption;
- end;
- if Host.HostDockSite is TCnCustomDockControl then
- TCnCustomDockControl(Host.HostDockSite).UpdateCaption(nil);
- end;
- end;
- procedure TCnCustomDockControl.WndProc(var Message: TMessage);
- var CMUnDockClient: TCMUnDockClient;
- DockableForm: TCnDockableForm;
- begin
- if Message.Msg = CM_UNDOCKCLIENT then
- begin
- CMUnDockClient := TCMUnDockClient(Message);
- if CMUnDockClient.Client is TCnDockableForm then
- begin
- DockableForm := TCnDockableForm(CMUnDockClient.Client);
- if DockableForm.FloatingChild <> nil then
- begin
- // Cn_LockWindow(Self);
- try
- { 说明要把停靠客户重新停靠到服务器上,只要调用ReplaceZoneChild替换原先的
- Zone的ChildControl就可以了,不要忘记首先把这个FloatingChild显示出来,
- 因为可能在前面FloatingChild被隐藏了,见CnDockFormControl.pas中的
- TCnDockableForm.DoClose函数 }
- if Self is TCnTabPageControl then
- DockableForm.FloatingChild.ManualDock(Self)
- else
- DockableForm.FloatingChild.Dock(Self, Rect(0,0,0,0));
- DockableForm.FloatingChild.Visible := True;
- if Self is TCnCustomDockPanel then
- CnDockManager.ReplaceZoneChild(DockableForm, DockableForm.FloatingChild);
- finally
- // Cn_UnLockWindow;
- end;
- end;
- end;
- end;
- inherited WndProc(Message);
- end;
- { TCnCustomDockPanel }
- constructor TCnCustomDockPanel.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
- csSetCaption, csOpaque, csDoubleClicks, csReplicatable];
- Color := clBtnFace;
- UseDockManager := True;
- end;
- function TCnCustomDockPanel.CreateDockManager: IDockManager;
- begin
- if (Self is TCnConjoinPanel) and
- (TCnConjoinPanel(Self).DockClient <> nil) and
- (TCnConjoinPanel(Self).DockClient.DockStyle <> nil) and
- (TCnConjoinPanel(Self).DockClient.DockStyle.CnConjoinPanelTreeClass <> nil) and
- (TCnConjoinPanel(Self).DockClient.DockStyle.CnConjoinPanelTreeClass <>
- TCnDockTreeClass(ClassType)) then
- begin
- if (DockManager = nil) and DockSite and UseDockManager then
- Result := TCnConjoinPanel(Self).DockClient.DockStyle.CnConjoinPanelTreeClass.Create(
- Self, TCnDockPanel(Self).DockServer.DockStyle.CnConjoinPanelZoneClass) as ICnDockManager
- else Result := DockManager;
- end else
- if (Self is TCnDockPanel) and
- (TCnDockPanel(Self).DockServer <> nil) and
- (TCnDockPanel(Self).DockServer.DockStyle <> nil) and
- (TCnDockPanel(Self).DockServer.DockStyle.CnDockPanelTreeClass <> nil) and
- (TCnDockPanel(Self).DockServer.DockStyle.CnDockPanelTreeClass <>
- TCnDockTreeClass(ClassType)) then
- begin
- if (DockManager = nil) and DockSite and UseDockManager then
- Result := TCnDockPanel(Self).DockServer.DockStyle.CnDockPanelTreeClass.Create(
- Self, TCnDockPanel(Self).DockServer.DockStyle.CnDockPanelZoneClass) as ICnDockManager
- else Result := DockManager;
- end else
- begin
- if (DockManager = nil) and DockSite and UseDockManager then
- Result := DefaultDockTreeClass.Create(Self, DefaultDockZoneClass) as ICnDockManager
- else Result := DockManager;
- end;
- DoubleBuffered := DoubleBuffered or (Result <> nil);
- end;
- destructor TCnCustomDockPanel.Destroy;
- begin
- SetDockSite(Self, False);
- inherited Destroy;
- end;
- { TCnDockCustomTabControl }
- constructor TCnDockCustomTabControl.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- Width := 289;
- Height := 193;
- TabStop := True;
- ControlStyle := [csAcceptsControls, csDoubleClicks];
- FTabs := TCnDockTabStrings.Create;
- TCnDockTabStrings(FTabs).FTabControl := Self;
- FImageChangeLink := TChangeLink.Create;
- FImageChangeLink.OnChange := ImageListChange;
- end;
- destructor TCnDockCustomTabControl.Destroy;
- begin
- FreeAndNil(FTabs);
- FreeAndNil(FSaveTabs);
- FreeAndNil(FImageChangeLink);
- inherited Destroy;
- end;
- function TCnDockCustomTabControl.CanChange: Boolean;
- begin
- Result := True;
- if Assigned(FOnChanging) then FOnChanging(Self, Result);
- end;
- function TCnDockCustomTabControl.CanShowTab(TabIndex: Integer): Boolean;
- begin
- Result := True;
- end;
- procedure TCnDockCustomTabControl.Change;
- begin
- if Assigned(FOnChange) then FOnChange(Self);
- end;
- procedure TCnDockCustomTabControl.CreateParams(var Params: TCreateParams);
- const
- AlignStyles: array[Boolean, TTabPosition] of DWORD =
- ((0, TCS_BOTTOM, TCS_VERTICAL, TCS_VERTICAL or TCS_RIGHT),
- (0, TCS_BOTTOM, TCS_VERTICAL or TCS_RIGHT, TCS_VERTICAL));
- TabStyles: array[TTabStyle] of DWORD = (TCS_TABS, TCS_BUTTONS,
- TCS_BUTTONS or TCS_FLATBUTTONS);
- RRStyles: array[Boolean] of DWORD = (0, TCS_RAGGEDRIGHT);
- begin
- InitCommonControl(ICC_TAB_CLASSES);
- inherited CreateParams(Params);
- CreateSubClass(Params, WC_TABCONTROL);
- with Params do
- begin
- Style := Style or WS_CLIPCHILDREN or
- AlignStyles[UseRightToLeftAlignment, FTabPosition] or
- TabStyles[FStyle] or RRStyles[FRaggedRight];
- if not TabStop then Style := Style or TCS_FOCUSNEVER;
- if FMultiLine then Style := Style or TCS_MULTILINE;
- if FMultiSelect then Style := Style or TCS_MULTISELECT;
- if FOwnerDraw then Style := Style or TCS_OWNERDRAWFIXED;
- if FTabSize.X <> 0 then Style := Style or TCS_FIXEDWIDTH;
- if FHotTrack and (not (csDesigning in ComponentState)) then
- Style := Style or TCS_HOTTRACK;
- if FScrollOpposite then Style := Style or TCS_SCROLLOPPOSITE;
- WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW) or
- CS_DBLCLKS;
- end;
- end;
- procedure TCnDockCustomTabControl.CreateWnd;
- begin
- inherited CreateWnd;
- if (Images <> nil) and Images.HandleAllocated then
- Perform(TCM_SETIMAGELIST, 0, Images.Handle);
- if Integer(FTabSize) <> 0 then UpdateTabSize;
- if FSaveTabs <> nil then
- begin
- FTabs.Assign(FSaveTabs);
- SetTabIndex(FSaveTabIndex);
- FSaveTabs.Free;
- FSaveTabs := nil;
- end;
- end;
- procedure TCnDockCustomTabControl.DrawTab(TabIndex: Integer; const Rect: TRect;
- Active: Boolean);
- begin
- if Assigned(FOnDrawTab) then
- FOnDrawTab(Self, TabIndex, Rect, Active)
- else
- Canvas.FillRect(Rect);
- end;
- function TCnDockCustomTabControl.GetDisplayRect: TRect;
- begin
- Result := ClientRect;
- SendMessage(Handle, TCM_ADJUSTRECT, 0, Integer(@Result));
- if TabPosition = tpTop then
- Inc(Result.Top, 2);
- end;
- function TCnDockCustomTabControl.GetImageIndex(TabIndex: Integer): Integer;
- begin
- Result := TabIndex;
- if Assigned(FOnGetImageIndex) then FOnGetImageIndex(Self, TabIndex, Result);
- end;
- function TCnDockCustomTabControl.GetTabIndex: Integer;
- begin
- Result := SendMessage(Handle, TCM_GETCURSEL, 0, 0);
- end;
- procedure TCnDockCustomTabControl.Loaded;
- begin
- inherited Loaded;
- if Images <> nil then UpdateTabImages;
- end;
- procedure TCnDockCustomTabControl.SetHotTrack(Value: Boolean);
- begin
- if FHotTrack <> Value then
- begin
- FHotTrack := Value;
- RecreateWnd;
- end;
- end;
- procedure TCnDockCustomTabControl.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if (Operation = opRemove) and (AComponent = Images) then
- Images := nil;
- end;
- procedure TCnDockCustomTabControl.SetImages(Value: TCustomImageList);
- begin
- if Images <> nil then
- Images.UnRegisterChanges(FImageChangeLink);
- FImages := Value;
- if Images <> nil then
- begin
- Images.RegisterChanges(FImageChangeLink);
- Images.FreeNotification(Self);
- Perform(TCM_SETIMAGELIST, 0, Images.Handle);
- end
- else Perform(TCM_SETIMAGELIST, 0, 0);
- end;
- procedure TCnDockCustomTabControl.ImageListChange(Sender: TObject);
- begin
- Perform(TCM_SETIMAGELIST, 0, TCustomImageList(Sender).Handle);
- end;
- function TCnDockCustomTabControl.InternalSetMultiLine(Value: Boolean): Boolean;
- begin
- Result := FMultiLine <> Value;
- if Result then
- begin
- if not Value and ((TabPosition = tpLeft) or (TabPosition = tpRight)) then
- TabControlError(sTabMustBeMultiLine);
- FMultiLine := Value;
- if not Value then FScrollOpposite := False;
- end;
- end;
- procedure TCnDockCustomTabControl.SetMultiLine(Value: Boolean);
- begin
- if InternalSetMultiLine(Value) then RecreateWnd;
- end;
- procedure TCnDockCustomTabControl.SetMultiSelect(Value: Boolean);
- begin
- if FMultiSelect <> Value then
- begin
- FMultiSelect := Value;
- RecreateWnd;
- end;
- end;
- procedure TCnDockCustomTabControl.SetOwnerDraw(Value: Boolean);
- begin
- if FOwnerDraw <> Value then
- begin
- FOwnerDraw := Value;
- RecreateWnd;
- end;
- end;
- procedure TCnDockCustomTabControl.SetRaggedRight(Value: Boolean);
- begin
- if FRaggedRight <> Value then
- begin
- FRaggedRight := Value;
- SetComCtlStyle(Self, TCS_RAGGEDRIGHT, Value);
- end;
- end;
- procedure TCnDockCustomTabControl.SetScrollOpposite(Value: Boolean);
- begin
- if FScrollOpposite <> Value then
- begin
- FScrollOpposite := Value;
- if Value then FMultiLine := Value;
- RecreateWnd;
- end;
- end;
- procedure TCnDockCustomTabControl.SetStyle(Value: TTabStyle);
- begin
- if FStyle <> Value then
- begin
- if (Value <> tsTabs) and (TabPosition <> tpTop) then
- raise EInvalidOperation.Create(SInvalidTabStyle);
- FStyle := Value;
- RecreateWnd;
- end;
- end;
- procedure TCnDockCustomTabControl.SetTabHeight(Value: Smallint);
- begin
- if FTabSize.Y <> Value then
- begin
- if Value < 0 then
- raise EInvalidOperation.CreateFmt(SPropertyOutOfRange, [Self.Classname]);
- FTabSize.Y := Value;
- UpdateTabSize;
- end;
- end;
- procedure TCnDockCustomTabControl.SetTabIndex(Value: Integer);
- begin
- SendMessage(Handle, TCM_SETCURSEL, Value, 0);
- end;
- procedure TCnDockCustomTabControl.SetTabPosition(Value: TTabPosition);
- begin
- if FTabPosition <> Value then
- begin
- if (Value <> tpTop) and (Style <> tsTabs) then
- raise EInvalidOperation.Create(SInvalidTabPosition);
- FTabPosition := Value;
- if not MultiLine and ((Value = tpLeft) or (Value = tpRight)) then
- InternalSetMultiLine(True);
- RecreateWnd;
- end;
- end;
- procedure TCnDockCustomTabControl.SetTabs(Value: TStrings);
- begin
- FTabs.Assign(Value);
- end;
- procedure TCnDockCustomTabControl.SetTabWidth(Value: Smallint);
- var
- OldValue: Smallint;
- begin
- if FTabSize.X <> Value then
- begin
- if Value < 0 then
- raise EInvalidOperation.CreateFmt(SPropertyOutOfRange, [Self.Classname]);
- OldValue := FTabSize.X;
- FTabSize.X := Value;
- if (OldValue = 0) or (Value = 0) then RecreateWnd
- else UpdateTabSize;
- end;
- end;
- procedure TCnDockCustomTabControl.TabsChanged;
- begin
- if not FUpdating then
- begin
- if HandleAllocated then
- SendMessage(Handle, WM_SIZE, SIZE_RESTORED,
- Word(Width) or Word(Height) shl 16);
- Realign;
- end;
- end;
- procedure TCnDockCustomTabControl.UpdateTabSize;
- begin
- SendMessage(Handle, TCM_SETITEMSIZE, 0, Integer(FTabSize));
- TabsChanged;
- end;
- procedure TCnDockCustomTabControl.UpdateTabImages;
- var
- I: Integer;
- TCItem: TTCItem;
- begin
- TCItem.mask := TCIF_IMAGE;
- for I := 0 to FTabs.Count - 1 do
- begin
- TCItem.iImage := GetImageIndex(I);
- if SendMessage(Handle, TCM_SETITEM, I,
- Longint(@TCItem)) = 0 then
- TabControlError(Format(sTabFailSet, [FTabs[I], I]));
- end;
- TabsChanged;
- end;
- procedure TCnDockCustomTabControl.CNDrawItem(var Message: TWMDrawItem);
- var
- SaveIndex: Integer;
- begin
- with Message.DrawItemStruct^ do
- begin
- SaveIndex := SaveDC(hDC);
- Canvas.Lock;
- try
- Canvas.Handle := hDC;
- Canvas.Font := Font;
- Canvas.Brush := Brush;
- DrawTab(itemID, rcItem, itemState and ODS_SELECTED <> 0);
- finally
- Canvas.Handle := 0;
- Canvas.Unlock;
- RestoreDC(hDC, SaveIndex);
- end;
- end;
- Message.Result := 1;
- end;
- procedure TCnDockCustomTabControl.WMDestroy(var Message: TWMDestroy);
- var
- FocusHandle: HWnd;
- begin
- if (FTabs <> nil) and (FTabs.Count > 0) then
- begin
- FSaveTabs := TStringList.Create;
- FSaveTabs.Assign(FTabs);
- FSaveTabIndex := GetTabIndex;
- end;
- FocusHandle := GetFocus;
- if (FocusHandle <> 0) and ((FocusHandle = Handle) or
- IsChild(Handle, FocusHandle)) then
- Windows.SetFocus(0);
- inherited;
- WindowHandle := 0;
- end;
- procedure TCnDockCustomTabControl.WMNotifyFormat(var Message: TMessage);
- begin
- with Message do
- Result := DefWindowProc(Handle, Msg, WParam, LParam);
- end;
- procedure TCnDockCustomTabControl.WMSize(var Message: TMessage);
- begin
- inherited;
- RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ERASE);
- end;
- procedure TCnDockCustomTabControl.CMFontChanged(var Message);
- begin
- inherited;
- if HandleAllocated then Perform(WM_SIZE, 0, 0);
- end;
- procedure TCnDockCustomTabControl.CMSysColorChange(var Message: TMessage);
- begin
- inherited;
- if not (csLoading in ComponentState) then
- begin
- Message.Msg := WM_SYSCOLORCHANGE;
- DefaultHandler(Message);
- end;
- end;
- procedure TCnDockCustomTabControl.CMTabStopChanged(var Message: TMessage);
- begin
- if not (csDesigning in ComponentState) then RecreateWnd;
- end;
- procedure TCnDockCustomTabControl.CNNotify(var Message: TWMNotify);
- begin
- with Message do
- case NMHdr^.code of
- TCN_SELCHANGE:
- Change;
- TCN_SELCHANGING:
- begin
- Result := 1;
- if CanChange then Result := 0;
- end;
- end;
- end;
- procedure TCnDockCustomTabControl.CMDialogChar(var Message: TCMDialogChar);
- var
- I: Integer;
- begin
- for I := 0 to FTabs.Count - 1 do
- if IsAccel(Message.CharCode, FTabs[I]) and CanShowTab(I) and CanFocus then
- begin
- Message.Result := 1;
- if CanChange then
- begin
- TabIndex := I;
- Change;
- end;
- Exit;
- end;
- inherited;
- end;
- procedure TCnDockCustomTabControl.AdjustClientRect(var Rect: TRect);
- begin
- Rect := DisplayRect;
- inherited AdjustClientRect(Rect);
- end;
- function TCnDockCustomTabControl.IndexOfTabAt(X, Y: Integer): Integer;
- var
- HitTest: TTCHitTestInfo;
- begin
- Result := -1;
- if PtInRect(ClientRect, Point(X, Y)) then
- with HitTest do
- begin
- pt.X := X;
- pt.Y := Y;
- Result := TabCtrl_HitTest(Handle, @HitTest);
- end;
- end;
- function TCnDockCustomTabControl.GetHitTestInfoAt(X, Y: Integer): THitTests;
- var
- HitTest: TTCHitTestInfo;
- begin
- Result := [];
- if PtInRect(ClientRect, Point(X, Y)) then
- with HitTest do
- begin
- pt.X := X;
- pt.Y := Y;
- if TabCtrl_HitTest(Handle, @HitTest) <> -1 then
- begin
- if (flags and TCHT_NOWHERE) <> 0 then
- Include(Result, htNowhere);
- if (flags and TCHT_ONITEM) = TCHT_ONITEM then
- Include(Result, htOnItem)
- else
- begin
- if (flags and TCHT_ONITEM) <> 0 then
- Include(Result, htOnItem);
- if (flags and TCHT_ONITEMICON) <> 0 then
- Include(Result, htOnIcon);
- if (flags and TCHT_ONITEMLABEL) <> 0 then
- Include(Result, htOnLabel);
- end;
- end
- else
- Result := [htNowhere];
- end;
- end;
- function TCnDockCustomTabControl.TabRect(Index: Integer): TRect;
- begin
- TabCtrl_GetItemRect(Handle, Index, Result);
- end;
- function TCnDockCustomTabControl.RowCount: Integer;
- begin
- Result := TabCtrl_GetRowCount(Handle);
- end;
- procedure TCnDockCustomTabControl.ScrollTabs(Delta: Integer);
- var
- Wnd: HWND;
- P: TPoint;
- Rect: TRect;
- I: Integer;
- begin
- Wnd := FindWindowEx(Handle, 0, 'msctls_updown32', nil);
- if Wnd <> 0 then
- begin
- Windows.GetClientRect(Wnd, Rect);
- if Delta < 0 then
- P.X := Rect.Left + 2
- else
- P.X := Rect.Right - 2;
- P.Y := Rect.Top + 2;
- for I := 0 to Abs(Delta) - 1 do
- begin
- SendMessage(Wnd, WM_LBUTTONDOWN, 0, MakeLParam(P.X, P.Y));
- SendMessage(Wnd, WM_LBUTTONUP, 0, MakeLParam(P.X, P.Y));
- end;
- end;
- end;
- procedure TCnDockCustomTabControl.TCMAdjustRect(var Message: TMessage);
- begin
- { Major hack around a problem in the Windows tab control. Don't try this
- at home. The tab control (4.71) will AV when in a TCM_ADJUSTRECT message
- when the height of the control is the same as the height of the tab (or the
- width of the control for tpBottom). This hack will return the last value
- successfully returned if an exception is encountered. This allows the
- control to function but the AV is till generated and and reported by the
- debugger. }
- try
- inherited;
- if (TabPosition <> tpTop) and (Message.WParam = 0) then
- FSavedAdjustRect := PRect(Message.LParam)^;
- except
- PRect(Message.LParam)^ := FSavedAdjustRect;
- end;
- end;
- procedure TCnDockCustomTabControl.PaintWindow(DC: HDC);
- var
- Message: TMessage;
- begin
- if not OwnerDraw then
- begin
- { 如果不是自己画,就调用系统的重画事件 }
- Message.Msg := WM_PAINT;
- Message.WParam := DC;
- Message.LParam := 0;
- Message.Result := 0;
- DefaultHandler(Message);
- end;
- inherited PaintWindow(DC);
- end;
- { TCnDockTabSheet }
- constructor TCnDockTabSheet.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- Align := alClient;
- ControlStyle := ControlStyle + [csAcceptsControls, csNoDesignVisible];
- Visible := False;
- FTabVisible := True;
- FHighlighted := False;
- end;
- destructor TCnDockTabSheet.Destroy;
- begin
- if FPageControl <> nil then
- begin
- if FPageControl.FUndockingPage = Self then FPageControl.FUndockingPage := nil;
- FPageControl.RemovePage(Self);
- end;
- inherited Destroy;
- end;
- procedure TCnDockTabSheet.DoHide;
- begin
- if Assigned(FOnHide) then FOnHide(Self);
- end;
- procedure TCnDockTabSheet.DoShow;
- begin
- if Assigned(FOnShow) then FOnShow(Self);
- end;
- function TCnDockTabSheet.GetPageIndex: Integer;
- begin
- if (FPageControl <> nil) and (FPageControl.FPages <> nil) then
- Result := FPageControl.FPages.IndexOf(Self)
- else Result := -1;
- end;
- function TCnDockTabSheet.GetTabIndex: Integer;
- var
- I: Integer;
- begin
- Result := 0;
- if not FTabShowing then Dec(Result) else
- for I := 0 to PageIndex - 1 do
- if TCnDockTabSheet(FPageControl.FPages[I]).FTabShowing then
- Inc(Result);
- end;
- procedure TCnDockTabSheet.CreateParams(var Params: TCreateParams);
- begin
- inherited CreateParams(Params);
- with Params.WindowClass do
- style := style and not (CS_HREDRAW or CS_VREDRAW);
- end;
- procedure TCnDockTabSheet.ReadState(Reader: TReader);
- begin
- inherited ReadState(Reader);
- if Reader.Parent is TCnDockPageControl then
- PageControl := TCnDockPageControl(Reader.Parent);
- end;
- procedure TCnDockTabSheet.SetImageIndex(Value: TImageIndex);
- begin
- if FImageIndex <> Value then
- begin
- FImageIndex := Value;
- if FTabShowing then FPageControl.UpdateTab(Self);
- end;
- end;
- procedure TCnDockTabSheet.SetPageControl(APageControl: TCnDockPageControl);
- begin
- if FPageControl <> APageControl then
- begin
- if FPageControl <> nil then FPageControl.RemovePage(Self);
- Parent := APageControl;
- if APageControl <> nil then APageControl.InsertPage(Self);
- end;
- end;
- procedure TCnDockTabSheet.SetPageIndex(Value: Integer);
- var
- I, MaxPageIndex: Integer;
- begin
- if (FPageControl <> nil) and (FPageControl.FPages <> nil) then
- begin
- MaxPageIndex := FPageControl.FPages.Count - 1;
- if Value > MaxPageIndex then
- raise EListError.CreateResFmt(@SPageIndexError, [Value, MaxPageIndex]);
- I := TabIndex;
- FPageControl.FPages.Move(PageIndex, Value);
- if I >= 0 then FPageControl.MoveTab(I, TabIndex);
- end;
- end;
- procedure TCnDockTabSheet.SetTabShowing(Value: Boolean);
- var
- Index: Integer;
- begin
- if FTabShowing <> Value then
- if Value then
- begin
- FTabShowing := True;
- FPageControl.InsertTab(Self);
- end else
- begin
- Index := TabIndex;
- FTabShowing := False;
- FPageControl.DeleteTab(Self, Index);
- end;
- end;
- procedure TCnDockTabSheet.SetTabVisible(Value: Boolean);
- begin
- if FTabVisible <> Value then
- begin
- FTabVisible := Value;
- UpdateTabShowing;
- end;
- end;
- procedure TCnDockTabSheet.UpdateTabShowing;
- begin
- SetTabShowing((FPageControl <> nil) and FTabVisible);
- end;
- procedure TCnDockTabSheet.CMTextChanged(var Message: TMessage);
- begin
- if FTabShowing then FPageControl.UpdateTab(Self);
- end;
- procedure TCnDockTabSheet.CMShowingChanged(var Message: TMessage);
- begin
- inherited;
- if Showing then
- begin
- try
- DoShow
- except
- Application.HandleException(Self);
- end;
- end else if not Showing then
- begin
- try
- DoHide;
- except
- Application.HandleException(Self);
- end;
- end;
- end;
- procedure TCnDockTabSheet.SetHighlighted(Value: Boolean);
- begin
- if not (csReading in ComponentState) then
- SendMessage(PageControl.Handle, TCM_HIGHLIGHTITEM, TabIndex,
- MakeLong(Word(Value), 0));
- FHighlighted := Value;
- end;
- { TCnDockPageControl }
- constructor TCnDockPageControl.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- ControlStyle := [csDoubleClicks, csOpaque];
- FPages := TList.Create;
- FCnDockTabSheetClass := TCnDockTabSheet;
- end;
- destructor TCnDockPageControl.Destroy;
- var
- I: Integer;
- begin
- for I := 0 to FPages.Count - 1 do TCnDockTabSheet(FPages[I]).FPageControl := nil;
- FPages.Free;
- inherited Destroy;
- end;
- procedure TCnDockPageControl.UpdateTabHighlights;
- var
- I: Integer;
- begin
- for I := 0 to PageCount - 1 do
- Pages[I].SetHighlighted(Pages[I].FHighlighted);
- end;
- procedure TCnDockPageControl.Loaded;
- begin
- inherited Loaded;
- UpdateTabHighlights;
- end;
- function TCnDockPageControl.CanShowTab(TabIndex: Integer): Boolean;
- begin
- Result := TCnDockTabSheet(FPages[TabIndex]).Enabled;
- end;
- procedure TCnDockPageControl.Change;
- var
- Form: TCustomForm;
- begin
- if TabIndex >= 0 then
- UpdateActivePage;
- if csDesigning in ComponentState then
- begin
- Form := GetParentForm(Self);
- if (Form <> nil) and (Form.Designer <> nil) then Form.Designer.Modified;
- end;
- inherited Change;
- end;
- procedure TCnDockPageControl.ChangeActivePage(Page: TCnDockTabSheet);
- var
- ParentForm: TCustomForm;
- begin
- if FActivePage <> Page then
- begin
- ParentForm := GetParentForm(Self);
- if (ParentForm <> nil) and (FActivePage <> nil) and
- FActivePage.ContainsControl(ParentForm.ActiveControl) then
- begin
- ParentForm.ActiveControl := FActivePage;
- if ParentForm.ActiveControl <> FActivePage then
- begin
- TabIndex := FActivePage.TabIndex;
- Exit;
- end;
- end;
- if Page <> nil then
- begin
- Page.BringToFront;
- Page.Visible := True;
- if (ParentForm <> nil) and (FActivePage <> nil) and
- (ParentForm.ActiveControl = FActivePage) then
- if Page.CanFocus then
- ParentForm.ActiveControl := Page else
- ParentForm.ActiveControl := Self;
- end;
- if FActivePage <> nil then FActivePage.Visible := False;
- FActivePage := Page;
- if (ParentForm <> nil) and (FActivePage <> nil) and
- (ParentForm.ActiveControl = FActivePage) then
- FActivePage.SelectFirst;
- end;
- end;
- procedure TCnDockPageControl.DeleteTab(Page: TCnDockTabSheet; Index: Integer);
- var
- UpdateIndex: Boolean;
- begin
- UpdateIndex := Page = ActivePage;
- Tabs.Delete(Index);
- if UpdateIndex then
- begin
- if Index >= Tabs.Count then
- Index := Tabs.Count - 1;
- TabIndex := Index;
- end;
- UpdateActivePage;
- end;
- procedure TCnDockPageControl.DoAddDockClient(Client: TControl; const ARect: TRect);
- begin
- if FNewDockSheet <> nil then Client.Parent := FNewDockSheet;
- end;
- procedure TCnDockPageControl.DockOver(Source: TDragDockObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- var
- R: TRect;
- begin
- GetWindowRect(Handle, R);
- Source.DockRect := R;
- DoDockOver(Source, X, Y, State, Accept);
- end;
- procedure TCnDockPageControl.DoRemoveDockClient(Client: TControl);
- begin
- if (FUndockingPage <> nil) and not (csDestroying in ComponentState) then
- begin
- SelectNextPage(True);
- FUndockingPage.Free;
- FUndockingPage := nil;
- end;
- end;
- function TCnDockPageControl.FindNextPage(CurPage: TCnDockTabSheet;
- GoForward, CheckTabVisible: Boolean): TCnDockTabSheet;
- var
- I, StartIndex: Integer;
- begin
- if FPages.Count <> 0 then
- begin
- StartIndex := FPages.IndexOf(CurPage);
- if StartIndex = -1 then
- if GoForward then StartIndex := FPages.Count - 1 else StartIndex := 0;
- I := StartIndex;
- repeat
- if GoForward then
- begin
- Inc(I);
- if I = FPages.Count then I := 0;
- end else
- begin
- if I = 0 then I := FPages.Count;
- Dec(I);
- end;
- Result := FPages[I];
- if not CheckTabVisible or Result.TabVisible then Exit;
- until I = StartIndex;
- end;
- Result := nil;
- end;
- procedure TCnDockPageControl.GetChildren(Proc: TGetChildProc; Root: TComponent);
- var
- I: Integer;
- begin
- for I := 0 to FPages.Count - 1 do Proc(TComponent(FPages[I]));
- end;
- function TCnDockPageControl.GetImageIndex(TabIndex: Integer): Integer;
- var
- I,
- Visible,
- NotVisible: Integer;
- begin
- if Assigned(FOnGetImageIndex) then
- Result := inherited GetImageIndex(TabIndex) else
- begin
- { For a PageControl, TabIndex refers to visible tabs only. The control
- doesn't store }
- Visible := 0;
- NotVisible := 0;
- for I := 0 to FPages.Count - 1 do
- begin
- if not GetPage(I).TabVisible then Inc(NotVisible)
- else Inc(Visible);
- if Visible = TabIndex + 1 then Break;
- end;
- // Result := 0;
- // if TabIndex + NotVisible >= PageCount then Exit;
- Result := GetPage(TabIndex + NotVisible).ImageIndex;
- end;
- end;
- function TCnDockPageControl.GetPageFromDockClient(Client: TControl): TCnDockTabSheet;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to PageCount - 1 do
- begin
- if (Client.Parent = Pages[I]) and (Client.HostDockSite = Self) then
- begin
- Result := Pages[I];
- Exit;
- end;
- end;
- end;
- function TCnDockPageControl.GetPage(Index: Integer): TCnDockTabSheet;
- begin
- Result := FPages[Index];
- end;
- function TCnDockPageControl.GetPageCount: Integer;
- begin
- Result := FPages.Count;
- end;
- procedure TCnDockPageControl.GetSiteInfo(Client: TControl; var InfluenceRect: TRect;
- MousePos: TPoint; var CanDock: Boolean);
- begin
- CanDock := GetPageFromDockClient(Client) = nil;
- inherited GetSiteInfo(Client, InfluenceRect, MousePos, CanDock);
- end;
- procedure TCnDockPageControl.InsertPage(Page: TCnDockTabSheet);
- begin
- FPages.Add(Page);
- Page.FPageControl := Self;
- Page.UpdateTabShowing;
- end;
- procedure TCnDockPageControl.InsertTab(Page: TCnDockTabSheet);
- begin
- Tabs.InsertObject(Page.TabIndex, Page.Caption, Page);
- UpdateActivePage;
- end;
- procedure TCnDockPageControl.MoveTab(CurIndex, NewIndex: Integer);
- begin
- Tabs.Move(CurIndex, NewIndex);
- end;
- procedure TCnDockPageControl.RemovePage(Page: TCnDockTabSheet);
- var
- NextSheet: TCnDockTabSheet;
- begin
- NextSheet := FindNextPage(Page, True, not (csDesigning in ComponentState));
- if NextSheet = Page then NextSheet := nil;
- Page.SetTabShowing(False);
- Page.FPageControl := nil;
- FPages.Remove(Page);
- SetActivePage(NextSheet);
- end;
- procedure TCnDockPageControl.SelectNextPage(GoForward: Boolean; CheckTabVisible: Boolean = True);
- var
- Page: TCnDockTabSheet;
- begin
- Page := FindNextPage(ActivePage, GoForward, CheckTabVisible);
- if (Page <> nil) and (Page <> ActivePage) and CanChange then
- begin
- SetActivePage(Page);
- Change;
- end;
- end;
- procedure TCnDockPageControl.SetActivePage(Page: TCnDockTabSheet);
- begin
- if (Page <> nil) and (Page.PageControl <> Self) then Exit;
- ChangeActivePage(Page);
- if Page = nil then
- TabIndex := -1
- else if Page = FActivePage then
- TabIndex := Page.TabIndex;
- end;
- procedure TCnDockPageControl.SetChildOrder(Child: TComponent; Order: Integer);
- begin
- TCnDockTabSheet(Child).PageIndex := Order;
- end;
- procedure TCnDockPageControl.ShowControl(AControl: TControl);
- begin
- if (AControl is TCnDockTabSheet) and (TCnDockTabSheet(AControl).PageControl = Self) then
- SetActivePage(TCnDockTabSheet(AControl));
- inherited ShowControl(AControl);
- end;
- procedure TCnDockPageControl.UpdateTab(Page: TCnDockTabSheet);
- begin
- Tabs[Page.TabIndex] := Page.Caption;
- end;
- procedure TCnDockPageControl.UpdateActivePage;
- begin
- if TabIndex >= 0 then
- SetActivePage(TCnDockTabSheet(Tabs.Objects[TabIndex]))
- else
- SetActivePage(nil);
- end;
- procedure TCnDockPageControl.CMDesignHitTest(var Message: TCMDesignHitTest);
- var
- HitIndex: Integer;
- HitTestInfo: TTCHitTestInfo;
- begin
- HitTestInfo.pt := SmallPointToPoint(Message.Pos);
- HitIndex := SendMessage(Handle, TCM_HITTEST, 0, Longint(@HitTestInfo));
- if (HitIndex >= 0) and (HitIndex <> TabIndex) then Message.Result := 1;
- end;
- procedure TCnDockPageControl.CMDialogKey(var Message: TCMDialogKey);
- begin
- if (Focused or Windows.IsChild(Handle, Windows.GetFocus)) and
- (Message.CharCode = VK_TAB) and (GetKeyState(VK_CONTROL) < 0) then
- begin
- SelectNextPage(GetKeyState(VK_SHIFT) >= 0);
- Message.Result := 1;
- end else
- inherited;
- end;
- procedure TCnDockPageControl.CMDockClient(var Message: TCMDockClient);
- var
- IsVisible: Boolean;
- DockCtl: TControl;
- begin
- Message.Result := 0;
- if FCnDockTabSheetClass <> nil then
- FNewDockSheet := FCnDockTabSheetClass.Create(Self)
- else FNewDockSheet := TCnDockTabSheet.Create(Self);
- try
- try
- DockCtl := Message.DockSource.Control;
- FNewDockSheet.PageControl := Self;
- if DockCtl is TCustomForm then
- FNewDockSheet.Caption := TCustomForm(DockCtl).Caption;
- DockCtl.Dock(Self, Message.DockSource.DockRect);
- except
- FNewDockSheet.Free;
- raise;
- end;
- IsVisible := DockCtl.Visible;
- FNewDockSheet.TabVisible := IsVisible;
- if IsVisible then ActivePage := FNewDockSheet;
- DockCtl.Align := alClient;
- finally
- FNewDockSheet := nil;
- end;
- end;
- procedure TCnDockPageControl.CMDockNotification(var Message: TCMDockNotification);
- var
- I: Integer;
- S: string;
- Page: TCnDockTabSheet;
- begin
- Page := GetPageFromDockClient(Message.Client);
- if Page <> nil then
- case Message.NotifyRec.ClientMsg of
- WM_SETTEXT:
- begin
- S := PChar(Message.NotifyRec.MsgLParam);
- { Search for first CR/LF and end string there }
- for I := 1 to Length(S) do
- if {$IFDEF UNICODE}CharInSet(S[i], [#13, #10]){$ELSE}S[I] in [#13, #10]{$ENDIF} then
- begin
- SetLength(S, I - 1);
- Break;
- end;
- Page.Caption := S;
- end;
- CM_VISIBLECHANGED:
- Page.TabVisible := Boolean(Message.NotifyRec.MsgWParam);
- end;
- inherited;
- end;
- procedure TCnDockPageControl.CMUnDockClient(var Message: TCMUnDockClient);
- var
- Page: TCnDockTabSheet;
- begin
- Message.Result := 0;
- Page := GetPageFromDockClient(Message.Client);
- if Page <> nil then
- begin
- FUndockingPage := Page;
- Message.Client.Align := alNone;
- end;
- end;
- function TCnDockPageControl.GetDockClientFromMousePos(MousePos: TPoint): TControl;
- var
- i, HitIndex: Integer;
- HitTestInfo: TTCHitTestInfo;
- Page: TCnDockTabSheet;
- begin
- Result := nil;
- if DockSite then
- begin
- HitTestInfo.pt := MousePos;
- HitIndex := SendMessage(Handle, TCM_HITTEST, 0, Longint(@HitTestInfo));
- if HitIndex >= 0 then
- begin
- Page := nil;
- for i := 0 to HitIndex do
- Page := FindNextPage(Page, True, True);
- if (Page <> nil) and (Page.ControlCount > 0) then
- begin
- Result := Page.Controls[0];
- if Result.HostDockSite <> Self then Result := nil;
- end;
- end;
- end;
- end;
- procedure TCnDockPageControl.WMLButtonDown(var Message: TWMLButtonDown);
- var
- DockCtl: TControl;
- begin
- inherited;
- if GlobalDockClient <> nil then
- DockCtl := ButtonEvent(Self, Message, mbLeft, msTabPage, GlobalDockClient.DoNCButtonDown)
- else DockCtl := nil;
- if (DockCtl <> nil) and (Style = tsTabs) then
- { 如果条件都满足,就调用CnGlobalDockPresident的BeginDrag方法,开始停靠操作 }
- CnGlobalDockPresident.BeginDrag(DockCtl, False);
- end;
- procedure TCnDockPageControl.WMLButtonDblClk(var Message: TWMLButtonDblClk);
- var
- DockCtl: TControl;
- begin
- inherited;
- if GlobalDockClient <> nil then
- DockCtl := ButtonEvent(Self, Message, mbLeft, msTabPage, GlobalDockClient.DoNCButtonDblClk)
- else DockCtl := nil;
- if (DockCtl <> nil) and (GlobalDockClient.CanFloat) then
- DockCtl.ManualDock(nil, nil, alNone);
- end;
- function TCnDockPageControl.GetActivePageIndex: Integer;
- begin
- if ActivePage <> nil then
- Result := ActivePage.GetPageIndex
- else
- Result := -1;
- end;
- procedure TCnDockPageControl.SetActivePageIndex(const Value: Integer);
- begin
- if (Value > -1) and (Value < PageCount) then
- ActivePage := Pages[Value]
- else
- ActivePage := nil;
- end;
- { TTabStrings }
- procedure TCnDockTabStrings.Clear;
- begin
- if SendMessage(FTabControl.Handle, TCM_DELETEALLITEMS, 0, 0) = 0 then
- TabControlError(sTabFailClear);
- FTabControl.TabsChanged;
- end;
- procedure TCnDockTabStrings.Delete(Index: Integer);
- begin
- if SendMessage(FTabControl.Handle, TCM_DELETEITEM, Index, 0) = 0 then
- TabControlError(Format(sTabFailDelete, [Index]));
- FTabControl.TabsChanged;
- end;
- function TCnDockTabStrings.Get(Index: Integer): string;
- const
- RTL: array[Boolean] of LongInt = (0, TCIF_RTLREADING);
- var
- TCItem: TTCItem;
- Buffer: array[0..4095] of Char;
- begin
- TCItem.mask := TCIF_TEXT or RTL[FTabControl.UseRightToLeftReading];
- TCItem.pszText := Buffer;
- TCItem.cchTextMax := SizeOf(Buffer);
- if SendMessage(FTabControl.Handle, TCM_GETITEM, Index,
- Longint(@TCItem)) = 0 then
- TabControlError(Format(sTabFailRetrieve, [Index]));
- Result := Buffer;
- end;
- function TCnDockTabStrings.GetCount: Integer;
- begin
- Result := SendMessage(FTabControl.Handle, TCM_GETITEMCOUNT, 0, 0);
- end;
- function TCnDockTabStrings.GetObject(Index: Integer): TObject;
- var
- TCItem: TTCItem;
- begin
- TCItem.mask := TCIF_PARAM;
- if SendMessage(FTabControl.Handle, TCM_GETITEM, Index,
- Longint(@TCItem)) = 0 then
- TabControlError(Format(sTabFailGetObject, [Index]));
- Result := TObject(TCItem.lParam);
- end;
- procedure TCnDockTabStrings.Put(Index: Integer; const S: string);
- const
- RTL: array[Boolean] of LongInt = (0, TCIF_RTLREADING);
- var
- TCItem: TTCItem;
- begin
- TCItem.mask := TCIF_TEXT or RTL[FTabControl.UseRightToLeftReading] or
- TCIF_IMAGE;
- TCItem.pszText := PChar(S);
- TCItem.iImage := FTabControl.GetImageIndex(Index);
- if SendMessage(FTabControl.Handle, TCM_SETITEM, Index,
- Longint(@TCItem)) = 0 then
- TabControlError(Format(sTabFailSet, [S, Index]));
- FTabControl.TabsChanged;
- end;
- procedure TCnDockTabStrings.PutObject(Index: Integer; AObject: TObject);
- var
- TCItem: TTCItem;
- begin
- TCItem.mask := TCIF_PARAM;
- TCItem.lParam := Longint(AObject);
- if SendMessage(FTabControl.Handle, TCM_SETITEM, Index,
- Longint(@TCItem)) = 0 then
- TabControlError(Format(sTabFailSetObject, [Index]));
- end;
- procedure TCnDockTabStrings.Insert(Index: Integer; const S: string);
- const
- RTL: array[Boolean] of LongInt = (0, TCIF_RTLREADING);
- var
- TCItem: TTCItem;
- begin
- TCItem.mask := TCIF_TEXT or RTL[FTabControl.UseRightToLeftReading] or
- TCIF_IMAGE;
- TCItem.pszText := PChar(S);
- TCItem.iImage := FTabControl.GetImageIndex(Index);
- if SendMessage(FTabControl.Handle, TCM_INSERTITEM, Index,
- Longint(@TCItem)) < 0 then
- TabControlError(Format(sTabFailSet, [S, Index]));
- FTabControl.TabsChanged;
- end;
- procedure TCnDockTabStrings.SetUpdateState(Updating: Boolean);
- begin
- FTabControl.FUpdating := Updating;
- SendMessage(FTabControl.Handle, WM_SETREDRAW, Ord(not Updating), 0);
- if not Updating then
- begin
- FTabControl.Invalidate;
- FTabControl.TabsChanged;
- end;
- end;
- function TCnDockPageControl.DoMouseEvent(var Message: TWMMouse;
- Control: TControl): TWMNCHitMessage;
- begin
- Result := Cn_CreateNCMessage(Control, Message.Msg + WM_NCMOUSEFIRST - WM_MOUSEFIRST,
- HTCAPTION, SmallPointToPoint(Message.Pos));
- end;
- procedure TCnDockPageControl.WMLButtonUp(var Message: TWMLButtonUp);
- begin
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbLeft, msTabPage, GlobalDockClient.DoNCButtonUp);
- end;
- procedure TCnDockPageControl.WMMButtonDblClk(
- var Message: TWMMButtonDblClk);
- begin
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbMiddle, msTabPage, GlobalDockClient.DoNCButtonDblClk);
- end;
- procedure TCnDockPageControl.WMMButtonDown(var Message: TWMMButtonDown);
- begin
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbMiddle, msTabPage, GlobalDockClient.DoNCButtonDown);
- end;
- procedure TCnDockPageControl.WMMButtonUp(var Message: TWMMButtonUp);
- begin
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbMiddle, msTabPage, GlobalDockClient.DoNCButtonUp);
- end;
- procedure TCnDockPageControl.WMRButtonDblClk(
- var Message: TWMRButtonDblClk);
- begin
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbRight, msTabPage, GlobalDockClient.DoNCButtonDblClk);
- end;
- procedure TCnDockPageControl.WMRButtonDown(var Message: TWMRButtonDown);
- begin
- { 欺骗系统以为是鼠标左键按下 }
- Message.Msg := WM_LBUTTONDOWN;
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbRight, msTabPage, GlobalDockClient.DoNCButtonDown);
- end;
- procedure TCnDockPageControl.WMRButtonUp(var Message: TWMRButtonUp);
- begin
- inherited;
- if GlobalDockClient <> nil then
- ButtonEvent(Self, Message, mbRight, msTabPage, GlobalDockClient.DoNCButtonUp);
- end;
- { TCnDockPresident }
- constructor TCnDockPresident.Create;
- begin
- { 创建列表和Hash表 }
- FDockServersList := TList.Create;
- FDockClientsList := TList.Create;
- FDockServersHash := TCnDockControlHashTable.Create(10, False);
- FDockClientsHash := TCnDockControlHashTable.Create(30, False);
- FDockableFormList := TList.Create;
- DockSiteList := TList.Create;
- end;
- destructor TCnDockPresident.Destroy;
- begin
- { 删除列表和Hash表 }
- FDockableFormList.Free;
- FDockServersList.Free;
- FDockClientsList.Free;
- FDockServersHash.Free;
- FDockClientsHash.Free;
- DockSiteList.Free;
- inherited Destroy;
- end;
- function TCnDockPresident.FindDockClientForm(AName: string): TControl;
- var i: Integer;
- begin
- Result := nil;
- for i := 0 to FDockServersList.Count - 1 do
- begin
- if TControl(FDockServersList[i]).Name = AName then
- begin
- Result := TControl(FDockServersList[i]);
- Exit;
- end;
- end;
- end;
- function TCnDockPresident.FindDockServerForm(AName: string): TControl;
- var i: Integer;
- begin
- Result := nil;
- for i := 0 to FDockClientsList.Count - 1 do
- begin
- if TControl(FDockClientsList[i]).Name = AName then
- begin
- Result := TControl(FDockClientsList[i]);
- Exit;
- end;
- end;
- end;
- function TCnDockPresident.FindDockControlForm(AName: string): TControl;
- begin
- Result := FindDockServerForm(AName);
- if Result = nil then
- FindDockClientForm(AName);
- end;
- function TCnDockPresident.GetFormVisible(DockWindow: TWinControl): Boolean;
- begin
- Result := CnDockFormControl.GetFormVisible(DockWindow);
- end;
- procedure TCnDockPresident.HideDockForm(DockWindow: TControl);
- begin
- CnDockFormControl.HideDockForm(DockWindow);
- end;
- procedure TCnDockPresident.LoadDockTreeFromFile(FileName: string);
- begin
- BeginLoad;
- try
- CnDockFormControl.LoadDockTreeFromFile(FileName);
- finally
- EndLoad;
- end;
- end;
- procedure TCnDockPresident.LoadDockTreeFromReg(RootKey: DWORD;
- RegPath: string);
- begin
- BeginLoad;
- try
- CnDockFormControl.LoadDockTreeFromReg(RootKey, RegPath);
- finally
- EndLoad;
- end;
- end;
- procedure TCnDockPresident.SaveDockTreeToFile(FileName: string);
- begin
- BeginSave;
- try
- CnDockFormControl.SaveDockTreeToFile(FileName);
- finally
- EndSave;
- end;
- end;
- procedure TCnDockPresident.SaveDockTreeToReg(RootKey: DWORD;
- RegPath: string);
- begin
- BeginSave;
- try
- CnDockFormControl.SaveDockTreeToReg(RootKey, RegPath);
- finally
- EndSave;
- end;
- end;
- procedure TCnDockPresident.SetConjoinDockHostBorderStyle(
- Value: TFormBorderStyle);
- begin
- CnDockFormControl.SetConjoinDockHostBorderStyle(Value);
- end;
- procedure TCnDockPresident.SetTabDockHostBorderStyle(
- Value: TFormBorderStyle);
- begin
- CnDockFormControl.SetTabDockHostBorderStyle(Value);
- end;
- procedure TCnDockPresident.ShowDockForm(DockWindow: TWinControl);
- begin
- CnDockFormControl.ShowDockForm(DockWindow);
- end;
- procedure TCnDockPresident.BeginLoad;
- var i: Integer;
- begin
- Inc(FLoadCount);
- if FLoadCount = 1 then
- begin
- FDockServersHash.MakeEmpty;
- for i := 0 to FDockServersList.Count - 1 do
- FDockServersHash.Insert(TControl(FDockServersList[i]).Name, FDockServersList[i]);
- FDockClientsHash.MakeEmpty;
- for i := 0 to FDockClientsList.Count - 1 do
- FDockClientsHash.Insert(TControl(FDockClientsList[i]).Name, FDockClientsList[i]);
- end;
- end;
- procedure TCnDockPresident.EndLoad;
- begin
- Dec(FLoadCount);
- if FLoadCount <= 0 then
- begin
- FLoadCount := 0;
- FDockServersHash.MakeEmpty;
- FDockClientsHash.MakeEmpty;
- end;
- end;
- function TCnDockPresident.IsLoading: Boolean;
- begin
- Result := FLoadCount > 0;
- end;
- procedure TCnDockPresident.BeginSave;
- begin
- Inc(FSaveCount);
- end;
- procedure TCnDockPresident.EndSave;
- begin
- Dec(FSaveCount);
- if FSaveCount <= 0 then
- FSaveCount := 0;
- end;
- function TCnDockPresident.IsSaving: Boolean;
- begin
- Result := FSaveCount > 0;
- end;
- procedure TCnDockPresident.AddDockClientToDockManager(
- AControl: TControl);
- begin
- FDockClientsList.Add(AControl);
- FDockClientsHash.Insert(AControl.Name, AControl);
- end;
- procedure TCnDockPresident.AddDockServerToDockManager(
- AControl: TControl);
- begin
- FDockServersList.Add(AControl);
- FDockServersHash.Insert(AControl.Name, AControl);
- end;
- procedure TCnDockPresident.RemoveDockClientFromDockManager(
- AControl: TControl);
- begin
- FDockClientsList.Remove(AControl);
- FDockClientsHash.Remove(AControl.Name);
- end;
- procedure TCnDockPresident.RemoveDockServerFromDockManager(
- AControl: TControl);
- begin
- FDockServersList.Remove(AControl);
- FDockServersHash.Remove(AControl.Name);
- end;
- procedure TCnDockPresident.BeginDrag(Control: TControl; Immediate: Boolean; Threshold: Integer);
- var
- P: TPoint;
- begin
- if (TCnControlAccess(Control).DragKind <> dkDock) then
- { 如果Control的DragKind属性不是dkDock,就推出 }
- Exit;
- // raise EInvalidOperation.CreateRes(@SCannotDragForm);
- CalcDockSizes(Control);
- if (DragControl = nil) or (DragControl = Pointer($FFFFFFFF)) then
- begin
- DragControl := nil;
- if csLButtonDown in Control.ControlState then
- begin
- GetCursorPos(P);
- P := Control.ScreenToClient(P);
- Control.Perform(WM_LBUTTONUP, 0, Longint(PointToSmallPoint(P)));
- end;
- { 当Threshold<0的时候,使用默认的值Mouse.DragThreshold }
- if Threshold < 0 then
- Threshold := Mouse.DragThreshold;
- { 防止在BeginDrag里面调用EndDrag }
- if DragControl <> Pointer($FFFFFFFF) then
- DragInitControl(Control, Immediate, Threshold);
- end;
- end;
- procedure TCnDockPresident.DragInitControl(Control: TControl;
- Immediate: Boolean; Threshold: Integer);
- var
- // ADragObject: TCnDragDockObject;
- ARect: TRect;
- procedure DoStartDock;
- begin
- if Assigned(GlobalDockClient) then
- GlobalDockClient.FormStartDock(DragObject);
- if DragObject = nil then
- begin
- DragObject := TCnDragDockObject.Create(Control);
- DragFreeObject := True;
- end;
- end;
- begin
- DragControl := Control;
- try
- DragObject := nil;
- DragFreeObject := False;
- { 调用StartDock事件 }
- DoStartDock;
- if DragControl = nil then Exit;
- with DragObject do
- begin
- if Control.HostDockSite is TCnCustomDockPanel then
- ARect := TCnCustomDockPanel(Control.HostDockSite).CnDockManager.GetFrameRectEx(Control)
- else GetWindowRect(TWinControl(Control).Handle, ARect);
- DockRect := ARect;
- EraseDockRect := DockRect;
- end;
- DragInit(DragObject, Immediate, Threshold);
- except
- DragControl := nil;
- raise;
- end;
- end;
- procedure TCnDockPresident.DragInit(ADragObject: TCnDragDockObject;
- Immediate: Boolean; Threshold: Integer);
- begin
- DragObject := ADragObject;
- DragObject.DragTarget := nil;
- GetCursorPos(DragStartPos);
- DragObject.DragPos := DragStartPos;
- DragSaveCursor := Windows.GetCursor;
- DragCapture := DragObject.Capture;
- DragThreshold := Threshold;
- with ADragObject, DockRect do
- begin
- if Right - Left > 0 then
- MouseDeltaX := (DragPos.x - Left) / (Right - Left) else
- MouseDeltaX := 0;
- if Bottom - Top > 0 then
- MouseDeltaY := (DragPos.y - Top) / (Bottom - Top) else
- MouseDeltaY := 0;
- if Immediate then
- begin
- ActiveDrag := dopDock;
- DrawDragDockImage;
- end
- else ActiveDrag := dopNone;
- end;
- DragImageList := DragObject.GetDragImages;
- if DragImageList <> nil then
- with DragStartPos do DragImageList.BeginDrag(GetDeskTopWindow, X, Y);
- QualifyingSites := TSiteList.Create;
- if ActiveDrag <> dopNone then DragTo(DragStartPos);
- end;
- procedure TCnDockPresident.DragTo(const Pos: TPoint);
- var
- DragCursor: TCursor;
- Target: TControl;
- TargetHandle: HWND;
- DoErase: Boolean;
- TempAlign: TAlign;
- // CanDock: Boolean;
- // R: TRect;
- begin
- if {(ActiveDrag <> dopNone) or }(Abs(DragStartPos.X - Pos.X) >= DragThreshold) or
- (Abs(DragStartPos.Y - Pos.Y) >= DragThreshold) then
- begin
- { 查找到停靠目标 }
- Target := DragFindTarget(Pos, TargetHandle, TCnControlAccess(DragControl).DragKind, DragControl);
- if (ActiveDrag = dopNone) and (DragImageList <> nil) then
- with DragStartPos do DragImageList.BeginDrag(GetDeskTopWindow, X, Y);
- DoErase := ActiveDrag <> dopNone;
- ActiveDrag := dopDock;
- if DragObject.CanLeave(TWinControl(Target)) then
- begin
- DoDockOver(dsDragLeave);
- if DragObject = nil then Exit;
- DragObject.DragTarget := Target;
- DragObject.DragHandle := TargetHandle;
- DragObject.DragPos := Pos;
- DoDockOver(dsDragEnter);
- if DragObject = nil then Exit;
- end;
- DragObject.DragPos := Pos;
- if DragObject.DragTarget <> nil then
- DragObject.DragTargetPos := TControl(DragObject.DragTarget).ScreenToClient(Pos);
- DragCursor := DragObject.GetDragCursor(DoDockOver(dsDragMove), Pos.X, Pos.Y);
- if DragImageList <> nil then
- begin
- if (Target = nil) or (csDisplayDragImage in Target.ControlStyle) then
- begin
- DragImageList.DragCursor := DragCursor;
- if not DragImageList.Dragging then
- DragImageList.BeginDrag(GetDeskTopWindow, Pos.X, Pos.Y)
- else DragImageList.DragMove(Pos.X, Pos.Y);
- end
- else begin
- DragImageList.EndDrag;
- Windows.SetCursor(Screen.Cursors[DragCursor]);
- end;
- end;
- // if Target = nil then DragObject.DropOnControl := nil;
- ResetCursor;
- if ActiveDrag = dopDock then
- begin
- with DragObject do
- begin
- { DoGetSiteInfo(Target, Control, R, Pos, CanDock);
- if not CanDock then
- begin
- Target := nil;
- DropOnControl := nil;
- end;}
- if Target = nil then
- begin
- if Assigned(GlobalDockClient) then
- GlobalDockClient.FormPositionDockRect(DragObject);
- end
- else begin
- { 获得DropOnControl }
- DropOnControl := GetDropCtl;
- TempAlign := DropAlign;
- if DropOnControl = nil then
- DoGetDockEdge(TargetControl, DragTargetPos, TempAlign)
- else
- DoGetDockEdge(DropOnControl, DropOnControl.ScreenToClient(Pos), TempAlign);
- // if TempAlign <> DropAlign then
- DropAlign := TempAlign;
- end;
- end;
- if DragObject <> nil then
- DragObject.DrawDragRect(DoErase);
- end;
- end;
- end;
- function TCnDockPresident.DragFindTarget(const Pos: TPoint; var Handle: HWND;
- DragKind: TDragKind; Client: TControl): Pointer;
- begin
- Result := GetDockSiteAtPos(Pos, Client);
- if Result <> nil then
- Handle := TWinControl(Result).Handle;
- end;
- function TCnDockPresident.DoDockOver(DragState: TDragState): Boolean;
- var Target: TControl;
- DockClient: TCnDockClient;
- begin
- Result := True;
- if DragObject.DragTarget <> nil then
- begin
- Target := TControl(DragObject.DragTarget);
- with Target.ScreenToClient(DragObject.DragPos) do
- if Target is TCnCustomDockControl then
- TCnCustomDockControl(Target).CustomDockOver(DragObject, X, Y, DragState, Result)
- else if Target is TForm then
- begin
- DockClient := FindDockClient(Target);
- if DockClient <> nil then
- DockClient.FormDockOver(DragObject, X, Y, DragState, Result);
- end;
- end;
- end;
- function TCnDockPresident.DragFindWindow(const Pos: TPoint): HWND;
- begin
- Result := DragObject.DragFindWindow(Pos);
- end;
- function TCnDockPresident.GetDockSiteAtPos(MousePos: TPoint;
- Client: TControl): TWinControl;
- var
- I: Integer;
- R: TRect;
- Site: TWinControl;
- CanDock, ControlKeyDown: Boolean;
- function ValidDockTarget(Target: TWinControl): Boolean;
- var
- Info: TCheckTargetInfo;
- Control: TWinControl;
- R1, R2: TRect;
- begin
- Result := True;
- { Find handle for topmost container of current }
- Info.CurrentWnd := DragFindWindow(MousePos);
- if Info.CurrentWnd = 0 then Exit;
- if (GetWindow(Info.CurrentWnd, GW_OWNER) <> Application.Handle) then
- begin
- Control := FindControl(Info.CurrentWnd);
- if Control = nil then Exit;
- while Control.Parent <> nil do Control := Control.Parent;
- Info.CurrentWnd := Control.Handle;
- end;
- { Find handle for topmost container of target }
- Control := Target;
- while Control.Parent <> nil do Control := Control.Parent;
- Info.TargetWnd := Control.Handle;
- if Info.CurrentWnd = Info.TargetWnd then Exit;
- { Find handle for topmost container of client }
- if Client.Parent <> nil then
- begin
- Control := Client.Parent;
- while Control.Parent <> nil do Control := Control.Parent;
- Info.ClientWnd := Control.Handle;
- end
- else if Client is TWinControl then
- Info.ClientWnd := TWinControl(Client).Handle
- else
- Info.ClientWnd := 0;
- Info.Found := False;
- Info.MousePos := MousePos;
- EnumThreadWindows(GetCurrentThreadID, @IsBeforeTargetWindow, Longint(@Info));
- { CurrentWnd is in front of TargetWnd, so check whether they're overlapped. }
- if Info.Found then
- begin
- GetWindowRect(Info.CurrentWnd, R1);
- DoGetSiteInfo(Target, Client, R2, MousePos, CanDock);
- // TCnWinControlAccess(Target).GetSiteInfo(Client, R2, MousePos, CanDock);
- { Docking control's host shouldn't count as an overlapped window }
- if (DragObject.Control.HostDockSite <> nil)
- and (DragObject.Control.HostDockSite.Handle = Info.CurrentWnd) then
- Exit;
- if IntersectRect(R1, R1, R2) then
- Result := False;
- end;
- end;
- function IsSiteChildOfClient: Boolean;
- begin
- if Client is TWinControl then
- Result := IsChild(TWinControl(Client).Handle, Site.Handle)
- else
- Result := False;
- end;
- begin
- Result := nil;
- ControlKeyDown := (GetKeyState(VK_CONTROL) and not $7FFF) <> 0;
- if (DockSiteList = nil) or ControlKeyDown then Exit;
- QualifyingSites.Clear;
- for I := 0 to DockSiteList.Count - 1 do
- begin
- Site := TWinControl(DockSiteList[I]);
- if (Site <> Client) and Site.Showing and Site.Enabled and
- IsWindowVisible(Site.Handle) and (not IsSiteChildOfClient) //and
- {((Client.HostDockSite <> Site) or (Site.VisibleDockClientCount > 1)) }then
- begin
- CanDock := True;
- DoGetSiteInfo(Site, Client, R, MousePos, CanDock);
- if CanDock and PtInRect(R, MousePos) then
- QualifyingSites.AddSite(Site);
- end;
- end;
- if QualifyingSites.Count > 0 then
- Result := QualifyingSites.GetTopSite;
- if (Result <> nil) and not ValidDockTarget(Result) then
- Result := nil;
- { if Result <> nil then
- begin
- DoGetSiteInfo(Site, Client, R, MousePos, CanDock);
- if not CanDock then
- Result := nil;
- end;}
- end;
- procedure TCnDockPresident.DragDone(Drop: Boolean);
- function CheckUndock: Boolean;
- begin
- Result := DragObject.DragTarget <> nil;
- with DragControl do
- if Drop and (ActiveDrag = dopDock) then
- if Floating or (HostDockSite = nil) then
- Result := True
- else
- Result := DoUnDock(DragObject, DragObject.DragTarget, DragControl);
- end;
- procedure DoFloatForm(Control: TControl);
- var
- WasVisible: Boolean;
- begin
- if (Control.FloatingDockSiteClass = Control.ClassType) then
- begin
- WasVisible := Control.Visible;
- try
- Control.Dock(nil, DragObject.DockRect);
- if (Control.Left <> DragObject.DockRect.Left) or (Control.Top <> DragObject.DockRect.Top) then
- begin
- Control.Left := DragObject.DockRect.Left;
- Control.Top := DragObject.DockRect.Top;
- end;
- finally
- if WasVisible then Control.BringToFront;
- end;
- end;
- end;
- var
- DragSave: TCnDragDockObject;
- DockObject: TCnDragDockObject;
- Accepted: Boolean;
- TargetPos: TPoint;
- ParentForm: TCustomForm;
- begin
- DockObject := nil;
- DragSave := nil;
- Accepted := False;
- if (DragObject = nil) or DragObject.Cancelling then Exit; // recursion control
- try
- DragSave := DragObject;
- try
- DragObject.Cancelling := True;
- DragObject.ReleaseCapture(DragCapture);
- if ActiveDrag = dopDock then
- begin
- DockObject := DragObject;
- DockObject.EraseDragDockImage;
- DockObject.Floating := DockObject.DragTarget = nil;
- end;
- if (DragObject.DragTarget <> nil) and
- (TObject(DragObject.DragTarget) is TControl) then
- TargetPos := DragObject.DragTargetPos
- else
- TargetPos := DragObject.DragPos;
- Accepted := CheckUndock and
- {(((ActiveDrag = dopDock) and DockObject.Floating) or
- ((ActiveDrag <> dopNone) and DoDockOver(dsDragLeave))) and}
- Drop;
- if ActiveDrag = dopDock then
- begin
- if Accepted and DockObject.Floating then
- begin
- ParentForm := GetParentForm(DockObject.Control);
- if (ParentForm <> nil) and
- (ParentForm.ActiveControl = DockObject.Control) then
- ParentForm.ActiveControl := nil;
- DoFloatForm(DragControl);
- end;
- end
- else begin
- if DragImageList <> nil then DragImageList.EndDrag
- else Windows.SetCursor(DragSaveCursor);
- end;
- DragControl := nil;
- if DragSave.DragTarget <> nil then
- begin
- if not Accepted then
- begin
- DragSave.DragPos := Point(0, 0);
- TargetPos.X := 0;
- TargetPos.Y := 0;
- end else
- // if Drop then
- DoDockDrop(DragSave, DragSave.DragPos);
- end;
- DragObject := nil;
- finally
- QualifyingSites.Free;
- QualifyingSites := nil;
- DragSave.Cancelling := False;
- DragSave.Finished(DragSave.DragTarget, TargetPos.X, TargetPos.Y, Accepted);
- DragObject := nil;
- end;
- finally
- DragControl := nil;
- // if DragFreeObject then
- DragSave.Free;
- end;
- end;
- procedure TCnDockPresident.RegisterDockSite(Site: TWinControl;
- DoRegister: Boolean);
- var
- Index: Integer;
- begin
- if (Site <> nil) then
- begin
- if DockSiteList = nil then DockSiteList := TList.Create;
- Index := DockSiteList.IndexOf(Pointer(Site));
- if DoRegister then
- begin
- if Index = -1 then DockSiteList.Add(Pointer(Site));
- end
- else begin
- if Index <> -1 then DockSiteList.Delete(Index);
- end;
- end;
- end;
- procedure TCnDockPresident.DoGetSiteInfo(Target, Client: TControl;
- var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
- var DockClient: TCnDockClient;
- begin
- if Target is TCnCustomDockControl then
- TCnCustomDockControl(Target).CustomGetSiteInfo(DragObject, Client, InfluenceRect, MousePos, CanDock)
- else if Target is TForm then
- begin
- DockClient := FindDockClient(Target);
- if DockClient <> nil then
- DockClient.FormGetSiteInfo(DragObject, Client, InfluenceRect, MousePos, CanDock);
- end
- else CanDock := False;
- end;
- procedure TCnDockPresident.DoDockDrop(Source: TCnDragDockObject; Pos: TPoint);
- var Target: TWinControl;
- DockClient: TCnDockClient;
- begin
- if Source.DragTarget <> nil then
- begin
- Target := Source.TargetControl;
- with Target.ScreenToClient(Pos) do
- if Target is TCnCustomDockControl then
- TCnCustomDockControl(Target).CustomDockDrop(Source, X, Y)
- else if Target is TForm then
- begin
- DockClient := FindDockClient(Target);
- if DockClient <> nil then
- DockClient.FormDockDrop(Source, X, Y);
- end;
- end;
- end;
- function TCnDockPresident.DoUnDock(Source: TCnDragDockObject; Target: TWinControl; Client: TControl): Boolean;
- begin
- if Client.HostDockSite is TCnCustomDockControl then
- Result := TCnCustomDockControl(Client.HostDockSite).CustomUnDock(Source, Target, Client)
- else Result := False;
- end;
- procedure TCnDockPresident.DoEndDrag(Target: TObject; X, Y: Integer);
- var DockClient: TCnDockClient;
- begin
- if Target is TCnCustomDockControl then
- TCnCustomDockControl(Target).CustomEndDock(Target, X, Y)
- else if Target is TForm then
- begin
- DockClient := FindDockClient(TControl(Target));
- if DockClient <> nil then
- DockClient.FormEndDock(Target, X, Y);
- end;
- end;
- procedure TCnDockPresident.CalcDockSizes(Control: TControl);
- var //BorderWidth: Integer;
- Rect: TRect;
- begin
- with Control do
- if Floating then
- begin
- UndockHeight := Height;
- UndockWidth := Width;
- end
- else if HostDockSite is TCnCustomDockPanel then
- begin
- //BorderWidth := TCnCustomDockPanel(HostDockSite).CnDockManager.BorderWidth;
- Rect := TCnCustomDockPanel(HostDockSite).CnDockManager.GetFrameRect(Control);
- if (HostDockSite.Align in [alTop, alBottom]) then
- TBDockHeight := Rect.Bottom - Rect.Top//Height + 2*BorderWidth
- else if (HostDockSite.Align in [alLeft, alRight]) then
- LRDockWidth := Rect.Right - Rect.Left;//Width + 2*BorderWidth;
- end;
- end;
- procedure TCnDockPresident.CancelDrag;
- begin
- if DragObject <> nil then DragDone(False);
- DragControl := nil;
- end;
- procedure TCnDockPresident.DoGetDockEdge(Target: TControl; MousePos: TPoint; var DropAlign: TAlign);
- var DockClient: TCnDockClient;
- begin
- if Target is TCnCustomDockControl then
- TCnCustomDockControl(Target).CustomGetDockEdge(DragObject, MousePos, DropAlign)
- else if Target is TForm then
- begin
- DockClient := FindDockClient(Target);
- if DockClient <> nil then
- DockClient.FormGetDockEdge(DragObject, MousePos, DropAlign);
- end;
- end;
- procedure TCnDockPresident.ResetCursor;
- begin
- if (GlobalDockClient <> nil) and (GlobalDockClient.DockStyle <> nil) then
- GlobalDockClient.DockStyle.ResetCursor(DragObject);
- end;
- { TSiteList }
- procedure TSiteList.AddSite(ASite: TWinControl);
- function GetTopParent: HWND;
- var
- NextParent: HWND;
- begin
- NextParent := ASite.Handle;
- Result := NextParent;
- while NextParent <> 0 do
- begin
- Result := NextParent;
- NextParent := GetParent(NextParent);
- end;
- end;
- var
- SI: PSiteInfoRec;
- Index: Integer;
- begin
- New(SI);
- SI.Site := ASite;
- SI.TopParent := GetTopParent;
- if Find(SI.TopParent, Index) then
- Insert(Index, SI) else
- Add(SI);
- end;
- procedure TSiteList.Clear;
- var
- I: Integer;
- begin
- for I := 0 to Count - 1 do
- Dispose(PSiteInfoRec(Items[I]));
- inherited Clear;
- end;
- function TSiteList.Find(ParentWnd: Hwnd; var Index: Integer): Boolean;
- begin
- Index := 0;
- Result := False;
- while Index < Count do
- begin
- Result := (PSiteInfoRec(Items[Index]).TopParent = ParentWnd);
- if Result then Exit;
- Inc(Index);
- end;
- end;
- function TSiteList.GetTopSite: TWinControl;
- var
- Index: Integer;
- DesktopWnd, CurrentWnd: HWND;
- begin
- Result := nil;
- if Count = 0 then Exit
- else if Count = 1 then Result := PSiteInfoRec(Items[0]).Site
- else begin
- DesktopWnd := GetDesktopWindow;
- CurrentWnd := GetTopWindow(DesktopWnd);
- while (Result = nil) and (CurrentWnd <> 0) do
- begin
- if Find(CurrentWnd, Index) then
- Result := PSiteInfoRec(List[Index])^.Site
- else
- CurrentWnd := GetNextWindow(CurrentWnd, GW_HWNDNEXT);
- end;
- end;
- end;
- { TCustomDockPanelSplitter }
- constructor TCustomDockPanelSplitter.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FAutoSnap := True;
- Align := alLeft;
- Width := 3;
- Cursor := crHSplit;
- FMinSize := 30;
- FResizeStyle := rsPattern;
- FOldSize := -1;
- end;
- destructor TCustomDockPanelSplitter.Destroy;
- begin
- FBrush.Free;
- inherited Destroy;
- end;
- procedure TCustomDockPanelSplitter.AllocateLineDC;
- begin
- FLineDC := GetDCEx(Parent.Handle, 0, DCX_CACHE or DCX_CLIPSIBLINGS
- or DCX_LOCKWINDOWUPDATE);
- if ResizeStyle = rsPattern then
- begin
- if FBrush = nil then
- begin
- FBrush := TBrush.Create;
- FBrush.Bitmap := AllocPatternBitmap(clBlack, clWhite);
- end;
- FPrevBrush := SelectObject(FLineDC, FBrush.Handle);
- end;
- end;
- procedure TCustomDockPanelSplitter.DrawLine;
- var
- P: TPoint;
- begin
- FLineVisible := not FLineVisible;
- P := Point(Left, Top);
- if Align in [alLeft, alRight] then
- P.X := Left + FSplit else
- P.Y := Top + FSplit;
- with P do PatBlt(FLineDC, X, Y, Width, Height, PATINVERT);
- end;
- procedure TCustomDockPanelSplitter.ReleaseLineDC;
- begin
- if FPrevBrush <> 0 then
- SelectObject(FLineDC, FPrevBrush);
- ReleaseDC(Parent.Handle, FLineDC);
- if FBrush <> nil then
- begin
- FBrush.Free;
- FBrush := nil;
- end;
- end;
- function TCustomDockPanelSplitter.FindControl: TControl;
- var
- P: TPoint;
- I: Integer;
- R: TRect;
- begin
- Result := nil;
- P := Point(Left, Top);
- case Align of
- alLeft: Dec(P.X);
- alRight: Inc(P.X, Width);
- alTop: Dec(P.Y);
- alBottom: Inc(P.Y, Height);
- else
- Exit;
- end;
- for I := 0 to Parent.ControlCount - 1 do
- begin
- Result := Parent.Controls[I];
- if Result.Visible and Result.Enabled then
- begin
- R := Result.BoundsRect;
- if (R.Right - R.Left) = 0 then
- if Align in [alTop, alLeft] then
- Dec(R.Left)
- else
- Inc(R.Right);
- if (R.Bottom - R.Top) = 0 then
- if Align in [alTop, alLeft] then
- Dec(R.Top)
- else
- Inc(R.Bottom);
- if PtInRect(R, P) then Exit;
- end;
- end;
- Result := nil;
- end;
- procedure TCustomDockPanelSplitter.RequestAlign;
- begin
- inherited RequestAlign;
- if (Cursor <> crVSplit) and (Cursor <> crHSplit) then Exit;
- if Align in [alBottom, alTop] then
- Cursor := crVSplit
- else
- Cursor := crHSplit;
- end;
- procedure TCustomDockPanelSplitter.Paint;
- const
- XorColor = $00FFD8CE;
- var
- FrameBrush: HBRUSH;
- R: TRect;
- begin
- R := ClientRect;
- Canvas.Brush.Color := Color;
- Canvas.FillRect(ClientRect);
- if Beveled then
- begin
- if Align in [alLeft, alRight] then
- InflateRect(R, -1, 2) else
- InflateRect(R, 2, -1);
- OffsetRect(R, 1, 1);
- FrameBrush := CreateSolidBrush(ColorToRGB(clBtnHighlight));
- FrameRect(Canvas.Handle, R, FrameBrush);
- DeleteObject(FrameBrush);
- OffsetRect(R, -2, -2);
- FrameBrush := CreateSolidBrush(ColorToRGB(clBtnShadow));
- FrameRect(Canvas.Handle, R, FrameBrush);
- DeleteObject(FrameBrush);
- end;
- if csDesigning in ComponentState then
- { Draw outline }
- with Canvas do
- begin
- Pen.Style := psDot;
- Pen.Mode := pmXor;
- Pen.Color := XorColor;
- Brush.Style := bsClear;
- Rectangle(0, 0, ClientWidth, ClientHeight);
- end;
- if Assigned(FOnPaint) then FOnPaint(Self);
- end;
- function TCustomDockPanelSplitter.DoCanResize(var NewSize: Integer): Boolean;
- begin
- Result := CanResize(NewSize);
- if Result and (NewSize <= MinSize) and FAutoSnap then
- NewSize := 0;
- end;
- function TCustomDockPanelSplitter.CanResize(var NewSize: Integer): Boolean;
- begin
- Result := True;
- if Assigned(FOnCanResize) then FOnCanResize(Self, NewSize, Result);
- end;
- procedure TCustomDockPanelSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer);
- var
- I: Integer;
- begin
- inherited MouseDown(Button, Shift, X, Y);
- if Button = mbLeft then
- begin
- FControl := FindControl;
- FDownPos := Point(X, Y);
- if Assigned(FControl) then
- begin
- if Align in [alLeft, alRight] then
- begin
- FMaxSize := Parent.ClientWidth - FMinSize;
- for I := 0 to Parent.ControlCount - 1 do
- with Parent.Controls[I] do
- if Visible and (Align in [alLeft, alRight]) then Dec(FMaxSize, Width);
- Inc(FMaxSize, FControl.Width);
- end
- else
- begin
- FMaxSize := Parent.ClientHeight - FMinSize;
- for I := 0 to Parent.ControlCount - 1 do
- with Parent.Controls[I] do
- if Align in [alTop, alBottom] then Dec(FMaxSize, Height);
- Inc(FMaxSize, FControl.Height);
- end;
- UpdateSize(X, Y);
- AllocateLineDC;
- with ValidParentForm(Self) do
- if ActiveControl <> nil then
- begin
- FActiveControl := ActiveControl;
- FOldKeyDown := TCnWinControlAccess(FActiveControl).OnKeyDown;
- TCnWinControlAccess(FActiveControl).OnKeyDown := FocusKeyDown;
- end;
- if ResizeStyle in [rsLine, rsPattern] then DrawLine;
- end;
- end;
- end;
- procedure TCustomDockPanelSplitter.UpdateControlSize;
- begin
- if FNewSize <> FOldSize then
- begin
- case Align of
- alLeft: FControl.Width := FNewSize;
- alTop: FControl.Height := FNewSize;
- alRight:
- begin
- Parent.DisableAlign;
- try
- FControl.Left := FControl.Left + (FControl.Width - FNewSize);
- FControl.Width := FNewSize;
- finally
- Parent.EnableAlign;
- end;
- end;
- alBottom:
- begin
- Parent.DisableAlign;
- try
- FControl.Top := FControl.Top + (FControl.Height - FNewSize);
- FControl.Height := FNewSize;
- finally
- Parent.EnableAlign;
- end;
- end;
- end;
- TCnControlAccess(FControl).Resize;
- Update;
- if Assigned(FOnMoved) then FOnMoved(Self);
- FOldSize := FNewSize;
- // Canvas.FillRect(GetClientRect);
- end;
- end;
- procedure TCustomDockPanelSplitter.CalcSplitSize(X, Y: Integer; var NewSize, Split: Integer);
- var
- S: Integer;
- begin
- if Align in [alLeft, alRight] then
- Split := X - FDownPos.X
- else
- Split := Y - FDownPos.Y;
- S := 0;
- case Align of
- alLeft: S := FControl.Width + Split;
- alRight: S := FControl.Width - Split;
- alTop: S := FControl.Height + Split;
- alBottom: S := FControl.Height - Split;
- end;
- NewSize := S;
- if S < FMinSize then
- NewSize := FMinSize
- else if S > FMaxSize then
- NewSize := FMaxSize;
- if S <> NewSize then
- begin
- if Align in [alRight, alBottom] then
- S := S - NewSize else
- S := NewSize - S;
- Inc(Split, S);
- end;
- end;
- procedure TCustomDockPanelSplitter.UpdateSize(X, Y: Integer);
- begin
- CalcSplitSize(X, Y, FNewSize, FSplit);
- end;
- procedure TCustomDockPanelSplitter.MouseMove(Shift: TShiftState; X, Y: Integer);
- var
- NewSize, Split: Integer;
- begin
- inherited;
- if (ssLeft in Shift) and Assigned(FControl) then
- begin
- CalcSplitSize(X, Y, NewSize, Split);
- if (DoCanResize(NewSize) and (FNewSize <> NewSize)) then
- begin
- if ResizeStyle in [rsLine, rsPattern] then DrawLine;
- FNewSize := NewSize;
- FSplit := Split;
- if ResizeStyle = rsUpdate then UpdateControlSize;
- if ResizeStyle in [rsLine, rsPattern] then DrawLine;
- end;
- end;
- end;
- procedure TCustomDockPanelSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer);
- begin
- inherited;
- if Assigned(FControl) then
- begin
- if ResizeStyle in [rsLine, rsPattern] then DrawLine;
- UpdateControlSize;
- StopSizing;
- end;
- end;
- procedure TCustomDockPanelSplitter.FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
- begin
- if Key = VK_ESCAPE then
- StopSizing
- else if Assigned(FOldKeyDown) then
- FOldKeyDown(Sender, Key, Shift);
- end;
- procedure TCustomDockPanelSplitter.SetBeveled(Value: Boolean);
- begin
- FBeveled := Value;
- Repaint;
- end;
- procedure TCustomDockPanelSplitter.StopSizing;
- begin
- if Assigned(FControl) then
- begin
- if FLineVisible then DrawLine;
- FControl := nil;
- ReleaseLineDC;
- if Assigned(FActiveControl) then
- begin
- TCnWinControlAccess(FActiveControl).OnKeyDown := FOldKeyDown;
- FActiveControl := nil;
- end;
- end;
- if Assigned(FOnMoved) then
- FOnMoved(Self);
- end;
- end.
|