源地址:http://edn.embarcadero.com/article/33446

摘要: Instructions on how to use the TDockTabSet component to make advanced docking user interfaces.

Introduction

This article discusses the use of the TDockTabSet component that was originally introduced in Delphi 2005.

Creating the applications main form

Create a File | New | VCL Forms Application - Delphi for Win32.

Setting up the main form
Locate the TDockTabSet component  on the additional page in the Tool Palette and drop it onto the main form.

  1. Set the following properties:
Align alLeft
DockSite False
ShrinkToFit True
Style tsModernTabs
TabPosition tpLeft
Width 25

You may want to use the tsModernPopup tab style instead of the tsModernTabs. The download that accompanies this article does.

To keep the TDockTabSet component company on the form, drop the following components and modify the properties as indicated.

  1. TPanel
Align alTop
BevelKind bkTile
BevelOuter bvNone
Caption
  1. TPanel
Align alLeft
BevelOuter bvNone
DockSite True
Name pDockLeft
Width 0
  1. TSplitter
Align alLeft
  1. TMemo
Align Client
  1. Drop a TButton on the top aligned Panel and set its caption to Show Form
  2. Set the Forms caption to TDockTabSetDemo Application
  3. Name the form frmMain and save the unit as MainForm

If you name your components differently remember to reference the correct name when adding the source code.

The main form of your application should look something like the following.

The setting of the all important property

There is one more property that needs to be set on the TDockTabSet before we can continue. Set the DestinationDockSite to be the left aligned panel. Called pDockLeft in this article.

Now it's time to create another form for the application. There are now 3 ways this can be done in Delphi 2006 and I'll mention all of them:

  1. Select the File | New | Form for Win32 or
  2. Click on the Project Manager
    1. In the Tool Palette you will see the object repository items get added.
    2. Locate the Delphi Projects | Delphi Files category.
    3. Double click on the Form icon to create a New Form.
  3. Right click on the project manager and select the Add New menu item. From the sub menu select Form.

I prefer the 3rd method, which is new to Delphi 2006 and I've discussed previously on my blog.
Name the new form frmDock and save the unit as DockForm.
In the code editor for this unit do the following.

  1. Delete the global frmDock: TfrmDock variable from the forms implementation section, it isn't required
  2. Make sure the form isn't in the list of forms that are created automatically (I always turn this option off by default). To do this select the Project | Options menu item and move frmDock to the Available Forms list for the Forms option page.
  3. Add an OnClose event that contains the following code
1
2
3
4
5
6
7
8
9
procedure TfrmDock.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ManualFloat(Rect(0, 0, 0, 0));
  Action := caFree;
end;

4.Add an OnStartDock event that contains the following code

1
procedure TfrmDock.FormStartDock(Sender: TObject; var DragObject:<br data-filtered="filtered"><br data-filtered="filtered">  TDragDockObject);<br data-filtered="filtered"><br data-filtered="filtered">begin<br data-filtered="filtered"><br data-filtered="filtered">  DragObject := TDragDockObjectEx.Create(Self);<br data-filtered="filtered"><br data-filtered="filtered">  DragObject.Brush.Color := clAqua; // this will display a red outline<br data-filtered="filtered"><br data-filtered="filtered">end;<br data-filtered="filtered">

5.Create a new class function called CreateDockForm that accepts a TColor, returns a TCustomForm and contains the following code.

1
class function TfrmDock.CreateDockForm(const aColor: TColor): TCustomForm;<br data-filtered="filtered"><br data-filtered="filtered">begin<br data-filtered="filtered"><br data-filtered="filtered">  result := TfrmDock.Create(Application);<br data-filtered="filtered"><br data-filtered="filtered">  result.Color := aColor;<br data-filtered="filtered"><br data-filtered="filtered">  result.Caption := ColorToString(aColor);<br data-filtered="filtered"><br data-filtered="filtered">  result.Show;<br data-filtered="filtered"><br data-filtered="filtered">end;<br data-filtered="filtered">

6.Finally modify the following properties on the dock form

BorderStyle bsSizeToolWin
DragKind dkDock
DragMode dmAutomatic

You may also want to modify the size of the frmDock form to not be so wide.
That is the form that will be docked completed. Time to write some in the main unit!

Switch to the MainForm unit now and make the following changes.

1.Invoke the Use Unit dialog (Alt+F11 or File | Use Unit) and select the DockForm unit.
2.Create an OnClick event for the TButton with the following code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
procedure TfrmMain.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  // close all previously dockable forms before recreating
  for i := 0 to Screen.FormCount - 1 do
    if Screen.Forms[i] is TfrmDock then
      Screen.Forms[i].Close;
  // dock to the component called pDockLeft
  TfrmDock.CreateDockForm(clBlue).ManualDock(pDockLeft);
  // dock to the top on the pDockLeft panel
  TfrmDock.CreateDockForm(clGreen).ManualDock(pDockLeft, nil, alTop);
  // dock to the right on the pDockLeft panel
  TfrmDock.CreateDockForm(clRed).ManualDock(pDockLeft, nil, alRight);
  // dock directly to the DockTabSet
  TfrmDock.CreateDockForm(clWhite).ManualDock(DockTabSet1);
