Delphi 停靠技术的应用2(窗体之间的相互停靠,引入宿主窗体)

        Delphi的可停靠窗体间可以相互停靠,而且花样还很多,可以停靠成并排的,也可以停靠成PageControl样式的,两个可停靠窗体合并后的窗体又可以再和别的可停靠窗体合并,形成树状。下面来介绍这方面的技术。

 

一、基础知识介绍

1、CM_DOCKCLIENT消息和TCMDockClient结构,CM_DOCKCLIENT消息和TCMDockClient结构是相互对应的。

1>、TCMDockClient的结构是:

 TCMDockClient = packed record
  Msg: Cardinal;
  DockSource: TDragDockObject;
  MousePos: TSmallPoint;
  Result: Integer;
 end;

参数说明:   

  DockSource:包含了停靠—拖动操作的信息,其中有一个重要的属性是Control,另一个重要的属性是DockRect,就是停靠的位置;

  MousePos是:鼠标的位置。

 

2>、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;

        从Delphi的DockDrop函数定义可以看出,TWinControl是先发送DOCKCLIENT消息,再触发OnDockDrop事件的。

 

2、用ManualDock函数可以安全的完成停靠功能,不要用Dock函数。

function ManualDock(NewDockSite: TWinControl; DropControl: TControl = nil; ControlSide: TAlign = alNone): Boolean;

参数说明:

  NewDockSite:要被停靠的窗体;

  DropControl:已经存在于NewDockSite的TControl,在这里可以把它设成nil;

  ControlSide: 停靠的位置,可以是上,下,左,右,全部等。

相应的还有一个:ManualFloat和UnDock函数

 

二、窗体之间相互停靠的实例

1.基本步骤:

1>、先创建一个新窗体:

        设置属性Name:DockableForm;DockSite:True ;DragKind:dkDock;DragMode:dmAutomatic(自动停靠,表示当鼠标在工具条上点击并移动后,会自动发起拖放动作)。

DockSite必须设置为True,不然不会触发DOCKCLIENT消息处理函数,也就不能停靠了。

DragMode必须设置为dmAutomatic:不然停靠如宿主窗体之后,就不能再拖出来。

 

2>、再创建一个宿主窗体:

        设置属性Name:TiledHost;DockSite:True;UseDockManager:True,表示窗体自动管理停靠。它的作用是用来装载两个DockableForm的。

注意:使用窗体作为停靠锚点时不会出现拖放把手和关闭按钮,而且停靠多个组件时,也不会自动排列,而是随意排列。所以,必须设置UseDockManager为True,使用一个停靠管理器来管理停靠的动作。

 

3>、在DockableForm中捕获DOCKCLIENT消息,在里面完成两个窗体的相互停靠

在private中声明消息处理函数及它的实现代码:

procedure CMDockClient(var Message: TCMDockClient); message CM_DOCKCLIENT;
end;

procedure TDockableForm.CMDockClient(var Message: TCMDockClient);
var
 Host: TForm;
begin
 if Message.DockSource.Control is TDockableForm then
 begin
    Host := TTiledHost.Create(Application);// 创建一个窗体实例
  Host.BoundsRect := Self.BoundsRect;// 获取组件所有角的像素位置,设置宿主窗体大小
  // 完成窗体的相互停靠

  Self.ManualDock(Host, nil, alNone); // 把自己停靠到TTiledHost
  Self.DockSite := False;// 不允许其他控件停靠在自己上面
    // 把Message.DockSource.Control也停靠到TTiledHost,完成窗体的相互停靠

Message.DockSource.Control.ManualDock(Host, nil, alNone);
  TDockableForm(Message.DockSource.Control).DockSite := False;
  

Host.Visible := True;//必须添加,不然窗体全部消失不见

 end;
end;

        先解释一下上面的代码,首先创建TTiledHost的实例,然后用ManualDock函数把自己停靠到TTiledHost,把Message.DockSource.Control也停靠到TTiledHost,这样就完成了窗体的相互停靠,

 

4>、就在DockableForm的OnDockOver事件里加入代码,使程序产生停靠的预览效果。

procedure TDockableForm.FormDockOver(Sender: TObject;
 Source: TDragDockObject; X, Y: Integer; State: TDragState;
 var Accept: Boolean);
var
 ARect: TRect;
begin
 Accept := Source.Control is TDockableForm;
 if Accept then
 begin
  ARect.TopLeft := ClientToScreen(Point(0, 0));
  ARect.BottomRight := ClientToScreen(
   Point(ClientWidth div 2, ClientHeight));
  Source.DockRect := ARect;
 end;
end;

  

5>、在DockableForm中添加一个按钮创建新的DockableForm。

Var i: integer;

procedure TDockableForm.btn1Click(Sender: TObject);

var

  AForm: TDockableForm;

begin

  AForm := TDockableForm.Create(Application);

  AForm.Caption := 'AForm' + IntToStr(i);

  Inc(i);

  AForm.Show;

end;

 

