【问题标题】:How do I prevent the vertical scrollbar from taking space in the control, causing an horizontal scrollbar?如何防止垂直滚动条在控件中占用空间,导致水平滚动条?
【发布时间】:2015-04-09 16:19:00
【问题描述】:

我有一个嵌入了FlowLayoutPanel 的自定义控件,我在其中添加了元素(其他自定义控件)。在FlowLayoutPanel 的布局事件中,我将FlowLayoutPanel 中的所有控件调整为包含FlowLayoutPanel 的大小。

在需要垂直滚动条 (AutoScroll = True) 之前一切正常,占用 FLpanel 内的空间,导致出现水平滚动条。

你看到的乱码是我在元素的构造函数中生成的一些随机占位符文本。

我想防止这种情况发生:

我尝试向用户控件添加一个垂直滚动控件并在Scroll 事件中执行FlowLayoutPanel.VertScroll.Value=sender.value:它似乎有效,但是在移动滚动条时使实际的垂直和水平滚动条闪烁(出现和消失)很多控制。

我真的不知道是否有一些属性可以使滚动条在FlowLayoutPanel控件内容之外。

我在 VB.Net 中执行此操作,但 C# 答案很好(因为它基本上是相同的语法,至少在使用控件和 UI 时)。

编辑


我忘了提到我在FlowLayoutPanel 中有WrapContents=falseAutoScroll=true

另外,如果你觉得这个设计很熟悉:它是 Opera M2 邮件列表屏幕的像素完美副本。

更新 1


在你的 cmets 之后,我想出了这个:

Public Class FlowListPanel ' The user control

Private Sub Me_Load(sender As Object, e As EventArgs) Handles Me.Load
    FL_Panel.AutoScroll = True ' FL_Panel is the FlowLayoutPanel
    FL_Panel.WrapContents = False

    FL_Panel.Dock = System.Windows.Forms.DockStyle.Fill
    FL_Panel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown
    FL_Panel.Margin = New System.Windows.Forms.Padding(0)
End Sub

Sub AddItem(c As Control)
    FL_Panel.Controls.Add(c)
    ReorderControls()
End Sub

Private Sub FLP_CSC(sender As Object, e As EventArgs) Handles FL_Panel.ClientSizeChanged
    ReorderControls()
End Sub

Sub ReorderControls()
    For Each ctrl In FL_Panel.Controls
        ctrl.Width = FL_Panel.ClientSize.Width
    Next
End Sub

Private Sub FL_Panel_L(sender As Object, e As LayoutEventArgs) Handles FL_Panel.Layout
    ReorderControls()
End Sub

End Class

似乎可以,但是当达到垂直滚动条出现的临界点时,出现水平滚动条出现问题。

一旦添加了另一个项目,水平滚动条就会消失。

另外,我认为问题可能是由于ReorderControls sub 没有被调用,所以我做了一个按钮来调用它,但没有任何改变。

移除元素时不会出现此问题(但仅在添加时出现)。

在调整窗口大小并且必须出现垂直滚动条时也会发生这种情况。

如下所示,添加新元素后,它可以正常工作:

更新 2


我已遵循 Plutonix 的建议(修改代码 from his other answer),因此我对 ReorderControls 子进行了一些修改,以这种方式:

    Sub ReorderControls()

    Dim HScrollVis As Boolean = NativeMethods.IsHScrollVisible(FL_Panel)

    If HScrollVis Then ' HScroll visible -> kill it with fire!
        NativeMethods.ShowHideScrollBar(FL_Panel,
                                        NativeMethods.SBOrientation.SB_HORZ,
                                        False)
        Return ' as it works anyway...
    End If

    For Each ctrl In FL_Panel.Controls
        ctrl.Width = FL_Panel.ClientSize.Width
    Next
    End Sub

现在水平滚动条闪烁一次,而不是停留在那里,当垂直滚动条出现时。

我喜欢 gif,所以这是目前的效果:

您可能看不到(由于 gif 的低帧率),水平条可能只有在几分之一秒内寻找它的人才能注意到。

