Do I need 2 different PInvokes to Get and Set mouse speed?

前端 未结 2 544
余生分开走
余生分开走 2021-01-21 14:53

I want to get the current mouse pointer speed, and I want to set it.

To get it, I use

Public Declare Function SystemParametersInfo Lib \"user32.dll\" Ali         


        
相关标签:
2条回答
  • 2021-01-21 15:00

    The core problem is that you cannot declare an overload in VB this way because as the error message says, they cannot overload each other because there differ only by parameters declared ByRef and ByVal (you didnt mention the error). This would not happen in C# because you'd use in and out which would change the signature.

    You have several options, one is to use the Alias:

    ' declaration for all ByVal args:
    Declare Function SetSysParam Lib "user32.dll" Alias "SystemParametersInfoA"...
    
    ' one parm ByRef for getting the speed:
    Declare Function GetSysParam Lib "user32.dll" Alias "SystemParametersInfoA"...
    

    In case it is not obvious, you'd invoke them as SetSysParam and GetSysParam.

    Code Analysis/FxCop will likely complain about the way you are using these, so here is how to implement API calls so it doesnt. Start with a class named NativeMethods:

    <DllImport("user32.dll", SetLastError:=True)>
    Private Shared Function SystemParametersInfo(uiAction As SPI,
            uiParam As UInteger,
            pvParam As IntPtr,
            fWinIni As SPIF) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ' alias a ByRef version for GETting the speed, but this is not
    ' needed since NET offers a cleaner way
    <DllImport("user32.dll", EntryPoint:="SystemParametersInfo", SetLastError:=True)>
    Private Shared Function SystemParametersInfoPVByRef(uiAction As SPI,
            uiParam As UInteger,
            ByRef pvParam As IntPtr,
            fWinIni As SPIF) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
     ' other stuff for the last param
    <Flags>
     Enum SPIF
         None = &H0
         SPIF_UPDATEINIFILE = &H1
         SPIF_SENDCHANGE = &H2
         SPIF_SENDWININICHANGE = &H2
     End Enum
    
    ' there are lots and lots of Sys Params, so use an Enum to group them
    Enum SPI
        SETMOUSESPEED = &H71
        GETMOUSESPEED = &H70
    End Enum
    
    ' exposed "wrapper" for setting the value to allow a more
    ' meaningful name and hiding gory details of Msg values etc
    Friend Shared Function SetMouseSpeed(speed As Integer) As Boolean
         ' somewhat optional error checking 
         If speed < 1 Then speed = 1
         If speed > 20 Then speed = 20
    
         Return SystemParametersInfo(SPI.SETMOUSESPEED, 0, New IntPtr(speed), SPIF.None)
    End Function
    
    Friend Shared Function GetMouseSpeed() As Integer
        Dim speed As New IntPtr(0)
    
        ' the caller will have to evaluate the return to see if this
        ' succeeded
        If SystemParametersInfoPVByRef(SPI.GETMOUSESPEED, 0, speed, SPIF.None) Then
            Return speed.ToInt32
        Else
            Return -1           ' magic number that API call failed
        End If
    
    End Function
    

    One advantage to the NET format is in the return. Nearly all API calls return 0 or 1 to indicate success or failure. The MarshalAs... Boolean converts that to an Net Boolean. You can add to the class over time collecting the correct magic numbers, declarations, Enums and structures for the various Win32 API calls. It is a shared/static procedure, so it would be called as:

    NativeMethods.SetMouseSpeed(myNewSpeed)
    

    The "wrappers" not only hides the untidy details of the API from your code, it can also also work out what to do if the API call fails. In the case of getting the speed, it works out what value to return instead of the current speed if/when the call fails, something not likely be misread as a speed value (like maybe -1). As noted in the code, there is nice clean way to get the mouse speed in .NET making the overload unneeded:

    mySpeed = System.Windows.Forms.SystemInformation.MouseSpeed
    

    Finally, I should mention that it is not a good idea to unilaterally change the user's setting for the user's mouse on their system. They picked that value for a reason. If there is some good reason to do so, the original value should be restored when the app exits.

    Technical note: I ran this thru CA to make sure of the size of everything

    0 讨论(0)
  • 2021-01-21 15:19

    As a complement of @Plutonix answer I'll share all the SystemParametersInfo declarations that I needed to write in the past for various purposes.

    Usage Example:

    ' Set Mouse Speed 
    ' ( Minimum: 1, Maximum: 20 )
     SystemParametersInfo(SPI.SPI_SETMOUSESPEED, False, 15UI, SPIF.None)
    

    NOTE: I didn't fixed some of the portable warnings that throws the code-analysis tool of VS in the API DataType declarations.

    ''' <summary>
    ''' ( For setting a Boolean pvParam )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As SPI,
                  ByVal uiParam As UInteger,
                  ByVal pvParam As Boolean,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For getting a Byref Boolean pvParam )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", EntryPoint:="SystemParametersInfo", SetLastError:=True)>
    Friend Shared Function SystemParametersInfoByRefpv(
                  ByVal uiAction As SPI,
                  ByVal uiParam As UInteger,
                  ByRef pvParam As Boolean,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For setting a Boolean uiParam and Boolean pvParam parameter )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As SPI,
                  ByVal uiParam As Boolean,
                  ByVal pvParam As Boolean,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For setting a IntPtr pvParam parameter )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As SPI,
                  ByVal uiParam As UInteger,
                  ByVal pvParam As IntPtr,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For setting an UInteger uiParam and pvParam parameters )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As SPI,
                  ByVal uiParam As UInteger,
                  ByVal pvParam As UInteger,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For setting an Boolean uiParam and UInteger pvParam )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As SPI,
                  ByVal uiParam As Boolean,
                  ByVal pvParam As UInteger,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For setting a String pvParam parameter )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True, BestFitMapping:=False)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As UInteger,
                  ByVal uiParam As UInteger,
                  ByVal pvParam As String,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For reading a String pvParam parameter )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True, BestFitMapping:=False)>
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As UInteger,
                  ByVal uiParam As UInteger,
                  ByVal pvParam As StringBuilder,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    ''' <summary>
    ''' ( For setting a AnimationInfo pvParam parameter )
    ''' Retrieves or sets the value of one of the system-wide parameters.
    ''' This function can also update the user profile while setting a parameter.
    ''' </summary>
    ''' <param name="uiAction">
    ''' The system-wide parameter to be retrieved or set.
    ''' </param>
    ''' <param name="uiParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify zero for this parameter.
    ''' </param>
    ''' <param name="pvParam">
    ''' A parameter whose usage and format depends on the system parameter being queried or set. 
    ''' For more information about system-wide parameters, see the uiAction parameter. 
    ''' If not otherwise indicated, you must specify NULL for this parameter.
    ''' For information on the PVOID datatype, see Windows Data Types.</param>
    ''' <param name="fWinIni">
    ''' If a system parameter is being set, specifies whether the user profile is to be updated, 
    ''' and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to 
    ''' notify them of the change.
    ''' This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, 
    ''' or it can be one or more of the following values.
    ''' </param>
    <DllImport("user32.dll", SetLastError:=True)> _
    Friend Shared Function SystemParametersInfo(
                  ByVal uiAction As SPI,
                  ByVal uiParam As UInteger,
                  ByRef pvParam As AnimationInfo,
                  ByVal fWinIni As SPIF
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    
    0 讨论(0)
提交回复
热议问题