如何使用组合框架进行垂直滚动 [英] How make vertical scrolling of form with comboboxes

查看:46
本文介绍了如何使用组合框架进行垂直滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hello Coders,

我有一个任务是使用30 - 40个组合框进行垂直滚动形式

Comboboxes在运行时动态添加。

但是,当我旋转鼠标滚轮的面板滚动执行时,

这段代码有什么问题?谢谢。

 公共  Form1 
继承 System.Windows.Forms.Form

< System.Diagnostics.DebuggerStepThrough()> _
私有 Sub InitializeComponent()
.Panel1 = System.Windows.Forms.Panel()
.SuspendLayout()
'
' Panel1
'
.Panel1.Anchor = CType ((系统。 Windows.Forms.AnchorStyles.Left System.Windows.Forms.AnchorStyles.Right),System.Windows.Forms.AnchorStyles)
.Panel1.AutoScroll = True
。 Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me .Panel1.Location = 系统。 Drawing.Point( 0 0
.Panel1.Name = Panel1
Me .Panel1.Size = System.Drawing.Size( 353 408
.Panel1.TabIndex = 0
'
' Form1
'
.AutoScaleDimensio ns = System.Drawing.SizeF( 6 .0!, 13 .0!)
Me .AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
.ClientSize = System.Drawing.Size( 353 408
.Controls.Add( .Panel1)
.Name = Form1
.Text = < span class =code-string> Form1
Me .ResumeLayout( False

结束 Sub
朋友 WithEvents Panel1 As System.Windows.Forms.Panel

公共 Sub New ()
InitializeComponent()
End Sub

私有 Sub Form1_Load(发件人作为 对象,e As EventArgs)句柄 。加载
' 加载时添加到Panel1几个组合框
Dim i As 整数
Dim YPosition As Integer = 0
对于 i = 0 35
Dim Combo = System.Windows.Forms.ComboBox()
Combo.Items.AddRange( New 对象(){ 首先 第二个 第三个})
Combo.Location = System.Drawing.Point( 55 95
Combo.Size = System.Drawing.Size( 121 21
Combo.SelectedIndex = 0
Combo.Location = Point( 5 ,YPosition)
AddHandler Combo.MouseWheel, AddressOf ComboBox_MouseWheel

Me .Panel1.Controls.Add(Combo)
YPosition + = Combo.Height + 15

下一步

结束 Sub

私有 Sub ComboBox_MouseWheel(发件人作为 对象,e As MouseEventArgs)
' http://blog.iordanov.info/?p=58
如果(e.Delta<> 0 然后
Dim NewVerticalScrollValue As 整数
' ???这很奇怪,但滚动执行方向相反???所以需要设置减去
Dim NewDelta 作为 整数 = e.Delta * -1 ' CInt(e.Delta / 3)* - 1
NewVerticalScrollValue = .Panel1.VerticalScroll.Value()+ NewDelta
如果(NewVerticalScrollValue> Me .Panel1.VerticalScroll.Maximum)那么
NewVerticalScrollValue = Me .Panel1.VerticalScroll.Maximum
结束 如果
如果(NewVerticalScrollValue< Me .Panel1.VerticalScroll。最小值)然后
NewVerticalScrollValue = Me .Panel1.VerticalScroll.Minimum
End 如果

如果 .Panel1.VerticalScroll。值<> NewVerticalScrollValue 然后
如果发​​件人 IsNot Nothing AndAlso TypeOf sender System.Windows.Forms.ComboBox 然后
DirectCast (sender,System.Windows.Forms.ComboBox).DroppedDown = False ' close combobox
结束 如果

' 如果TypeOf e是HandledMouseEventArgs那么
' Dim WheelEventArgs As Handl edMouseEventArgs = TryCast(e,HandledMouseEventArgs)
' 如果WheelEventArgs IsNot Nothing那么
' WheelEventArgs.Handled = True'不要滚动组合框中的项目而是滚动面板
' 结束如果
' 结束如果

.Panel1.VerticalScroll.Value = NewVerticalScrollValue
如果 Me .Panel1.VerticalScroll.Value<> NewVerticalScrollValue 然后
Debug.Print( String .Format( CB不同:{0} - {1} !!!! .Panel1.VerticalScroll.Value,NewVerticalScrollValue))
Else
Debug.Print( String .Format( CB:{0} .Panel1.VerticalScroll.Value))
结束 如果
结束 如果
结束 如果
结束 Sub

结束

解决方案

您遇到了一个控件(ComboBox)的乐趣,它具有您希望发送给其父节点的事件消息(MouseWheel)的焦点。在这种情况下,ComboBox还具有与MouseWheel相关联的预定义功能(它在项目列表中向上/向下移动所选项目)。我修改了你的代码,通过允许消息传递给控件,​​如果指针位于控件上,或者将消息发送到控件的父级(硬编码为Panel),如果指针未超过控制。我试着评论它足以跟随,但如果你有任何问题,请随时问。



 Imports System.Runtime.InteropServices 

Public Class Form1
继承System.Windows.Forms。表格
'实施IMessageFilter以便我们可以拦截滚动消息
实现IMessageFilter

< System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Panel1 = New PanelWithExposedWndProc'**** note note
Me.SuspendLayout()
'
'Panel1
'
Me.Panel1.Anchor = CType((System.Windows.Forms.AnchorStyles.Left或System.Windows.Forms.AnchorStyles.Right),System.Windows.Forms.AnchorStyles)
Me。 Panel1.AutoScroll = True
Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me.Panel1.Location = New System.Drawing.Point(0,0)
Me .Panel1.Name =Panel1
Me.Panel1.Size = New System.Drawing.Size(353,408)
Me.Panel1.TabIndex = 0
'
' Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!,13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me。 ClientSize = New System.Drawing.Size(353,408)
Me.Controls.Add(Me.Panel1)
Me.Name =Form1
Me.Text =Form1
Me.ResumeLayout(False)
End Sub

Public Sub New( )
InitializeComponent()
End Sub

Private Sub Form1_Load(ByVal sender As Object,ByVal e As EventArgs)处理Me.Load
'加载加载到Panel1几个组合框
Dim i As Integer
Dim YPosition As Integer = 0
For i = 0 To 35
Dim Combo As New System.Windows.Forms.ComboBox()
Combo.Items.AddRange(New Object(){First,Second,Third})
Combo.Location = New System.Drawing.Point(55,95)
Combo。 Size = New System.Drawing.Size(121,21)
Combo.SelectedIndex = 0
Combo.Location = New Point(5,YPosition)

Me.Panel1.Controls .Add(Combo)
YPosition + = Combo.Height + 15
Next
End Sub

'Friend WithEvents Panel1 As System.Windows.Forms.Panel
'改为使用子类别面板,需要它来发送滚动消息
Friend WithEvents Panel1 As PanelWithExposedWndProc

Private Const WM_MOUSEWHEEL As Int32 =& H20A
公共函数PreFilterMessage(ByRef m As System.Windows.Forms.Message)As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
如果m.Msg = WM_MOUSEWHEEL那么
'获取然后控制该消息从句柄指向
Dim c As Control = Control.FromChildHandle(m.HWnd)

如果c IsNot Nothing AndAlso c.Parent IsNot Nothing and c .Parent是Panel1然后是
'Focus中的控件是Panel1
的父级'确定鼠标指针当前是否在控件上接收
'鼠标滚轮消息
'第一次提取来自LParam的鼠标位置
Dim MouseLocation As New Point (m.LParam.ToInt32()和& HFFFF,m.LParam.ToInt32()>> 16)
如果不是c.ClientRectangle.Contains(c.PointToClient(MouseLocation))那么
'指针不在控件之上,因此阻止消息转到焦点控件
'并将消息重新发送到Panel1,以便它滚动
m.HWnd = Panel1.Handle
Panel1.ProcessMessage(m)
返回True'返回True阻止消息
结束如果
End if
End if
End Function

Private Sub Form1_Activated(ByVal sender As Object,ByVal e As System.EventArgs)Handles Me.Activated
'消息过滤器是应用程序范围的,因此仅在此表单处于活动状态时才适用
Application.AddMessageFilter(Me)
End Sub

Private Sub Form1_Deactivate(ByVal sender As Object,ByVal e As System.EventArgs)处理Me.Deactivate
'消息过滤器是应用程序范围的,因此仅在此表单处于活动状态时才适用
'由于此表单已被停用,请删除过滤器
Application.RemoveMessageFilter(Me)
End Sub
End Class

Public Class PanelWithExposedWndProc
Inherits Panel
'此方法只暴露受保护的WndProc方法
Friend Sub ProcessMessage(ByVal msg As Message)
Me.WndProc(msg)
End Sub
End Class


Hello Coders,
I have a task to make vertical scrolling of form with 30 – 40 comboboxes
Comboboxes adding dynamically on runtime.
But when I rotate the mouse wheel scroll of panel executing brokenly
What wrong in this code? Thanks.

Public Class Form1
    Inherits System.Windows.Forms.Form

    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Panel1 = New System.Windows.Forms.Panel()
        Me.SuspendLayout()
        '
        'Panel1
        '
        Me.Panel1.Anchor = CType((System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.Panel1.AutoScroll = True
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.Panel1.Location = New System.Drawing.Point(0, 0)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(353, 408)
        Me.Panel1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(353, 408)
        Me.Controls.Add(Me.Panel1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents Panel1 As System.Windows.Forms.Panel

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        'on load add to Panel1 few comboboxes
        Dim i As Integer
        Dim YPosition As Integer = 0
        For i = 0 To 35
            Dim Combo = New System.Windows.Forms.ComboBox()
            Combo.Items.AddRange(New Object() {"First", "Second", "Third"})
            Combo.Location = New System.Drawing.Point(55, 95)
            Combo.Size = New System.Drawing.Size(121, 21)
            Combo.SelectedIndex = 0
            Combo.Location = New Point(5, YPosition)
            AddHandler Combo.MouseWheel, AddressOf ComboBox_MouseWheel

            Me.Panel1.Controls.Add(Combo)
            YPosition += Combo.Height + 15

        Next

    End Sub

    Private Sub ComboBox_MouseWheel(sender As Object, e As MouseEventArgs)
        'http://blog.iordanov.info/?p=58
        If (e.Delta <> 0) Then
            Dim NewVerticalScrollValue As Integer
            '??? it's strange, but scroll execute in opposite direction ??? so need set minus
            Dim NewDelta As Integer = e.Delta * -1 ' CInt(e.Delta / 3) * -1
            NewVerticalScrollValue = Me.Panel1.VerticalScroll.Value() + NewDelta
            If (NewVerticalScrollValue > Me.Panel1.VerticalScroll.Maximum) Then
                NewVerticalScrollValue = Me.Panel1.VerticalScroll.Maximum
            End If
            If (NewVerticalScrollValue < Me.Panel1.VerticalScroll.Minimum) Then
                NewVerticalScrollValue = Me.Panel1.VerticalScroll.Minimum
            End If

            If Me.Panel1.VerticalScroll.Value <> NewVerticalScrollValue Then
                If sender IsNot Nothing AndAlso TypeOf sender Is System.Windows.Forms.ComboBox Then
                    DirectCast(sender, System.Windows.Forms.ComboBox).DroppedDown = False 'close combobox
                End If

                'If TypeOf e Is HandledMouseEventArgs Then
                '    Dim WheelEventArgs As HandledMouseEventArgs = TryCast(e, HandledMouseEventArgs)
                '    If WheelEventArgs IsNot Nothing Then
                '        WheelEventArgs.Handled = True 'don't scroll items in combobox but scroll panel
                '    End If
                'End If

                Me.Panel1.VerticalScroll.Value = NewVerticalScrollValue
                If Me.Panel1.VerticalScroll.Value <> NewVerticalScrollValue Then
                    Debug.Print(String.Format("CB different: {0} - {1} !!!!", Me.Panel1.VerticalScroll.Value, NewVerticalScrollValue))
                Else
                    Debug.Print(String.Format("CB: {0}", Me.Panel1.VerticalScroll.Value))
                End If
            End If
        End If
    End Sub

End Class

解决方案

You have encountered the joy of a control (ComboBox) having focus for a event message(MouseWheel) that you would prefer to have sent to its parent instead. In this case, the ComboBox has also has predefined function associated with the MouseWheel (it moves the selected item up/down the item list). I have modified your code to deal with this by allowing the message to pass to the control if the the pointer is positioned over it or to send the message to the control's parent (hard coded to be the Panel) if it pointer is not over the control. I tried to comment it enough to follow, but if you have any questions, feel free to ask.

Imports System.Runtime.InteropServices

Public Class Form1
   Inherits System.Windows.Forms.Form
   ' Implement IMessageFilter so that we can intercept the scroll message
   Implements IMessageFilter

    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Panel1 = New PanelWithExposedWndProc ' **** note change
        Me.SuspendLayout()
        '
        'Panel1
        '
        Me.Panel1.Anchor = CType((System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.Panel1.AutoScroll = True
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.Panel1.Location = New System.Drawing.Point(0, 0)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(353, 408)
        Me.Panel1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(353, 408)
        Me.Controls.Add(Me.Panel1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
        'on load add to Panel1 few comboboxes
        Dim i As Integer
        Dim YPosition As Integer = 0
        For i = 0 To 35
            Dim Combo As New System.Windows.Forms.ComboBox()
            Combo.Items.AddRange(New Object() {"First", "Second", "Third"})
            Combo.Location = New System.Drawing.Point(55, 95)
            Combo.Size = New System.Drawing.Size(121, 21)
            Combo.SelectedIndex = 0
            Combo.Location = New Point(5, YPosition)

            Me.Panel1.Controls.Add(Combo)
            YPosition += Combo.Height + 15
        Next
    End Sub

    'Friend WithEvents Panel1 As System.Windows.Forms.Panel
   ' Use the sub classed panel instead, need this to send it the scroll message
   Friend WithEvents Panel1 As PanelWithExposedWndProc

   Private Const WM_MOUSEWHEEL As Int32 = &H20A
   Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
      If m.Msg = WM_MOUSEWHEEL Then
         ' Get then control that message is directed to from the handle
         Dim c As Control = Control.FromChildHandle(m.HWnd)

         If c IsNot Nothing AndAlso c.Parent IsNot Nothing And c.Parent Is Panel1 Then
            ' The control in Focus is parented to Panel1
            ' Determine if the mouse pointer is currently over the control receiving the
            ' mouse wheel message
            ' 1st extract the mouse position from LParam
            Dim MouseLocation As New Point(m.LParam.ToInt32() And &HFFFF, m.LParam.ToInt32() >> 16)
            If Not c.ClientRectangle.Contains(c.PointToClient(MouseLocation)) Then
               ' pointer is not over the control, so block the message from going to the control in focus
               ' and resend the message to Panel1 so that it scrolls
               m.HWnd = Panel1.Handle
               Panel1.ProcessMessage(m)
               Return True ' returning True blocks the message
            End If
         End If
      End If
   End Function

   Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
      ' Message Filter is application wide, so only apply when this form is active
      Application.AddMessageFilter(Me)
   End Sub

   Private Sub Form1_Deactivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Deactivate
      ' Message Filter is application wide, so only apply when this form is active
      ' Since this form has been deactivate, remove the filter
      Application.RemoveMessageFilter(Me)
   End Sub
End Class

Public Class PanelWithExposedWndProc
   Inherits Panel
   ' This method just exposes the protected WndProc method
   Friend Sub ProcessMessage(ByVal msg As Message)
      Me.WndProc(msg)
   End Sub
End Class


这篇关于如何使用组合框架进行垂直滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