end;

The remaining code is required to get the docking behavior to play nice amongst each other.

1.Create an OnDockDrop event for the pDockLeft panel and add the following code
This OnDockDrop event makes sure that the width of the pDockLeft panel is sufficient for when the frmDock form is dropped on it. If the panel previously had a width of 0 (which means you can't see it) then set the width to 150. This value is hardcoded for the demo but I could have easily read the current width of the control being dropped and using that value. You can get the width of the control being dropped from the TDragDockObject passed in as the Source parameter. You would use the following to get the width of the control that is being dropped:

1
pDockLeft.Width := Source.Control.Width;

The OnDockDrop code also makes sure that the splitter is visible when a form is being docked and that it is in the correct position.

1
2
3
4
5
6
7
procedure TfrmMain.pDockLeftDockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);
begin
  if pDockLeft.Width = 0 then
    pDockLeft.Width := 150;
  Splitter1.Visible := True;
  Splitter1.Left := pDockLeft.Width;
end;

2.Create an OnUndock event for the pDockLeft panel and add the following code
If the form being undocked is the last one on it then we need to set the Panels width back to 0 and hide the Splitter.

1
2
3
4
5
6
7
8
procedure TfrmMain.pDockLeftUnDock(Sender: TObject; Client: TControl; NewTarget: TWinControl; var Allow: Boolean);
begin
  if pDockLeft.DockClientCount = 1 then
  begin
    pDockLeft.Width := 0;
    Splitter1.Visible := False;
  end;
end;

3.Create an OnDockOver event for the pDockLeft panel and add the code below.
The DockOver event is the event responsible for drawing the forms outline at the dock site.

1
2
3
4
5
6
7
8
9
10
11
12
13
procedure TfrmMain.pDockLeftDockOver(Sender: TObject; Source: TDragDockObject; X, Y: Integer; State: TDragState;
  var Accept: Boolean);
var
  lRect: TRect;
begin
  Accept := Source.Control is TfrmDock;
  if Accept then
  begin
    lRect.TopLeft := pDockLeft.ClientToScreen(Point(0, 0));
    lRect.BottomRight := pDockLeft.ClientToScreen(Point(150, pDockLeft.Height));
    Source.DockRect := lRect;
  end;
end;

4.Create an OnDockDrop event for the DockTabSet1 component and add the code below.
If a control is being docked to the DockTabSet component we want to make sure it is visible.

1
procedure TfrmMain.DockTabSet1DockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);<br data-filtered="filtered">begin<br data-filtered="filtered">  DockTabSet1.Visible := True;<br data-filtered="filtered">end;<br data-filtered="filtered">

5.Create an OnTabRemoved event for the DockTabSet1 component and add the following below.
The DockTabSet1 component should only be visible if there is a control docked to it.

1
2
3
4
procedure TfrmMain.DockTabSet1TabRemoved(Sender: TObject);
begin
  DockTabSet1.Visible := DockTabSet1.Tabs.Count > 0;
end;

How the created forms should look in the Structure View window

More action shots

Application appearance on startup

Tab selected. Note you can click on the pin button to pin the green form to the docksite or click on the cross to close the form. To not do anything, click in the memo to change the focus away from the green form to hide it.


Dragging an undocked form, note the red drag outline

Hide image

All windows unpinned

What about VCL.NET support?

Unfortunately there is a bug in the VCL.NET implementation of the TDockTabSet component. It is currently logged in QualityCentral and hopefully it will be addressed in the next major Delphi release.

Report No: 24640 ( RAID: 238759 ) Status: Open
TDockTabSet control doesn't work correctly in VCL.NET
http://qc.borland.com/wc/qcmain.aspx?d=24640

The bug cannot be fixed in an update as it requires an interface change to the TDockTabSet class. If you wish to fix the bug yourself you can use the following workaround:

Move the DoAddDockClient method from strict private to protected and override it.

previously...

  TDockTabSet = class(TTabSet)
strict private
procedure DoAddDockClient(Client: TControl; const ARect: TRect);

should become...

  TDockTabSet = class(TTabSet)
protected
procedure DoAddDockClient(Client: TControl; const ARect: TRect); override;

You also have to take the necessary steps to ensure that the modified unit is compiled into your assembly as well.

An alternate approach might be:

  1. Create a new Delphi.NET package
  2. Save the package and name it FixedDockTabSetNET100
  3. Open the Borland.VCL.TDockTabSet unit from the sourceDotNetVCL folder
  4. Select File | Save As... and save a copy of the unit in the folder where you saved the package and rename the package to FixedDockTabSet
  5. In the FixedDockTabSet unit right click on the TDockTabSet class name and select Rename refactoring. Rename the class to TFixedDockTabSet
  6. Create a global function called Register and implement it as follows:
procedure Register;
begin
RegisterComponents('Fixed DockTabSet', [TFixedDockTabSet]);
end;

Build the new package Install the package using the Installed .NET Components menu item from the components menu, making sure to add it to the VCL.NET components tab. If all worked well when you create a new VCL.NET Application you will get a Fixed DockTabSet palette page that has the new TDockTabSet control on it.