我认为问题已解决 80%,并将继续前进。如果我或某人提出明确的建议,我会立即接受答案。

【问题讨论】:

  • 您需要扩展控件以获得更多水平空间。只需减少文本和字体之间的一些空白,您就有足够的空间可以利用。不要让它变得比需要的更难
  • 你试过这个吗:stackoverflow.com/questions/5556561/…
  • 您是否尝试过使用 Windows Messaging / WinProc 执行此操作..?这是一个例子stackoverflow.com/questions/16009743/…
  • 如果您不想要 HScroll,则需要缩小事物的宽度,以便它们和 VScroll 适合。如果您不喜欢显示的间隙/BG,您可以在ClientSizeChanged 事件中添加代码,并在它发生变化时缩小它们(弹出时似乎只有 6 个)。您还可以添加一些 PInvokes 来吃掉 HScroll,这样它就不会在添加第 7 个时弹出然后消失。 OTOH,这也许可以作为自定义控件内置到它们中?
  • @JeremyK 我正在考虑它,但我不知道如何获取滚动条的大小,也不知道什么事件是合适的(现在我知道了,谢谢 tp Plutonix)。

标签: c# .net vb.net winforms


【解决方案1】:

这是一种替代方法,可为您提供所需的结果。当然它不能直接回答您的问题,但在我看来,如果您需要弄乱控件的工作方式以获得所需的解决方案,那么您没有使用正确的控件。

而不是将您的控件直接添加到 FowLayoutPanel,

使用包含 TableLayoutPanel 的标准 Panel 对象。

将面板属性设置为...

AutoScroll=True

将 TableLayoutPanel 属性设置为

停靠 = 顶部

Autosize = True , GrowAndSHrink

从 TableLayoutPanel 中的一个单元格开始..

现在将您的控件添加到 TableLayoutPanel...

例如

Dim CTRL As New Your_User_Control
TableLayoutPanel1.Controls.Add(CTRL)
CTRL.Dock = DockStyle.Top

当滚动条出现时,TableLAyoutPanel 会水平收缩适当的量,包含的所有控件也会自动收缩。

【讨论】:

  • 表格列应设置为 100% 才能正常工作。
【解决方案2】:

只需确保使用以下属性对其进行初始化:

this.WrapContents = false;
this.AutoScroll = true;

您还需要确保添加到其中的控件的最大宽度为控件宽度减去滚动条宽度。

不过应该​​这样做。


编辑:

我从我的一个自定义控件中得到了这个解决方案。它似乎与this post 非常相似——我最初可能从那里得到它,我真的不记得了。帖子链接以防万一。


编辑 2:

当您已经设置了这些属性并查看图像时,您只需将要添加到 FlowPanel 的控件变窄,或者将 FlowPanel 变宽。

基本上,您只需要留出滚动条出现时所占用的空间。如果您真的想始终使用所有宽度,您可以检测它是否可见并强制内部控件相应地更新其布局。

【讨论】:

  • 我更新了问题,因为我已经在使用这些设置,但我忘了在问题中指定它。 ;)
  • 您是否尝试将this.Invalidate(); 添加到ClientSizeChanged 处理程序?我怀疑您只需要告诉控件再次重绘自己,因为您只是在执行布局更改后更改内容的大小。
  • 我在用户控件和 flowlayoutpanel 上都尝试了 Invalidate,但没有结果。但是,我有点早于@plutonix 的建议解决了。现在,当 vbar 出现时,我得到的只是快速闪烁。这对我来说是可以接受的,因为它几乎不引人注意......
  • 非常好 - 我可能会尝试在没有的情况下修复它,因为我怀疑它几乎就在那里 - 事实上它在你添加另一个项目后消失让我相信你只需要改变订单在适当的时候稍微或标记重绘或布局更新。如果我得到它的工作,我会更新答案。
  • 是的,我也有同样的感觉。 :)
猜你喜欢
  • 2012-11-14
  • 2013-11-05
  • 2016-11-10
  • 2019-09-13
  • 2018-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多