Windows.Forms.Panel 32767大小限制

时间:2011-11-09 11:58:46

标签: c# .net winforms

我有一个使用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后,不再显示任何图像。

我的问题:是否可以打破此限制并在面板中显示更多内容?

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

4 个答案:

答案 0 :(得分:11)

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

你必须以不同的方式做到这一点。就像在Paint方法中使用Graphics.TranslateTransform()一样。

答案 1 :(得分:1)

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位整数表示的最高数字。

答案 2 :(得分:1)

没有绘画方法的解决方案

我遇到了这个问题。我不想重写已编码到我的子控件中的功能。此例程通过滚动条管理子控件,并使隐藏的场外控件保持隐藏状态。

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构建控件时允许单独传递子区域,以允许相同的app +视图呈现为Web应用程序和Windows应用程序。与限制面板相同。根据需要重构。

答案 3 :(得分:-1)

为什么不向面板添加滚动条

只需设置AutoScrollbar = true

并将RightToLeft属性设置为true。