Mouse Acceleration (Enhance Pointer Precision)
SPI_SETMOUSESPEED = 0x0070
DllCall("SystemParametersInfo", UInt, SPI_SETMOUSESPEED, UInt, 0, UInt, 10, UInt, 0)
However, I'm now trying to turn "Enhance Pointer Precision" on and off. I've been doing some half-blind searching, not really knowing what I'm looking for, but I thought I had finally figured out how to get and set the precision setting:
SPI_GETMOUSE = 0x0003
DllCall("SystemParametersInfo", UInt, SPI_GETMOUSE, UintP, Precision, UInt, 0, UInt, 0)
MsgBox, Setting is %Precision%.
SPI_SETMOUSE = 0x0004
DllCall("SystemParametersInfo", UInt, SPI_SETMOUSE, Uint, 1, UInt, 6, UInt, 10)
But neither works. SPI_GETMOUSE always returns 0 and SPI_SETMOUSE doesn't work. (Retrieving all three parameters of SPI_GETMOUSE returns 0, [blank] and 0.)
I really don't know what I'm doing here, so any help is welcome.
Assuming "mouse acceleration" is the value you're after, I think you would have to build an array of three integers using the structure steps described on the DllCall page, then pass that array via DllCall("SystemParametersInfo", ...)
If you get stuck, post again and maybe someone will try to get it working.
It took me 90 minutes of blind trial and error until something magically clicked and I was able to understand what I was supposed to be doing. Bing!
The following will turn off "Enhance pointer precision" as seen in XP's Mouse Properties > Pointer Options:
SPI_SETMOUSE = 0x0004 VarSetCapacity(MySet, 12, 0) DllCall("SystemParametersInfo", UInt, SPI_SETMOUSE, UInt, 0, Str, MySet, UInt, 1)
The value "1" in DllCall's last parameter makes sure the setting writes to the registry.
The following will set the appropriate registry keys to the default values Windows uses when you turn on "Enhance pointer precision":
SPI_SETMOUSE = 0x0004 VarSetCapacity(MySet, 12, 0) InsertInteger(6, MySet, 0) ; MouseThreshold1 InsertInteger(10, MySet, 4) ; MouseThreshold2 InsertInteger(1, MySet, 8) ; MouseSpeed InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) ; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest, ; only pSize number of bytes starting at pOffset are altered in it. { Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data. DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF) } DllCall("SystemParametersInfo", UInt, SPI_SETMOUSE, UInt, 0, Str, MySet, UInt, 1)
You can verify these settings in HKEY_CURRENT_USER/Control Panel/Mouse.
Note that MouseSpeed does not refer to "Select a pointer speed," but simply sets whether or not "Enhance pointer precision" is on (1 or 0). For "Select a pointer speed," you would refer to MouseSensitivity (in the same registry branch), which should be a number between 1 and 20.
To change that, you can use:
SPI_SETMOUSESPEED = 0x0071 MySpeed = 10 ; A number between 1-20. DllCall("SystemParametersInfo", UInt, SPI_SETMOUSESPEED, UInt, 0, UInt, MySpeed, UInt, 0)
Note also that I've only tried this on XP.
Thanks for pointing me in the right direction!
By the way, the reason I'm doing this is because I want different settings on my laptop for both my touch pad and for my mouse.
My initial solution is simply to create a shortcut that will run the script; the script will detect what the current settings are and change them to the alternate settings. I just toggle them, depending on what I want to use.
Now that my mind is going, though, I'm wondering if there's some way I can automate it by detecting the moment a mouse is plugged in, but without continually repeating SM_MOUSEPRESENT on a SetTimer. (Depending on where I and my laptop are, I may or may not bother to plug in the mouse.)
Even better, it would be nice to have the script detect which one I'm using at the time and reflect the settings accordingly. (Say, if I have the mouse plugged, but I happen to be using the touch pad, anyway.)
Regarding your other questions, if you're using a usb mouse it is possible to receive usb event notifications (plugged in/unplugged - try searching the forum for that and my user name) but no one on the forum has found a way of differentiating between input from one mouse and another (the same goes for keyboards).
Note that MouseSpeed does not refer to "Select a pointer speed," but simply sets whether or not "Enhance pointer precision" is on (1 or 0). For "Select a pointer speed," you would refer to MouseSensitivity (in the same registry branch), which should be a number between 1 and 20.
Regarding the MoiuseSpeed and Threshold parameter i found following info at MSDN:
[...]The movement is a delta in the X and Y range.
During acceleration, if the delta is larger than MouseThreshold1, it is doubled.
During acceleration, if the delta is larger than MouseThreshold1 and MouseThreshold2, and if MouseSpeed is 2, it is doubled again.
Depending on the size of the mouse movement and the settings of MouseThreshold1, MouseThreshold2, and MouseSpeed, the actual position delta will be unchanged, doubled, or quadrupled. This calculation is carried out independently for the X and Y coordinates.
Thanks, I should have mentioned that. It looks like you can actually customize the sensitivity of the acceleration, too.
evl -
I found this topic; that looks basically like what I'm looking for.
Now if I can only figure out how to detect whether it's been plugged in or unplugged.
Whoa - now that's weird. I just got another notification like I got before, but I didn't unplug the mouse. I wonder what caused that. :?: It's no good to me if it does that randomly like that ...
Yes there are a few "phantom" events, but still fairly rare and better than using a timer to check. If you check the registry you can find the device enumeration (i.e. list):
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Mouclass\Enum
I think that one should change before/after you connect the mouse - don't forget to refresh the view to see the changes in the registry editor. You can then use a registry loop to scan for the device you want (in this case, one containing "HID" (or you could use the Product ID (PID)) and Vendor ID (VID) if you want to be more specific).
Thanks for the help. If I don't have any more problems, I'll try to post what I come up with.
Review the section under "User Pointer Settings" to see what can be changed.
The Alps Touch Pad icon location is accurate for the default installation on my Dell. I made an educated guess on the Synaptics location, which I believe is used on ThinkPads. You can change them, of course.
/* AutoHotkey Version: 1.x Language: English Platform: WinXP Title: Laptop Mouse Monitor Author: Wesley Treat, www.wesleytreat.com Date: May 2006 Script Function: If a USB mouse is plugged into the laptop, optimize the pointer speed and precision settings for the mouse. If it's not, optimize the settings for the touch pad. Monitor for changes in mouse's presence. */ ; ============================================================ ; CONFIGURATION ; ============================================================ ; ------------------------------------------------------------ ; USER POINTER SETTINGS ; Mouse ID ; Check HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Mouclass\Enum ; to determine the ID of your mouse. This should be the value of the key that ; appears and disappears when you plug in and unplug your mouse. You can ; probably just use "HID." MouseID = HID ; Pointer Speed (1-20) PadSpeed = 10 MouseSpeed = 12 ; Enhance Pointer Precision PadEnhance = 1 MouseEnhance = 0 ; Precision Thresholds PadThreshold1 = 6 PadThreshold2 = 10 MouseThreshold1 = 0 MouseThreshold2 = 0 ; For details on precision and threshold settings, see ; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/cerefSystemParametersInfo.asp ; under SPI_SETMOUSE. By default, thresholds 1 and 2 are "6" and "10" respectively. ; Use a tray icon? TrayIcon = 1 ; Tray Icons ; If you want the tray icon to reflect the current settings, enter a valid ; PadIcon and PadIconGroup. To use the only standard AutoHotkey icon, comment ; out all the icon locations. MouseIcon = %A_WinDir%\system32\main.cpl MouseIconGroup = 1 ; The likely location of the Alps Touch Pad icon. ; PadIcon = %ProgramFiles%\Apoint\Apoint.exe ; PadIconGroup = 1 ; The likely location of the Synaptics Touch Pad icon. ; PadIcon = %ProgramFiles%\Synaptics\SynTP\SynTPEnh.exe ; PadIconGroup = 1 ; If you like, you can change the names for your devices. These names are ; reflected in the tooltips. MouseName = Mouse PadName = Touch Pad ; ------------------------------------------------------------ ; SCRIPT SETTINGS - YOU SHOULDN'T NEED TO CHANGE ANYTHING BELOW THIS LINE. If !TrayIcon Menu, Tray, NoIcon ; Constants ; Read more at the following: ; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp ; http://www.pinvoke.net/search.aspx?search=SPI&namespace=%5BAll%5D SPI_GETMOUSE = 0x0003 SPI_SETMOUSE = 0x0004 SPI_GETMOUSESPEED = 0x0070 SPI_SETMOUSESPEED = 0x0071 ; Watch for hardware changes OnMessage(0x219, "HardwareUpdate") ; Check whether or not the mouse exists to begin with and make sure the pointer ; settings match. Gosub, MouseCheck Gosub, ChangeSettings If !MousePresent and !FileExist(PadIcon) and FileExist(MouseIcon) Menu, Tray, Icon, %MouseIcon%, %MouseIconGroup% MouseLast = %MousePresent% ToolTip, Pointer Settings Set To: %CurrentName% Sleep, 2000 ToolTip Return Exit ; Everything above this line is run when the script is loaded. ; ============================================================ ; FUNCTIONS & SUBROUTINES ; ============================================================ HardwareUpdate() { Global MouseLast Global MousePresent Global CurrentName Gosub, MouseCheck ; We might get phantom hardware-change messages, so make sure the status ; of the mouse has actually changed before changing any settings. If MousePresent = %MouseLast% Exit Else { Gosub, ChangeSettings MouseLast = %MousePresent% ; Update mouse status. ToolTip, Pointer Settings Changed To: %CurrentName% Sleep, 2000 ToolTip } Return } MouseCheck: MousePresent = 0 Sleep, 1000 ; Give the registry a moment to update. Loop, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\Services\Mouclass\Enum, 0, 0 { RegRead, CurrentValue IfInString, CurrentValue, %MouseID% { MousePresent = 1 Break ; Don't check any more values. } } Return ChangeSettings: If MousePresent { CurrentName = %MouseName% DeviceSpeed = %MouseSpeed% DeviceEnhance = %MouseEnhance% DeviceThreshold1 = %MouseThreshold1% DeviceThreshold2 = %MouseThreshold2% If TrayIcon and FileExist(MouseIcon) Menu, Tray, Icon, %MouseIcon%, %MouseIconGroup% Menu, Tray, Tip, Current Pointer Settings: %CurrentName% } Else { CurrentName = %PadName% DeviceSpeed = %PadSpeed% DeviceEnhance = %PadEnhance% DeviceThreshold1 = %PadThreshold1% DeviceThreshold2 = %PadThreshold2% If TrayIcon and FileExist(PadIcon) Menu, Tray, Icon, %PadIcon%, %PadIconGroup% Menu, Tray, Tip, Current Pointer Settings: %CurrentName% } VarSetCapacity(DeviceArray, 12, 0) InsertInteger(DeviceThreshold1, DeviceArray, 0) ; Reg. Value MouseThreshold1 InsertInteger(DeviceThreshold2, DeviceArray, 4) ; Reg. Value MouseThreshold2 InsertInteger(DeviceEnhance, DeviceArray, 8) ; Reg. Value MouseSpeed InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) ; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest, ; only pSize number of bytes starting at pOffset are altered in it. { Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data. DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF) } ; Keep this here for future reference. ; DllCall("SystemParametersInfo", UInt, SPI_GETMOUSESPEED, UInt, 0, UIntP, SpeedCurrent, UInt, 0) ; Change the pointer speed. DllCall("SystemParametersInfo", UInt, SPI_SETMOUSESPEED, UInt, 0, UInt, DeviceSpeed, UInt, 1) ; Change the pointer precision settings. DllCall("SystemParametersInfo", UInt, SPI_SETMOUSE, UInt, 0, Str, DeviceArray, UInt, 1) Return
I tried the script, but I think it's always thinking I have a mouse hooked up. I'm using the "thinkoutside" stowaway travel mouse (bluetooth). In my registry, the HID is always there, in the same entry as the bluetooth mouse.
Can you help me?
Thanks,
Greg
Thanks,
Greg