Results 1 to 9 of 9

Thread: [RESOLVED] Retrieving mouse speed

  1. #1

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Resolved [RESOLVED] Retrieving mouse speed

    I am writing a program in which the user can vary the mouse speed, and I need to restore it to its original value on exit. I am able to set the mouse speed OK but I cannot read it. Here's some test code (VB2010):
    Code:
    	<System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint:="SystemParametersInfo")> _
    	Public Shared Function SystemParametersInfo(ByVal uAction As Int32, ByVal uParam As Int32, ByVal pvParam As IntPtr, ByVal fuWinIni As Int32) As Int32
    	End Function
    
    	Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    		Const SPI_GETMOUSESPEED As Int32 = &H70
    		Const SPI_SETMOUSESPEED As Int32 = &H71
    		Dim setValue As Integer = 17
    		Dim setValuePtr As New IntPtr(setValue)
    		Dim getValue As Integer
    		Dim getValuePtr As New IntPtr(getValue)
    		SystemParametersInfo(SPI_SETMOUSESPEED, 0, setValuePtr, 0)
    		SystemParametersInfo(SPI_GETMOUSESPEED, 0, getValuePtr, 1)
    		Console.WriteLine(getValue.ToString)
    	End Sub
    This sets the mouse speed correctly (to 17 in the above code) but the console output is always 0. Can anyone see what's wrong?

    The msdn documentation is as follows:
    Name:  mouseSpeed.png
