TSpTbxDock vs TSpTbxMultiDock

时间:2013-06-19 16:59:55

标签: delphi delphi-7 sptbxlib

在我当前的项目中,我有TTbxDock个工具栏和面板(TTbxDockablePanel)。在移动TBX - > SpTBX后,我无法在TSpTbxDockablePanel上放置一个面板(TSpTbxDock)。我看到一条运行时错误消息,说我无法将面板放在底座上。

Error, 'Cannot insert TSpTBXDockablePanel into TSpTBXDock.'

  • 我是否需要使用TSpTbxMultiDock代替面板?为什么?
  • 我可以将工具栏放在TSpTbxMultiDock而不是TSpTBXDock上吗?

即。为什么写这样的代码:

procedure TSpTBXCustomMultiDock.ValidateInsert(AComponent: TComponent);
begin
  inherited;
  if not (AComponent is TSpTBXCustomDockablePanel) then
    raise EInvalidOperation.CreateFmt('Cannot insert %s into MultiDock', [AComponent.ClassName]);
end;

procedure TSpTBXCustomDockablePanel.ValidateContainer(AComponent: TComponent);
begin
  inherited;
  if (AComponent is TTBDock) and not (AComponent is TSpTBXCustomMultiDock) then
    raise EInvalidOperation.CreateFmt('Cannot insert %s into %s. Place it on a MultiDock instead', [Self.ClassName, AComponent.ClassName]);
end;

为什么我不能只使用一种码头?

1 个答案:

答案 0 :(得分:9)

"我需要使用TSpTbxMultiDock代替面板?为什么"?

简短的回答是,因为编写TSpTBXMultiDock组件只处理和停靠TSpTBXDockablePanel

答案很长,TSpTBXMultiDock组件是为了处理和停靠TSpTBXDockablePanel s 而编写的,因为停靠代码依赖于控件中的特定方法/属性对接。请参阅TSpTBXCustomDockablePanel.SetParent,它会查看此内容:它会访问属性和方法TSpTBXCustomMultiDock.

  • UpdateDockablePanelsDockPos
  • ClientAreaWidth
  • ClientAreaHeight

