在我当前的项目中,我有TTbxDock
个工具栏和面板(TTbxDockablePanel
)。在移动TBX - > SpTBX后,我无法在TSpTbxDockablePanel
上放置一个面板(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;
为什么我不能只使用一种码头?
答案 0 :(得分:9)
简短的回答是,因为编写TSpTBXMultiDock
组件只处理和停靠TSpTBXDockablePanel
。
答案很长,TSpTBXMultiDock
组件是为了处理和停靠TSpTBXDockablePanel
s 而编写的,因为停靠代码依赖于控件中的特定方法/属性对接。请参阅TSpTBXCustomDockablePanel.SetParent
,它会查看此内容:它会访问属性和方法TSpTBXCustomMultiDock.
UpdateDockablePanelsDockPos
ClientAreaWidth
ClientAreaHeight
换句话说,停靠和布局代码需要知道某些信息并要求停靠控件执行某些操作。最简单的方法是约束它可以停靠的特定类的后代控件的类型,它声明并实现所需的接口(松散地使用接口,没有声明(class)interface
,它&# 39; s只是一组非正式的方法/属性。)
从快速扫描代码开始,我认为只有第一个代码UpdateDockablePanelsDockPos
才真正必不可少。我可能错过了一些东西。但是这种方法获得了所有停靠面板的列表并更新了每个人DockPos
,这是面板中停靠点的一维位置。也就是说,对于水平面板,它是左/水平开始,而对于垂直面板,它是顶/垂直开始。它还会更新总数,以便小组知道它有多大,或者可以选择。
我不太确定我已经回答了你的问题。我觉得我已经给出了一个正确的答案,但没有给出有用的答案(以上是技术原因,而不是概念上的原因),这需要深入了解你所做的事情。做的。我的猜测是你问这个因为你正在与TBX挣扎 - > SpTBX迁移,您需要可以处理工具栏和可停靠面板的停靠区域。幸运的是,这两个问题导致了你的第二个问题...
我在这里踩到了记忆中的领域而且我无法保证这部分答案是正确的,因为我将我们的应用程序从TBX转换为SpTBX很长很长很久以前。
首先,不,你不能在可停靠的面板上放置TSpTBXToolbar
。你也不能在TSpTBXDockablePanel
上停靠TSpTBXDock
。工具栏可以停靠在扩展坞中,可停靠的面板可以停靠在多堆中。
这样做的原因是猜测,但我猜它是因为两个停靠控件的不同行为及其目的。
<强>工具栏:强>
可停靠的面板:
MenuBar
(见下文),否则工具栏的设计是缩小,而不是增长,并显示一个V形和一个下拉菜单。小组没有这种行为。在转移之后,回到你的问题。当我们转换我们的应用程序时,我记得想知道如果用户想要创建一个布局,以便有工具栏,然后是可停靠的面板,然后再使用工具栏,将会发生什么,以便尽可能接近混合这两种类型。这样做需要一个dock,然后是一个multidock,然后再一个dock,但实际上这实际上会导致用户能够创建相当复杂的和令人困惑的布局。可停靠UI的一个问题是许多用户发现它们令人困惑(老实说,您会感到惊讶),并且可能会意外移动或停靠他们不想要的项目。 (例如,将菜单栏限制在顶部是一种很好的做法 - 不要让它被移动。这只是令人困惑。)
我们目前的设计是我们主窗口的每一面都有两个底座:一个是普通底座,然后是旁边那个(靠近表格中心)一个多边形。由此产生的行为是,所有工具栏(例如菜单和普通工具栏)只能停靠在窗口边缘旁边。然后,可停靠面板更靠近窗体内部。在每个表单边缘上保持成对的停靠点和多个堆栈可以使两种类型的控件停靠在表单的任何一侧,但是约束工具栏始终位于表单的最边缘。这实际上是UI的意义:可停靠的面板往往包含比工具栏更复杂的内容,因此它们是更多的中央控件。当然,如果表单的一个特定边缘上只有一个可停靠的面板,而不是可停靠的工具栏,那么工具栏底座是不可见的(宽度或高度为0),因此面板也位于窗口边缘旁边。
写成文字,很难解释前两段(这个方案如何运作,以及为什么这样好/好。)你需要在实践中尝试并且对用户有意义。的行为。但基本上,我建议您在表单上使用两种类型的停靠点,并使TSpTBXMultiDock
对齐&#39;在内部&#39;或者&#39;内部到&#39;正常的工具栏停靠。希望这个图像有所帮助。
您可能对以下属性感兴趣:
DockableTo
(工具栏和可停靠面板):约束工具栏或面板可以停靠的哪一侧(顶部,底部,左侧,右侧)。使用它可以使某些控件只能停靠在某些特定的停靠点中 - 例如,主菜单只停靠在顶部。DefaultDock
(同样,两者):当用户双击停靠,而不是拖动停靠时,它会去哪里?CurrentDock
:我认为您已经发现了这一点,但是在设计器中将其设置为在停靠点之间移动工具栏或面板,并在运行时读取(或者,我想,如果您在运行时设置以编程方式想要将东西移动到特定的码头。)DockMode
:控制工具栏或面板是否可以浮动(取消停靠并成为自己的窗口),包括它是否可以更改停靠点。使用它的一个例子是主菜单约束。FixedDockSize
(仅限面板):可以通过用户或上面提到的停靠代码停止面板的大小调整。MenuBar
(仅限工具栏):给工具栏稍微不同的行为,我认为它总是占据了底座的整个宽度,并且不允许其他工具栏停靠在它旁边。它也可能会改变项目的呈现方式。