Views: 832
Size:  10.9 KB

  2. #2
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Retrieving mouse speed

    I'll take a look, have you checked the pointer value for the get function, that it is non-zero? Not sure if new IntPtr(val) returns a pointer...

    EDIT

    Yep the pointer returned 0.
    Code:
            Dim setValue As Integer = 17
            Dim setValuePtr As New IntPtr(setValue)
            Dim getValue As Integer
            Dim getValuePtr As New IntPtr(getValue)
            MsgBox(getValuePtr) 'Zero here
    You have to use ByRef instead of ByVal to get the value. This works with me:
    Code:
        <System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint:="SystemParametersInfo")> _
    Public Shared Function SystemParametersInfoGet(ByVal uAction As SPI, ByVal uParam As Int32, ByRef pvParam As IntPtr, ByVal fuWinIni As SPIF) As Int32
        End Function
    
        <System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint:="SystemParametersInfo")> _
    Public Shared Function SystemParametersInfoSet(ByVal uAction As SPI, ByVal uParam As Int32, ByVal pvParam As IntPtr, ByVal fuWinIni As SPIF) As Int32
        End Function
    
        Public Enum SPI As Int32
            GETMOUSESPEED = &H70
            SETMOUSESPEED = &H71
        End Enum
        Public Enum SPIF As Int32
            UPDATEINIFILE = 0
            SENDCHANGE = 1
            SENDWININICHANGE = 2
        End Enum
    
        Private Sub Routine()
            Dim setValue As Integer = 17
            Dim getValue As Integer
            SystemParametersInfoSet(SPI.SETMOUSESPEED, 0, setValue, 0)
            MsgBox("is set")
            SystemParametersInfoGet(SPI.GETMOUSESPEED, 0, getValue, 1)
            MsgBox("got: " & getValue)
        End Sub
    EDIT

    Since I hold an API class (own project) I added this property to the class:
    Code:
            Public Enum Action As Int32
                GETMOUSESPEED = &H70
                SETMOUSESPEED = &H71
            End Enum
            Public Shared Property MOUSESPEED() As Integer
                Get
                    Dim rval As Integer = 0
                    SystemParametersInfoGet(Action.GETMOUSESPEED, 0, rval, 0)
                    Return rval
                End Get
                Set(ByVal value As Integer)
                    SystemParametersInfoSet(Action.SETMOUSESPEED, 0, value, 1)
                End Set
            End Property
    May you find it useful, use it.

  3. #3

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Retrieving mouse speed

    Rep+ to you bergerkiller: ByRef is the answer! It looks simple in retrospect but I spent a ridiculous amount of time trying to get this to work and didn't think of that. I'm not sure whether I need to structure the Sub into a Get and a Set version for my present purposes since ByRef seems to work fine in both cases. But your code is very clear and I will certainly end up defining a property following your example.

    Cheers, BB

  4. #4
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Re: Retrieving mouse speed

    Quote Originally Posted by boops boops View Post
    <snip> I'm not sure whether I need to structure the Sub into a Get and a Set version for my present purposes since ByRef seems to work fine in both cases.
    I was going to post earlier but my answer was pretty much the same as bergerkiller's. I'm pretty sure ByRef does not work in both cases, at least it does not work with the equivalent C# code.

    Check the return value of SystemParametersInfo, I think you will find using ByRef to set will return 0. It's expecting a value not an address.
    W o t . S i g

  5. #5
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: [RESOLVED] Retrieving mouse speed

    Yep, you need to use ByVal for the SET functions to work. In the documentation it says "inout", meaning the function can return a value or a value can be passed to the function. Since the function has only one possible output, I made the following "property function" for it, to simplify it all:

    vb Code:
    1. <System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint:="SystemParametersInfo")> _
    2.         Private Shared Function SystemParametersInfoGet(ByVal uAction As SPI.Action, ByVal uParam As Int32, ByRef pvParam As IntPtr, ByVal fuWinIni As Int32) As Int32
    3.         End Function
    4.         <System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint:="SystemParametersInfo")> _
    5.         Private Shared Function SystemParametersInfoSet(ByVal uAction As SPI.Action, ByVal uParam As Int32, ByVal pvParam As IntPtr, ByVal fuWinIni As Int32) As Int32
    6.         End Function
    7.         Public Enum Action As Int32
    8.             GETMOUSESPEED = &H70
    9.             SETMOUSESPEED = &H71
    10.             GETKEYBOARDSPEED = &HA
    11.             SETKEYBOARDSPEED = &HB
    12.         End Enum
    13.         Public Shared Property SystemParametersInfo(ByVal uAction As SPI.Action, ByVal uParam As Int32, ByVal fuWinIni As Int32) As IntPtr
    14.             Get
    15.                 Dim rval As IntPtr
    16.                 SystemParametersInfoGet(uAction, uParam, rval, fuWinIni)
    17.                 Return rval
    18.             End Get
    19.             Set(ByVal value As IntPtr)
    20.                 SystemParametersInfoSet(uAction, uParam, value, fuWinIni)
    21.             End Set
    22.         End Property

    It's a nice alternative to using the two functions.Action names starting with SET need to be set, GET need to be returned by the property.

    I am not sure, but it could be that SET = GET + 1, so you could do uAction + 1 in the Set of the property. And then you can remove all SET commands from the Action enumeration and remove the GET_ prefix:

    vb Code:
    1. Public Enum Action As Int32
    2.             MOUSESPEED = &H70
    3.             KEYBOARDSPEED = &HA
    4.         End Enum
    5.         Public Shared Property SystemParametersInfo(ByVal uAction As SPI.Action, ByVal uParam As Int32, ByVal fuWinIni As Int32) As IntPtr
    6.             Get
    7.                 Dim rval As IntPtr
    8.                 SystemParametersInfoGet(uAction, uParam, rval, fuWinIni)
    9.                 Return rval
    10.             End Get
    11.             Set(ByVal value As IntPtr)
    12.                 SystemParametersInfoSet(uAction + 1, uParam, value, fuWinIni)
    13.             End Set
    14.         End Property

    EDIT

    Ow and you could also divide the two enumerations to two types: one for SET and one for GET.

  6. #6

    Thread Starter
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: [RESOLVED] Retrieving mouse speed

    You are both right: there must be 2 subs. I understand next to nothing about APIs -- for example I don't understand how a function can do something when it doesn't have any code in it. So I should be more careful about speculating without checking. BB

  7. #7
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,974

    Re: [RESOLVED] Retrieving mouse speed

    API functions in your project don't have any code in them because they aren't really functions, they are just info about how to call functions that exist in external files, including the file name ("User32.dll"), the function name (EntryPoint:="SystemParametersInfo"), and the parameters (on the Function line).

    The syntax for declaring API's is one of just a few where the syntax is worse than VB6, which made it clearer.

  8. #8
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: [RESOLVED] Retrieving mouse speed

    Quote Originally Posted by si_the_geek View Post
    The syntax for declaring API's is one of just a few where the syntax is worse than VB6, which made it clearer.
    Why doesn't VB10 have an API Viewer app like VB6?

    I find it hard to use VB6 now after close to 8 months of playing around with VB10, a lot of things are so much easier, but when it comes to API...

  9. #9
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,974

    Re: [RESOLVED] Retrieving mouse speed

    A large percentage of things are built-into the .Net framework, so it isn't as useful as it was to VB6 people.

    I generally use the official API documentation on MSDN (which often contains VB.Net examples at the bottom of the page), as you can be fairly sure that it is accurate and complete.

    I also find http://www.pinvoke.net/ useful, and they have an addin for Visual Studio too.

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