分享

docksite 停靠

 一路狂奔141 2014-05-05

 

在查看代码时,对docksite这个属性很好奇,百度搜了很久,发现了一个很好玩的东西。关于如何制作类似工具栏的东东,可以把它拖出来作为浮动工具条。还有可以把它拖到窗体的左边,形成竖条工具条。

大体的内容如下:

在Delphi中只要是从TWinControl继承的控件都支持被停靠(如上面的LeftDockPanel),也就是有DockSite这个属性;所有从TControl继承的控件都支持停靠(如上面的DockableForm),也就是有DragKind这个属性.所以支持被停靠的控件都支持停靠,支持停靠的控件不一定支持被停靠,道理很简单,因为TWinControl继承于TControl。

基本的步骤:
在TWinControl类中有一个DockSite属性(boolean),它的作用是是否允许别的控件停靠在它的上面,在TControl类中有一个DragKind属性,如果要这个控件能停靠在别的控件上,就把DragKind属性设成dkDock。就这么简单,只要设置一下属性,一个支持停靠的程序就完成了。

假定主窗口左边可以停靠,在主窗口上放一个Align属性为alLeft的Panel(可用其他能被停靠的控件),取名为LeftDockPanel,宽度为0,DockSite属性为True。在它右边再放一个TSplitter,取名为LeftSplitter,Align属性为alLeft。建一个窗体,取名叫DockableForm,DragKind属性设成dkDock,DragMode属性设为dmAutomatic(自动停靠)。

上面操作完成之后,并不能达到想要的效果,停靠的窗体停靠进去后就不见了。这与其触发的事件有关系,分别为:
OnDockOver(Sender:   TObject;   Source:   TDragDockObject;   X,   Y:   Integer;   State:   TDragState;   var   Accept:   Boolean);
OnDockDrop(Sender:   TObject;   Source:   TDragDockObject;   X,   Y:   Integer);
OnGetSiteInfo(Sender:   TObject;   DockClient:   TControl;   var   InfluenceRect:   TRect;   MousePos:   TPoint;   var   CanDock:    Boolean);
OnStartDock(Sender:   TObject;   var   DragObject:   TDragDockObject);
OnEndDock(Sender,   Target:   TObject;   X,   Y:   Integer);
OnUnDock(Sender:   TObject;   Client:   TControl;   NewTarget:   TWinControl;   var   Allow:   Boolean);

OnDockOver事件是控制停靠窗体的预览位置;OnDockDrap事件是控制停靠窗体的最终位置;OnGetSiteInfo是询问是否可以停靠;OnStartDock是停靠开始,OnEndDock是停靠结尾,OnUnDock是不停靠(也就是被拖出来时)。


OnDockOver是在停靠控件(DockableForm)掠过被停靠控件(LeftDockPanel)时触发的。Source包含了停靠—拖动操作的信息,其中有一个重要的属性是Control,就是DockableForm,另一个重要的属性是DockRect,就是停靠的位置;X,Y是鼠标的位置,State的状态有dsDragEnter,   dsDragLeave,   dsDragMove,分别表示拖动进入,拖动离开,拖动移动;Accept是是否同意停靠的意思。OnDockOver事件主要作用是控制停靠窗体的预览位置。在该方法中添加如下代码:
var
  ARect:   TRect;
begin
  Accept   :=   Source.Control   is   TDockableForm;
  if   Accept   then
  begin
    //修改预览停靠位置
    ARect.TopLeft   :=   LeftDockPanel.ClientToScreen(Point(0,   0));
    ARect.BottomRight   :=   LeftDockPanel.ClientToScreen(
    Point(Self.ClientWidth   div   3,   LeftDockPanel.Height));
    Source.DockRect   :=   ARect;
    end;
end;

OnDockDrop是在停靠窗体进入被停靠控件时发生的,作用是控制停靠窗体的最终位置。参数和OnDockOver差不多。在该方法中添加如下代码:
begin
  LeftDockPanel.Width := ClientWidth div 3;
  LeftSplitter.Left := LeftDockPanel.Width+LeftSplitter.Width;
end;

添加了以上代码之后,当我们把停靠窗体关闭时,会发现装载DockableForm的LeftDockPanel不能还原,此时,可以在DockableForm的OnClose事件中,把LeftDockPanel的宽度设为0。在OnClose事件中添加如下代码:
begin 
  MainForm.LeftDockPanel.Width := 0;
  Action := caHide;
end;

停靠窗体设置完成。。同理可以在主窗体的其他位置都实现这个功能。

OnGetSiteInfo是在窗体移动时触发的,所以经常触发,它里面的DockClient就是TDockableForm。有一个引用参数叫CanDock,和OnDockOver中的Accept差不多,都是询问是否允许停靠。在这里可以不写,CanDock默认就是True,也可以写上CanDock := DockClient is TDockableForm;

OnStartDock,OnEndDock,OnUnDock这三个事件都是在DockableForm上面有用,意思分别是停靠开始,停靠结尾,不停靠。OnStartDock和OnEndDock经常会被触发,OnUnDock只在停靠窗体变成浮动时触发。


什么时候装下Delphi验证。。\(^o^)/~

 

 

 


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多