以上所講的是如何在主窗口上停靠窗體,原代碼都通過測試。同理,我們可以在主窗口的右邊,下邊,上邊都實現停靠功能。
對了,剛才我們只介紹了OnDockOver和OnDockDrop,忘了介紹別的事件,下面簡單介紹一下:
3.OnGetSiteInfo(Sender: TObject; DockClIEnt: TControl;
var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
這個事件是在窗體移動時觸發的,所以經常觸發,它裡面的DockClIEnt就是TDockableForm,
有一個引用參數叫CanDock,和OnDockOver中的Accept差不多,都是詢問是否允許停靠。在這裡可以不寫,CanDock默認就是True,也可以寫上CanDock := DockClIEnt is TDockableForm;
4.OnStartDock(Sender: TObject;
var DragObject: TDragDockObject);
5.OnEndDock(Sender, Target: TObject; X, Y: Integer);
6.OnUnDock(Sender: TObject; ClIEnt: TControl;
NewTarget: TWinControl; var Allow: Boolean);
這三個事件都是在DockableForm上面有用,意思分別是停靠開始,停靠結尾,不停靠(也就是被拖出來時)。
OnStartDock和OnEndDock經常會被觸發,
OnUnDock只在停靠窗體變成浮動時觸發
講了那麼多,大家有沒有被搞糊塗?那好,我來做一下總結:
在Delphi中只要是從TWinControl繼承的控件都支持被停靠(如上面的LeftDockPanel),也就是有DockSite這個屬性;所有從TControl繼承的控件都支持停靠(如上面的DockableForm),也就是有DragKind這個屬性.所以支持被停靠的控件都支持停靠,支持停靠的控件不一定支持被停靠,道理很簡單,因為TWinControl繼承於TControl。OnDockOver事件是控制停靠窗體的預覽位置;OnDockDrap事件是控制停靠窗體的最終位置;OnGetSiteInfo是詢問是否可以停靠;OnStartDock是停靠開始,OnEndDock是停靠結尾,OnUnDock是不停靠(也就是被拖出來時)。
想必Delphi用的熟的大蝦都知道在Delphi的可停靠窗體間可以相互停靠,而且花樣還很多,可以停靠成並排的,也可以停靠成PageControl樣式的,兩個可停靠窗體合並後的窗體又可以再和別的可停靠窗體合並,形成樹狀。下面來介紹這方面的技術:
說道這裡,我們不得不介紹一下CM_DOCKCLIENT消息和TCMDockClIEnt結構,
CM_DOCKCLIENT消息和TCMDockClient結構是相互對應的,TCMDockClIEnt的結構是:
TCMDockClIEnt = packed record
Msg: Cardinal;
DockSource: TDragDockObject;
MousePos: TSmallPoint;
Result: Integer;
end;
其中DockSource包含了停靠—拖動操作的信息,前面已經提到過;MousePos是鼠標的位置。CM_DOCKCLIENT事件在停靠和被停靠控件都可以捕獲,因為它是TWinControl類發出的,
代碼如下:
procedure TWinControl.DockDrop(Source: TDragDockObject; X, Y: Integer);
begin
if (Perform(CM_DOCKCLIENT, Integer(Source), Integer(SmallPoint(X, Y))) >= 0)
and Assigned(FOnDockDrop) then
FOnDockDrop(Self, Source, X, Y);
end;