-
Oct 23rd, 2016, 12:27 PM
#1
Thread Starter
Addicted Member
MouseWheel After Deployment
Hi All! I have a VB.NET MDI project with multiple forms developed in VS2010. I’m using net framework 4 client profile.
On one of the forms I have a PictureBox that I use to draw graphics. I use the MouseWheel event to zoom the graphics
in and out. It works fine on my win 10 machine but when I deployed it to a win 7 machine with net framework 4
client profile installed, the MouseWheel event doesn’t work. I also use a protected overrides function
“ProcessCmdKey” to allow the user to move and zoom the graphics with the arrow and page keys. I’m not sure if this
is why the mouse wheel doesn’t work in the deployment machine? Does anyone know this may be happening?
Below is a sample of the code I’m using. Thanks in advance for any help!
Code:
Private Sub picPlotter_MouseWheel(ByVal sender As System.Object, ByVal e As MouseEventArgs) Handles picPlotter.MouseWheel
If intDrawIndex < 0 Then Exit Sub
Dim x As Integer = e.X
Dim y As Integer = e.Y
If e.Delta > 0 Then
blnZoomActive = True
blnMoveActive = True
sngZoomFactor = 1.1
sngMainScale = sngMainScale * 1.1
If x > sngCrtCenX + 100 Then
sngMoveX = -10
ElseIf x < sngCrtCenX - 100 Then
sngMoveX = 10
End If
If y > sngCrtCenY + 100 Then
sngMoveY = -10
ElseIf y < sngCrtCenY - 100 Then
sngMoveY = 10
End If
Else
blnZoomActive = True
blnMoveActive = True
sngZoomFactor = 0.9
sngMainScale = sngMainScale * 0.9
If x > sngCrtCenX + 100 Then
sngMoveX = 10
ElseIf x < sngCrtCenX - 100 Then
sngMoveX = -10
End If
If y > sngCrtCenY + 100 Then
sngMoveY = 10
ElseIf y < sngCrtCenY - 100 Then
sngMoveY = -10
End If
End If
MovePlot()
ChangePlotScale()
End Sub
Protected Overrides Function ProcessCmdKey(ByRef m As Message, ByVal keyData As Keys) As Boolean
If keyData = Keys.PageUp Then
blnZoomActive = True
sngZoomFactor = 1.1
sngMainScale = sngMainScale * 1.1
ChangePlotScale()
End If
If keyData = Keys.PageDown Then
blnZoomActive = True
sngZoomFactor = 0.9
sngMainScale = sngMainScale * 0.9
ChangePlotScale()
End If
If keyData = Keys.Right Then
blnMoveActive = True
sngMoveX = -3
MovePlot()
End If
If keyData = Keys.Left Then
blnMoveActive = True
sngMoveX = 3
MovePlot()
End If
If keyData = Keys.Down Then
blnMoveActive = True
sngMoveY = -3
MovePlot()
End If
If keyData = Keys.Up Then
blnMoveActive = True
sngMoveY = 3
MovePlot()
End If
If Control.ModifierKeys = Keys.Shift Then
Select Case keyData And (Not Keys.Modifiers)
Case Keys.Right
blnMoveActive = True
sngMoveX = -23
MovePlot()
Case Keys.Left
blnMoveActive = True
sngMoveX = 23
MovePlot()
Case Keys.Down
blnMoveActive = True
sngMoveY = -23
MovePlot()
Case Keys.Up
blnMoveActive = True
sngMoveY = 23
MovePlot()
End Select
End If
Return True 'MyBase.ProcessCmdKey(m, keyData)
End Function
-
Oct 23rd, 2016, 12:38 PM
#2
Re: MouseWheel After Deployment
I think you will need to add some logging code to investigate this more. However, I will say that when I worked with the mouse wheel I found that it was terribly inconsistent between mice and machines. The documentation states how it is supposed to work. I occasionally did get the behavior according to the documentation, but usually I didn't.
I like the fact that you are ignoring everything about the delta other than the sign. What you need to do is determine whether you are getting mouse events, and what that delta is...though it may not matter, because it looks like SOMETHING should happen, regardless of what the delta is with your code. The delta is the most unreliable part, so it's good that you don't rely on it much.
The simplest thing to do is to try a different mouse. The next thing you could do is add some logging to see whether or not the event is even being raised. If it is, then you could log the delta.
My usual boring signature: Nothing
-
Oct 23rd, 2016, 04:17 PM
#3
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
Thanks Shaggy Hiker! That is disappointing? A hit and miss mouse wheel I will add logging code and redeploy it to the win 7 machine and see what happens.
-
Oct 23rd, 2016, 05:13 PM
#4
Re: MouseWheel After Deployment
A possible cause: mouse wheel events are normally raised only by the control which has focus, and that usually isn't a picture box. A quick thing you could try is to call the picture box's Select method from its MouseEnter event handler. However, I'm not certain that will fix the problem because I can't see why it should differ from one OS/machine to another.
BB
-
Oct 23rd, 2016, 09:44 PM
#5
Re: MouseWheel After Deployment
I'm currently on Win10 and too lazy to fire-up another computer to test on, but the MouseWheel event fires for the control under the mouse pointer regardless if it has focus.
The MouseWheel message will bubble-up the parent-child window tree until it is handled. On thing that I know of that marks the message as handled is a scrollable control like a form or panel with its Autoscroll property set to True that scrolls when the wheel is used. You can also mark the message as handled by handling the MouseWheel event, casting the MouseEventArgs argument to a HandledMouseEventArgs and setting the Handled property to prevent it from being passed to its parent window.
One thing that you could try to do is implement an IMessage Filter and process the WM_MouseWheel message at the application level. see: Application.AddMessageFilter Method
-
Oct 24th, 2016, 02:46 AM
#6
Re: MouseWheel After Deployment
I just checked under Windows 8.1. The presence of a button or text box on the same form will prevent a picture box from raising wheel events, unless the latter is explicitly selected (= focused). So maybe that is the explanation after all.
For a short discussion and some code examples of using IMessageFilter to resolve this problem, see the ZoomPictureBox thread, posts #51-54.
BB
-
Oct 24th, 2016, 09:04 AM
#7
Re: MouseWheel After Deployment
I believe Windows 10 operates differently: a control doesn't need to have focus for the mouse wheel to operate on that control. whichever control the mouse is over will accept the mousewheel commands.
Previous versions required the scrollable control to have focus.
Last edited by SJWhiteley; Oct 24th, 2016 at 09:09 AM.
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
Oct 29th, 2016, 07:40 AM
#8
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
Thanks everyone for your replies! Sorry I took so long to get back to you. Yes, as boops boops said, there is one TextBox and two Buttons on to form that get focus before the PB does even from the keyboard.
So I will need to add a IMessage Filter just as soon as I figure out how to use it in the form with the PB. Thanks again. I'm off the experiment.
-
Nov 24th, 2016, 11:21 AM
#9
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
The IMessage Filter is nice but do I really need to use it? What if I just add a handler? (AddHandler MouseWheel, AddressOf picPlotter_MouseWheel) Shouldn't this work?
-
Nov 24th, 2016, 11:53 AM
#10
Re: MouseWheel After Deployment
Think about what that does. You can add a handler to an object that raises events. Such an object maintains a list of functions for each event it raises. When the event occurs, the object iterates through the list of functions and calls each item in turn. When you add a handler, what you are really doing is adding a function to the list maintained for that event.
Note that this is maintained by the object that will raise the event. You are talking about getting the mouse wheel. If the object receives the MouseWheel event from the system, then it will raise a MouseWheel event. If that object doesn't receive the event from the system, then it won't be raising anything, so the handlers you have won't be called. What you are trying to intercept is the system message that is coming to the application, regardless of which control(s) are going to get it in the end.
My usual boring signature: Nothing
-
Nov 24th, 2016, 12:14 PM
#11
Re: MouseWheel After Deployment
Originally Posted by DFPCNC
The IMessage Filter is nice but do I really need to use it? What if I just add a handler? (AddHandler MouseWheel, AddressOf picPlotter_MouseWheel) Shouldn't this work?
As far as I am concerned you could just as well put PictureboxName.Select in the picture box's MouseEnter event handler. If it's a single control on a form, it doesn't matter if you specify the handler sub with AddHandler or with the Handles clause. The net effect is the same.
The person who raised the subject of message filters in the thread I linked to thought that "stealing" the focus was undesirable. Personally I don't see anything wrong with it if it doesn't interfere with usability of the app. If necessary, you could save the identity of the control affected and use it return the "stolen" focus in the picture box's MouseLeave event.
BB
Last edited by boops boops; Nov 24th, 2016 at 12:19 PM.
-
Nov 24th, 2016, 03:46 PM
#12
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
I'm lost! Do I add a Class and called it "picPlotter" or do I add this Class to the form with the picture box?
I added a Class to the project and called it "picPlotter" but I don't understand how to add (Application.AddMessageFilter(Me)) in my constructor?
I'm getting an error "Declaration expected"? This is what I have so far.
Code:
Public Class picPlotter
Inherits UserControl
Implements IMessageFilter
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
If m.Msg = &H20A Then
SendMessage(Me.Handle, m.Msg, m.WParam, m.LParam)
Return True
Else
Return False
End If
End Function
#Region "Constructor"
Application.AddMessageFilter(Me)
#End Region
End Class
-
Nov 24th, 2016, 06:01 PM
#13
Re: MouseWheel After Deployment
You must put the statement Application.AddMessageFilter(Me) in a Sub or Function. Presumably you meant it to go in the Constructor; in other words in the New sub.
Directives like #Region/#End Region are just to keep the source code tidy and have no effect on the compiled code. People often have several constructors (New subs) in a class, so it's customary to group these subs in a Region.
BB
-
Nov 25th, 2016, 11:16 AM
#14
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
I added a Public Shared Sub AddMessageFilter() to the form with the picture box. Then I changed the SendMessage call in the Class module to
SendMessage(frm3DPlot.Handle, m.Msg, m.Param, m.LParam). Focus doesn't seem to go to the form Sub or the Class Function? Am I forgetting
a reference to the IMessageFilter? Also, I don't see how this sends the MouseWheel event to the picPlotter_MouseWheel sub?
Code:
Imports System.ComponentModel
Friend Class frm3DPlot 'Form with picture box
Public Shared Sub AddMessageFilter(ByVal value As IMessageFilter)
Application.AddMessageFilter(value)
End Sub
End Class
' New Added Class
Public Class TestMessageFilter()
Implements IMessageFilter
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements IMessageFilter.PreFilterMessage
If m.Msg = &H20A Then
SendMessage(frm3DPlot.Handle, m.Msg, m.WParam, m.LParam)
Return True
Else
Return False
End If
End Function
End Class
-
Nov 25th, 2016, 11:32 AM
#15
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
How about just adding a MouseEnter sub? Like this. Oh yes, as you mentioned in a earlier post BB.
Code:
Private Sub picPlotter_MouseEnter(sender As System.Object, e As System.MouseEventArgs) Handles picPlotter.MouseEnter
picPlotter.Focus()
End Sub
Last edited by DFPCNC; Nov 25th, 2016 at 11:35 AM.
-
Nov 25th, 2016, 01:11 PM
#16
Re: MouseWheel After Deployment
Originally Posted by DFPCNC
How about just adding a MouseEnter sub? Like this. Oh yes, as you mentioned in a earlier post BB.
Code:
Private Sub picPlotter_MouseEnter(sender As System.Object, e As System.MouseEventArgs) Handles picPlotter.MouseEnter
picPlotter.Focus()
End Sub
Exactly. Using IMessageFilter would be like using a steamroller to crack a very small nut.
Besides, if you are a perfectionist you could return focus to the control that had it before like this:
Code:
Private wasFocused As Control
Private Sub PictureBox1_MouseEnter(sender As Object, e As EventArgs) Handles picPlotter.MouseEnter
wasFocused = Me.ActiveControl
picPlotter.Focus()
End Sub
Private Sub PictureBox1_MouseLeave(sender As Object, e As EventArgs) Handles picPlotter.MouseLeave
If wasFocused IsNot Nothing Then wasFocused.Focus()
End Sub
This code belongs in the form which has the picture box. But restoring the focus isn't essential (unless you have a good reason), and as mentioned before none of the above is needed in Windows 10 although it won't do any harm.
Curious note on my earlier code: msdn says the Select method isnt't available for PictureBoxes. But in practice it is, and it has the same effect as Focus.
BB
-
Nov 25th, 2016, 01:40 PM
#17
Thread Starter
Addicted Member
Re: MouseWheel After Deployment
Yes, Thanks BB! I did catch the error in the MouseEnter sub in my last post, (MouseEventArgs should be EventArgs). I won't have access to the win7 machine for testing until after the holidays but I don't see why this shouldn't
work.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|