【问题标题】:How do I detect if a panel is in the viewable window?如何检测面板是否在可视窗口中?
【发布时间】:2015-09-30 14:47:35
【问题描述】:

使用 Winforms 和 vb.net VS 2012:

如果我有一个大的可滚动面板,我将一堆较小的面板放在较大的面板中。当我向上或向下滚动较大的面板时,一些较小的面板将滚动到视野之外。我的问题是,我可以在较小的面板上放置一个侦听器,以便较小的面板知道它何时滚动到视野之外?

我不能使用 .visible 属性,因为即使面板不在窗口中,它也始终设置为 true。我也知道我可以设置 .focus 属性以将其重新显示在视图中,但是当其他东西获得焦点时,它仍然会在可视窗口中失去焦点。

那么有没有我可以监听的属性或东西来检测面板何时滚动到视野之外?如果没有,我还能做些什么来检测这一点吗?

谢谢。

【问题讨论】:

    标签: vb.net scroll panel


    【解决方案1】:

    从 Panel 的 Scroll() 和 MouseWheel() 事件中,使用如下代码:

    Private Sub Panel1_Scroll(sender As Object, e As ScrollEventArgs) Handles Panel1.Scroll
        CheckVisibility(sender)
    End Sub
    
    Private Sub Panel1_MouseWheel(sender As Object, e As MouseEventArgs) Handles Panel1.MouseWheel
        CheckVisibility(sender)
    End Sub
    
    Private Sub CheckVisibility(ByVal pnl As Panel)
        Dim results As New List(Of String)
    
        Dim pnlRectScreen As Rectangle = pnl.Parent.RectangleToScreen(pnl.Bounds)
        For Each child As Control In pnl.Controls
            Dim childRectScreen As Rectangle = pnl.RectangleToScreen(child.Bounds)
            If pnlRectScreen.IntersectsWith(childRectScreen) Then
                If pnlRectScreen.Contains(childRectScreen) Then
                    results.Add(child.Name & ": Completely Visible")
                Else
                    results.Add(child.Name & ": Partially Visible")
                End If
            Else
                results.Add(child.Name & ": Not Visible")
            End If
        Next
    
        ListBox1.DataSource = Nothing
        ListBox1.DataSource = results
    End Sub
    

    如果您只想知道它何时隐藏,则使用 Dictionary() 跟踪当前可见性,并在它变为隐藏时执行某些操作。这是一个更强大的示例:

    Public Enum ControlVisibility
        Hidden
        PartialyVisible
        FullyVisible
    End Enum
    
    Private VisibiltyState As New Dictionary(Of Control, ControlVisibility)
    
    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        Dim pnl As Panel = Panel1
        Dim pnlRectScreen As Rectangle = pnl.Parent.RectangleToScreen(pnl.Bounds)
        For Each child As Control In pnl.Controls
            Dim childRectScreen As Rectangle = Panel2.RectangleToScreen(child.Bounds)
            If pnlRectScreen.IntersectsWith(childRectScreen) Then
                If pnlRectScreen.Contains(childRectScreen) Then
                    VisibiltyState.Add(child, ControlVisibility.FullyVisible)
                Else
                    VisibiltyState.Add(child, ControlVisibility.PartialyVisible)
                End If
            Else
                VisibiltyState.Add(child, ControlVisibility.Hidden)
            End If
        Next
    End Sub
    
    Private Sub Panel1_Scroll(sender As Object, e As ScrollEventArgs) Handles Panel1.Scroll
        CheckVisibility(sender)
    End Sub
    
    Private Sub Panel1_MouseWheel(sender As Object, e As MouseEventArgs) Handles Panel1.MouseWheel
        CheckVisibility(sender)
    End Sub
    
    Private Sub CheckVisibility(ByVal pnl As Panel)
        Dim NewVisibility As ControlVisibility
        Dim pnlRectScreen As Rectangle = pnl.Parent.RectangleToScreen(pnl.Bounds)
        For Each child As Control In pnl.Controls
            Dim childRectScreen As Rectangle = pnl.RectangleToScreen(child.Bounds)
            If pnlRectScreen.IntersectsWith(childRectScreen) Then
                If pnlRectScreen.Contains(childRectScreen) Then
                    NewVisibility = ControlVisibility.FullyVisible
                Else
                    NewVisibility = ControlVisibility.PartialyVisible
                End If
            Else
                NewVisibility = ControlVisibility.Hidden
            End If
    
            ' has it changed?
            If VisibiltyState(child) <> NewVisibility AndAlso NewVisibility = ControlVisibility.Hidden Then
                Debug.Print(child.Name & " has become hidden: " & DateTime.Now.ToString("h:mm:ss.ffff"))
            End If
    
            VisibiltyState(child) = NewVisibility
        Next
    End Sub
    

    【讨论】:

    • 这似乎可行,但似乎也有很多开销。滚动条每移动一次,就得跑这个过程400多个对象,我觉得延迟太长了。
    • 你只需要试试看,对不起。据我所知,没有 canned 事件可以满足您的需求....
    • 谢谢,我试过了,它对于我需要的东西来说太慢了。我必须找到另一种处理对象的方法。
    猜你喜欢
    • 2021-11-28
    • 1970-01-01
    • 2010-10-02
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多