Results 1 to 17 of 17

Thread: MouseWheel After Deployment

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    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

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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.

  4. #4
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    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

  5. #5
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    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

  6. #6
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    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

  7. #7
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    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."

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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.

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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?

  10. #10
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    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

  11. #11
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: MouseWheel After Deployment

    Quote Originally Posted by DFPCNC View Post
    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

  12. #12

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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

  13. #13
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    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

  14. #14

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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

  15. #15

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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.

  16. #16
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: MouseWheel After Deployment

    Quote Originally Posted by DFPCNC View Post
    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

  17. #17

    Thread Starter
    Addicted Member
    Join Date
    Aug 2014
    Location
    SoCal, USA
    Posts
    150

    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
  •  



Click Here to Expand Forum to Full Width