2

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

错误,“无法将 TSpTBXDockablePanel 插入 TSpTBXDock。”

  • 我需要使用 aTSpTbxMultiDock代替面板吗?为什么?
  • 我可以将工具栏放在 aTSpTbxMultiDock而不是 a上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;

为什么我不能只使用一种类型的底座?

4

1 回答 1

9

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

简短的回答是,因为TSpTBXMultiDock组件被编写为仅处理和停靠TSpTBXDockablePanels。

长答案是TSpTBXMultiDock组件被编写为仅处理和停靠TSpTBXDockablePanels因为停靠代码依赖于它停靠的控件中的特定方法/属性。看TSpTBXCustomDockablePanel.SetParent,它会照顾这个:它访问属性和方法TSpTBXCustomMultiDock.

  • UpdateDockablePanelsDockPos
  • ClientAreaWidth
  • ClientAreaHeight

换句话说,停靠和布局代码需要知道某些信息并要求停靠的控件做某些事情。最简单的方法是限制控件的类型,它可以停靠到声明和实现所需接口的特定类的后代(松散地使用接口,没有(类)interface声明,它只是一组非正式的方法/ 特性。)

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

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

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

我在这里进入了记忆领域,我不能保证这部分答案是正确的,因为很久很久以前我将我们的应用程序从 TBX 转换为 SpTBX。

首先,不,您不能将 aTSpTBXToolbar放在可停靠面板上。您也不能将 a 停靠TSpTBXDockablePanelTSpTBXDock. 工具栏可以停靠到停靠栏,可停靠面板可以停靠到多停靠栏。

原因是猜测,但我猜这是因为两个停靠控件的不同行为及其用途。

工具栏:

  • 旨在包含 SpTBX 项目(按钮、下拉菜单等,而不是任何普通的 VCL 控件、按钮等),并且可以动态地从工具栏更改为菜单等,例如,当窗体调整大小和工具栏缩小时。
  • 堆栈:以及它们之间有任意数量的空间(与停靠面板不同,它们总是彼此相邻)工具栏之间可以有空间;它们坐在用户放置的任何位置。他们也经常坐成几排,一个码头扩展并包含几排。
  • 旨在缩小:一个表单可能会变得太小,或者用户可以将工具栏拖到另一个上,工具栏将只显示它可以显示的项目,并隐藏其他项目或显示 V 形(一个微小的 >> 按钮来打开一个包含其他项目的菜单。)

可停靠面板:

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

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

我们当前的设计是主窗口的每一侧都有两个停靠栏:一个普通停靠栏,然后旁边(靠近窗体中心)一个多停靠栏。产生的行为是所有工具栏,例如菜单和普通工具栏,只能停靠在窗口边缘旁边。然后,可停靠面板更靠近表单的内部。在每个窗体边缘上保持成对的停靠和多停靠彼此相邻可以让这两种类型的控件停靠在窗体的任何一侧,但将工具栏限制为始终位于窗体的最边缘。实际上,这使得 UI 有意义:可停靠面板往往在其中包含比工具栏更复杂的东西,因此它们是更集中的控件。当然,如果表单的一个特定边缘上只有一个可停靠面板,而不是可停靠工具栏,

我推荐的 SpTBX 坞站布局

写成文字,很难解释前两段(这个方案是如何工作的,以及为什么这样可以/好。)您需要在实践中尝试并了解用户的行为。但基本上,我建议在您的表单上使用这两种类型的停靠栏,并保持TSpTBXMultiDocks 对齐“内部”或“内部”正常工具栏停靠。希望这张图片有帮助。

其他

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

  • DockableTo(工具栏和可停靠面板):限制工具栏或面板可以停靠的边(上、下、左、右)。使用它可以使某些控件只能停靠在某些特定的停靠栏中 - 例如,主菜单只能停靠在顶部。
  • DefaultDock(同样,两者):当用户双击停靠而不是拖动停靠时,它会去哪里?
  • CurrentDock:我认为您已经找到了这个,但是在设计器中将其设置为在扩展坞之间移动工具栏或面板,并在运行时读取(或者,如果您想以编程方式将东西移动到特定的扩展坞,我想在运行时设置。)
  • DockMode:控制工具栏或面板是否可以浮动(取消停靠并成为自己的窗口),包括是否可以更改停靠。使用它的一个例子是主菜单约束。
  • FixedDockSize(仅限面板):停止面板调整大小,无论是由用户还是由上面提到的对接代码。
  • MenuBar(仅限工具栏):使工具栏的行为略有不同,我认为它总是占据整个停靠栏的宽度,并且不允许其他工具栏停靠在它旁边。它还可能会稍微改变项目的渲染方式。
于 2013-06-19T21:11:32.803 回答