6>、运行程序

        点击按钮生成新的DockableForm时,把其中一个拖动到另一个上,就可以实现两个窗体之间的相互停靠,并一起在HostHost中显示。

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个免费程序(目前还是测试版),作者不但提供控件, 而且还无偿提供控件的所有源代码,您可以在个人或者商业程序中免费使用DockPresident 地址: http://www.pigtwo.com/CtrlData/WebSite/luxiaoban.htm 如果您下载并且使用了DockPresident,请留下您的感受和意见,也算是对作者所做工作的肯定。 下面是她的readme文件中的内容: 作为Delphi的忠实用户,我想大家对Delphi中的停靠窗体应该比较熟悉吧,是不是也希望自己编的程序也具有这样的功能? 使她看起来更漂亮,更专业,更方便。本人做的一套停靠控件DockPresident正好能满足您的要求,DockPresident包含五个控件, 她们分别是TlbDockServer, TlbDockClient, TlbDelphiDockStyle, TlbVCDockStyle, TlbVIDDockStyle。 只要在主窗口上放上TDockServer控件,在一般窗口上放上TlbDockClient控件,这两个窗体就有了停靠功能。不用编写一行代码, 效果和Delphi的IDE一样,并且比她功能更强。并且两个都放了TlbDockClient控件的窗体还可以相互停靠, 分别停靠成平铺型和分页型的窗体。用户还可以改变停靠的风格, TlbDockServer和TlbDockClient都有一个属性叫做DockStyle, 只要把TlbDelphiDockStyle, TlbVCDockStyle或者TlbVIDDockStyle控件赋值给DockStyle属性, 用户您就拥有了Delphi, Visual C++或者Visual InterDev的停靠风格。 这套控件还有很多属性供用户设置,来改变她们的停靠特性。 在当前文件夹中又有一些子文件夹,分别是: Source: 控件的源代码. SupportClass: 一个第三方控件wmEdit的DCU文件,用于Demo程序中. Help: 帮助文件,请读者务必仔细阅读,里面有控件的详细说明. Document: 文档资料,如果读者想对DockPresident有更深入的了解, 阅读里面的文章. Demo: 例子程序,用来演示DockPresident控件的使用方法和效果,里面有两个程序AdviceDemo和VCDemo. AdviceDemo程序演示了所有的DockPresident控件的用法, VCDemo主要用来演示TlbVCDockStyle的用法.由于wmEdit的原因,在VCDemo程序中有两个工程文件, 分别是VCDemoPro_D5和VCDemoPro_D6,如果用户使用的是Delphi5.0,请使用VCDemoPro_D5工程, 反之就使用VCDemoPro_D6. Bin 用来存储Source文件夹中对应文件的DCU,编译后会产生,用户可以把它删除掉. 控件安装: 如果用户使用的是Delphi5.0,请打开DockControl_D5.dpk文件安装,如果用户使用的是Delphi6.0, 请打开DockControl_D6.dpk文件安装.控件安装完成后,用户还需要配置一下Delphi, 好让Delphi能找到源文件的路经, 设置方法: 点击Tools菜单的Environment Options,弹出Environment Options对话框, 点击Library页,然后点击Library path右边的按钮, 在弹出的Directories对话框中添加上控件源文件所在的文件夹,比如:D:DockFormControlSource. 如果用户没有配置Delphi,Demo文件夹中的程序也是可以使用的,因为作者已经帮用户设置好了, 但是如果用户要自己做一个全新的程序,请按照前面的方法配置您的Delphi.
Delphi 中,可以使用以下步骤将子窗体的值传递给父窗体: 1. 在子窗体中定义一个公共的属性,用于保存要传递的值。 2. 在子窗体中创建一个公共的方法,用于将需要传递的值设置到属性中。 3. 在父窗体中创建一个公共的方法,用于接收子窗体传递的值。 4. 在父窗体中创建子窗体的实例,并调用子窗体的设置值方法。 5. 在子窗体关闭时,调用父窗体的接收值方法,以便在父窗体中更新相应的控件。 以下是示例代码: 在子窗体中定义公共属性和方法: ```delphi type TChildForm = class(TForm) private FValue: Integer; public procedure SetValue(AValue: Integer); end; implementation procedure TChildForm.SetValue(AValue: Integer); begin FValue := AValue; end; ``` 在父窗体中定义公共方法: ```delphi type TMainForm = class(TForm) public procedure UpdateValue(AValue: Integer); end; implementation procedure TMainForm.UpdateValue(AValue: Integer); begin // 在这里更新父窗体中需要显示子窗体值的控件 end; ``` 在父窗体创建子窗体实例并调用设置值方法: ```delphi var ChildForm: TChildForm; begin ChildForm := TChildForm.Create(Self); ChildForm.SetValue(123); ChildForm.Show; end; ``` 在子窗体关闭时,调用父窗体的接收值方法: ```delphi procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction); begin if Assigned(Owner) and (Owner is TMainForm) then TMainForm(Owner).UpdateValue(FValue); end; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值