如何使用组合框架进行垂直滚动 [英] How make vertical scrolling of form with comboboxes
本文介绍了如何使用组合框架进行垂直滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
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屋!
查看全文