Closing comments

With the help of the TDockTabSet component you can now create more advanced user interfaces with dockable windows which is sure to annoy most users. With a lot more hair pulling and sleepless nights, you can use the code in this article as a basis to create your our docking framework. I've done this as part for my QualityCentral windows client I created.
I encourage you to download and try it out from my website www.jed-software.com.

Hide image

Hide image

While doing so, don't forget to add any issues or enhancements to QualityCentral.
Source Download

You can download the source to this article from Code Central:
  Download Source Code

本文转自 不得闲 博客园博客,原文链接:http://www.cnblogs.com/DxSoft/archive/2010/12/15/1906408.html   ,如需转载请自行联系原作者

使用Delphi自带的TDockTabSet组件实现停靠功能(Jeremy North)相关推荐

  1. Delphi 7自带的TeeChart组件

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Delp ...

  2. DELPHI第三方控件及组件大全(安装方法与使用)

    一,DELPHI第三方控件安装方法介绍 1.对于单个控件,Componet–>install component..–>PAS或DCU文件–>install; 2.对于带*.dpk文 ...

  3. IntraWEB Ultimate 15.2.20是Delphi自带的一套Web开发框架

    IntraWEB Ultimate 15.2.20是Delphi自带的一套Web开发框架 IntraWeb是Delphi自带的一套Web开发框架,使用IntraWeb能够让开发人员比以往更快,更容易地 ...

  4. Delphi 自带的 Base64 编解码函数

    今天帮别人解决一个关于 Base64 编解码的问题,竟然发现 Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因. 这个 ...

  5. Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件

    转载请注明出处:http://blog.csdn.net/xiaanming/article/details/11821523 貌似有些天没有写博客了,前段时间在忙找工作的事,面试了几家公司,表示反响 ...

  6. Delphi创建COM组件并分别用Delphi和html调用该组件的简单实例

    一.功能介绍及效果图 用delphi xe6 创建一个简单的COM组件,并分别测试了用delphi和HTML调用该组件的方法ShowWuXiaNames.效果图如下: 图一:在Windows中注册的C ...

  7. Ajax 发送json格式数据以及发送文件(FormData)和自带的序列化组件: serializers

    前后端传输数据的编码格式(contentType) get请求数据就是直接放在url?后面的 url?usernmae=junjie&password=123... 可以向后端发送post请求 ...

  8. 计算机附带的游戏怎么删除,如何清除Win7系统附件中自带的游戏组件

    系统城的小编这里要为大家带来的是关于如何清除Win7系统附件中自带的游戏组件的方法,大家知道,我们的系统的开始菜单中有一个附件,这里的游戏是系统自带的,很多人几乎从来都不会去玩它,那么我们就可以将他们 ...

  9. Delphi学习笔记:常用组件

    一.事件 OnCanResize:当组件试图改变大小时触发(当组件有所改变时触发的事件) onClick:(鼠标单击事件)当在此组件上按下鼠标左键时触发的事件 OnConstrainedResize: ...

最新文章

  1. 在巨头壁垒下,人工智能细分领域涌现领跑者,这是AI真正的新机遇
  2. 【checkStyle】ignore some class
  3. 二、lvm条带化的概念
  4. c#操作Xml(八)
  5. 现代 ABAP 编程语言中的正则表达式
  6. gpgga格式读取MATLAB,GPS编码格式及读取.doc
  7. 隐秘的角落里数亿场AI战争正在发生
  8. origin 设置数据显示位数
  9. 出国怎么能不出现天价微博?
  10. Win-MASM64汇编语言-NEG指令
  11. 南开大学开源新图像分割算法,刷新精度记录 | 资源
  12. 翻译 Real-Time Global Localization of Robotic Cars in Lane Level via Lane Marking Detection and Shape
  13. Java反射----获取Class类实例的4种方式
  14. 换个角度深入理解GlusterFS
  15. PHP CURL 使用代理 获取国外资源
  16. freeswitch 模块
  17. 广东第一高中生_广东高中排行榜TOP10,有你的母校吗?
  18. Linux7密钥,centos7秘钥验证
  19. numpy(逻辑函数与数学函数)
  20. 吉隆坡Mac高清动态壁纸

热门文章

  1. linux-``反引号
  2. 学习 .net 的一些主要网站
  3. linux下svn重新定位的方法
  4. 生成各种统计图的C#方法
  5. Spring 2.5 基于注解驱动的 Spring MVC
  6. 已放弃 (核心已转储)_辽宁已放弃师弟!CBA公布外援优先续约名单:北京队不在列...
  7. POJ2536 二分图匹配
  8. 【IOC 控制反转】IOC 简介 ( 依赖注入的两种实现方式 | 编译期注入 | 运行期注入 )
  9. 【Android 性能优化】布局渲染优化 ( 过渡绘制 | 自定义控件过渡绘制 | 布局文件层次深 | GPU 过渡绘制调试工具 | 背景过度绘制 )
  10. 【Netty】NIO 网络通信 SelectionKey 常用 API 简介