换句话说,停靠和布局代码需要知道某些信息并要求停靠控件执行某些操作。最简单的方法是约束它可以停靠的特定类的后代控件的类型,它声明并实现所需的接口(松散地使用接口,没有声明(class)interface,它&# 39; s只是一组非正式的方法/属性。)

从快速扫描代码开始,我认为只有第一个代码UpdateDockablePanelsDockPos才真正必不可少。我可能错过了一些东西。但是这种方法获得了所有停靠面板的列表并更新了每个人DockPos,这是面板中停靠点的一维位置。也就是说,对于水平面板,它是左/水平开始,而对于垂直面板,它是顶/垂直开始。它还会更新总数,以便小组知道它有多大,或者可以选择。

我不太确定我已经回答了你的问题。我觉得我已经给出了一个正确的答案,但没有给出有用的答案(以上是技术原因,而不是概念上的原因),这需要深入了解你所做的事情。做的。我的猜测是你问这个因为你正在与TBX挣扎 - > SpTBX迁移,您需要可以处理工具栏和可停靠面板的停靠区域。幸运的是,这两个问题导致了你的第二个问题...

"我可以在TSpTbxMultiDock上放置工具栏吗?"

我在这里踩到了记忆中的领域而且我无法保证这部分答案是正确的,因为我将我们的应用程序从TBX转换为SpTBX很长很长很久以前。

首先,不,你不能在可停靠的面板上放置TSpTBXToolbar。你也不能在TSpTBXDockablePanel上停靠TSpTBXDock。工具栏可以停靠在扩展坞中,可停靠的面板可以停靠在多堆中。

这样做的原因是猜测,但我猜它是因为两个停靠控件的不同行为及其目的。

<强>工具栏:

  • 旨在包含SpTBX项目(按钮,下拉列表等,而不是任何正常的VCL控件,按钮等),并且可以从工具栏动态更改为菜单等,例如,在调整表单大小时并且工具栏缩小。
  • 堆叠:以及它们之间有任何空间(不像对接的面板,它们总是彼此相邻)工具栏之间可以有空间;他们坐在用户放置的地方。它们通常也会分成几排,一个扩展坞包含多行。
  • 旨在缩小:表单可能会变得太小,或者用户可以将工具栏拖到另一个工具栏上,工具栏只显示它可以显示的项目,并隐藏其他项目或显示chevron(一个小的&gt;&gt;按钮,用于打开包含其他项目的菜单。)

可停靠的面板:

  • 旨在容纳复杂的控件,包括标准的VCL控件 - 它们意味着作为工具栏和对接系统兼容的方式来构建复杂的停靠窗体。 (我们将我们设计为框架和客户端 - 将框架对齐到可停靠面板。)
  • 很少有几行。这取决于您作为UI实施者,但许多彼此相邻的面板可能会迅速填满表单空间。我们为可停靠面板保持LimitToOneRow打开,因此它们只能填充一个维度(即,在表单的左侧和右侧,可停靠的面板只能位于彼此的上方和下方,而不是每个的左侧和右侧其他。)
  • 调整行为的方式不同:它们始终相邻,两者之间没有间隙(工具栏可以放置在任何位置),并且通常会拉伸一个或多个面板以填充扩展坞的整个大小(工具栏)除非设置了MenuBar(见下文),否则工具栏的设计是缩小,而不是增长,并显示一个V形和一个下拉菜单。小组没有这种行为。

在转移之后,回到你的问题。当我们转换我们的应用程序时,我记得想知道如果用户想要创建一个布局,以便有工具栏,然后是可停靠的面板,然后再使用工具栏,将会发生什么,以便尽可能接近混合这两种类型。这样做需要一个dock,然后是一个multidock,然后再一个dock,但实际上这实际上会导致用户能够创建相当复杂的和令人困惑的布局。可停靠UI的一个问题是许多用户发现它们令人困惑(老实说,您会感到惊讶),并且可能会意外移动或停靠他们不想要的项目。 (例如,将菜单栏限制在顶部是一种很好的做法 - 不要让它被移动。这只是令人困惑。)

我们目前的设计是我们主窗口的每一面都有两个底座:一个是普通底座,然后是旁边那个(靠近表格中心)一个多边形。由此产生的行为是,所有工具栏(例如菜单和普通工具栏)只能停靠在窗口边缘旁边。然后,可停靠面板更靠近窗体内部。在每个表单边缘上保持成对的停靠点和多个堆栈可以使两种类型的控件停靠在表单的任何一侧,但是约束工具栏始终位于表单的最边缘。这实际上是UI的意义:可停靠的面板往往包含比工具栏更复杂的内容,因此它们是更多的中央控件。当然,如果表单的一个特定边缘上只有一个可停靠的面板,而不是可停靠的工具栏,那么工具栏底座是不可见的(宽度或高度为0),因此面板也位于窗口边缘旁边。

My recommended SpTBX dock layout

写成文字,很难解释前两段(这个方案如何运作,以及为什么这样好/好。)你需要在实践中尝试并且对用户有意义。的行为。但基本上,我建议您在表单上使用两种类型的停靠点,并使TSpTBXMultiDock对齐&#39;在内部&#39;或者&#39;内部到&#39;正常的工具栏停靠。希望这个图像有所帮助。

其他

您可能对以下属性感兴趣:

  • DockableTo(工具栏和可停靠面板):约束工具栏或面板可以停靠的哪一侧(顶部,底部,左侧,右侧)。使用它可以使某些控件只能停靠在某些特定的停靠点中 - 例如,主菜单只停靠在顶部。
  • DefaultDock(同样,两者):当用户双击停靠,而不是拖动停靠时,它会去哪里?
  • CurrentDock:我认为您已经发现了这一点,但是在设计器中将其设置为在停靠点之间移动工具栏或面板,并在运行时读取(或者,我想,如果您在运行时设置以编程方式想要将东西移动到特定的码头。)
  • DockMode:控制工具栏或面板是否可以浮动(取消停靠并成为自己的窗口),包括它是否可以更改停靠点。使用它的一个例子是主菜单约束。
  • FixedDockSize(仅限面板):可以通过用户或上面提到的停靠代码停止面板的大小调整。
  • MenuBar(仅限工具栏):给工具栏稍微不同的行为,我认为它总是占据了底座的整个宽度,并且不允许其他工具栏停靠在它旁边。它也可能会改变项目的呈现方式。