我有一个使用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后,不再显示任何图像。
我的问题:是否可以打破此限制并在面板中显示更多内容?
我知道这种方法无论如何都不方便,但现在没有时间重新设计整个应用程序了。
答案 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。