Windows.Forms.Panel 32767大小限制

本文关键字:32767 Forms Panel Windows | 更新日期: 2023-09-27 18:14:09

我有一个应用程序,它使用Windows.Forms.Panel来显示图片列表。当面板的高度超过32767像素时,其余的内容被简单地切断。

的例子:

Windows.Forms.Panel myPanel;
ArrayList pictureList;
foreach(pic in pictureList) {
    myPanel.Controls.Add(pic) // adds all the objects without complaints
}

在这个例子中,所有的元素都被添加到面板中,没有抛出错误,但是当面板的大小达到32767之后,就不再显示图像了。

我的问题是:是否有可能打破这个限制,在面板中显示更多的内容?

我知道这种方法在任何方面都不方便,但是现在没有时间重新设计整个应用程序。

Windows.Forms.Panel 32767大小限制

这是Windows的架构限制。指示窗口位置的各种消息,如WM_MOUSEMOVE,以32位整数形式报告位置,其中16位为X位置,16位为y位置。因此,不能创建大于short.MaxValue的窗口。这并不是一个真正的问题,没有人有超过32,767像素的显示器,而且在很长一段时间内都不会。

你必须用不同的方法来做这件事。就像在Paint方法中使用Graphics.TranslateTransform()一样

LPARAM - Windows的一种数据类型,用于向Windows过程传递消息参数。它是一个32位的指针,传递消息分为两部分,即高阶(32位的前16位)和低阶(32位的后16位)。

  Where 
       High order is used to pass the height of the control and
       Low order is used to pass the width of the control

如果控件的高度或宽度超过32762size,就会显示错误,因为

32767是16位有符号整数所能表示的最大值。

不使用paint方法的解决方案

我就有这个问题。我不想重新编写已经编码到子控件中的功能。此例程通过滚动条管理子控件,并将未播放的控件隐藏并仅在屏幕外。

Public Class ManuallyScrollingPanel
  Inherits Panel
  Public WithEvents sbar As New System.Windows.Forms.VScrollBar
  Sub New()
    MyBase.New()
    Controls.Add(sbar)
    sbar.Visible = True
    Me.AutoScroll = False
  End Sub
  Sub SetScrollParams()
    If PanelPositions.Any Then
      Dim NewMax = CInt((From item In PanelPositions.Values Select item.Bottom).Max + 500) - Height
      If sbar.Maximum <> NewMax Then
        sbar.Maximum = NewMax
      End If
    End If
  End Sub
  Public Sub RegisterChildSize(pnl As Panel, DesiredBounds As Drawing.Rectangle)
    PanelPositions(pnl) = DesiredBounds
    SetScrollParams()
  End Sub
  Dim PanelPositions As New Dictionary(Of Panel, Drawing.Rectangle)
  Private Sub ManuallyScrollingPanel_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
    sbar.Top = 0
    sbar.Left = Width - sbar.Width
    sbar.Height = Me.Height
    SetScrollParams()
    sbar.LargeChange = CInt(Height * 0.9)
    sbar.SmallChange = CInt(Height * 0.2)
  End Sub
  Private Sub sb_Scroll(sender As Object, e As ScrollEventArgs) Handles sbar.Scroll
    ScrollTo(e.NewValue)
  End Sub
  Private Sub sb_ValueChanged(sender As Object, e As EventArgs) Handles sbar.ValueChanged
    ScrollTo(sbar.Value)
  End Sub
  Sub ScrollTo(pos As Integer)
    Me.AutoScroll = False
    For Each kvp In PanelPositions
      Dim VirtBounds = New Drawing.Rectangle(CInt(kvp.Value.Left), CInt(kvp.Value.Top - pos), CInt(kvp.Value.Width), CInt(kvp.Value.Height))
      If VirtBounds.Bottom < 0 Or VirtBounds.Top > Height Then
        ' it's not visible - hide it and position offscreen
        kvp.Key.Visible = False
        kvp.Key.Top = VirtBounds.Top
      Else
        ' Visible, position it
        kvp.Key.Top = VirtBounds.Top
        kvp.Key.Visible = True
      End If
    Next
  End Sub
End Class
然后,对于每个子控件(我的是动态添加的,听起来像OP正在做同样的事情)进行此调用:
CType(Parent, ManuallyScrollingPanel).RegisterChildSize(Me, PanelObject.Bounds)

注意,当我从dto构建控件以允许相同的应用程序+视图作为web应用程序和windows应用程序呈现时,我分别传递了子控件的边界。将其限制为面板也是如此。

为什么不给面板添加一个滚动条呢

just set AutoScrollbar = true

并将rightolleft属性设置为true