Swap Mouse Buttons and Restore Mouse Button State
Posted: 07 Mar 2019, 14:15
I'm regularly switching the mouse between my left and right hand. For a very long time I used a tiny free utility to do that, but recently it looked like it had stopped working, so I decided to write one using AutoHotKey. When I wrote it, I found out that my script was behaving the same way as the utility and that the issue was, most likely, related to a bad driver behaviour under Windows 10 when the computer is unlocked and or wakes up from sleep.
So, I decided to update my script to correct that. Hope that it could be of use to somebody else!
All comments and suggestions are welcome!
P.S. The script is based on two forum posts from the archived AHK forums. I'm not sure whether I'm allowed to post links or not, so I didn't include them, but I'll gladly post the links to these posts if this is allowed!
So, I decided to update my script to correct that. Hope that it could be of use to somebody else!
All comments and suggestions are welcome!
Code: Select all
; AutoHotKey code to swap the buttons of the mouse and restore the previous state
;
; Under Windows 10, some drivers (Synaptics) might reset the mouse to right-handed when the computer is unlocked or
; awaken from suspended state.
; To correct this, two messages are being monitored by the script and the mouse buttons' state is restored after
; these events.
;
; Version: 0.1
; Date: 2019-03-07
; Windows messages to monitor
msg_WM_WTSSESSION_CHANGE = 0x2b1
msg_WM_POWERBROADCAST = 0x218
; Registry key and value to store the state of the mouse buttons
reg_KeyName = HKEY_CURRENT_USER\SessionInformation
reg_ValueName = LeftHandedMouse
; Set taskbar tray icon
Menu, Tray, Icon, shell32.dll, 44 ; Gold star icon
Menu, Tray, Tip, Swap Mouse Buttons
; Initialize
; Create an invisile window which is registered to receive WTSRegisterSessionNotification notifications (for lock and unlock messages)
; and RegisterPowerSettingNotification notifications (for suspend and wake-up messages)
Gui,+LastFound
hwnd:=WinExist()
; Register the window for WTSRegisterSessionNotification notifications in order to receive the WM_WTSSESSION_CHANGE messages
DllCall("Wtsapi32.dll\WTSRegisterSessionNotification","UInt",hwnd,"UInt",0)
; Register the window for RegisterPowerSettingNotification notification in order to receive the WM_POWERBROADCAST messages
; hHandle is set to the hidden window
; PowerSettingGuid is set to GUID_SYSTEM_AWAYMODE
; Flags is 0 (DEVICE_NOTIFY_WINDOW_HANDLE) to register for notifications sent using WM_POWERBROADCAST messages
DllCall("User32.dll\RegisterPowerSettingNotification",hwnd,"98a7f580-01f7-48aa-9c0f-44352c29e5C0",0)
; Register function to recieive the WM_WTSSESSION_CHANGE messages
OnMessage(msg_WM_WTSSESSION_CHANGE,"f_WM_Monitor")
; Register functino to receive the WM_POWERBROADCAST messages
OnMessage(msg_WM_POWERBROADCAST,"f_WM_Monitor")
; Set the mouse to the last known state
RegRead, buttonState, %reg_KeyName%, %reg_ValueName%
if (ErrorLevel) ; Reistry value not found
{
buttonState := DllCall("user32.dll\SwapMouseButton", "UInt", 1) ; Set left-handed mouse
if buttonState <> 0 ; If the result is non-zero, the mouse was set to left-handed before the above DLL call
{
buttonState := 1
}
RegWrite, REG_DWORD, %reg_KeyName%, %reg_ValueName%, %buttonState%
}
tmpInt := DllCall("user32.dll\SwapMouseButton", "UInt", buttonState)
Return
; Use F12 to swap the mouse buttons
; Show tool tip and store the status in the registry
F12::
buttonState := DllCall("user32.dll\SwapMouseButton", "UInt", 1) ; Set left-handed mouse
if buttonState <> 0 ; If the result is non-zero, the mouse was set to left-handed before the above DLL call
{
buttonState := 0
tmpInt := DllCall("user32.dll\SwapMouseButton", "UInt", 0) ; Set right-handed mouse
ToolTip, Right Handed
}
else
{
buttonState := 1
ToolTip, Left Handed
}
RegWrite, REG_DWORD, %reg_KeyName%, %reg_ValueName%, %buttonState%
SetTimer, tRemoveToolTip, -3000 ; Whith negative period, the timer will run only once
Return
; Function to monitor the WM_WTSSESSION_CHANGE and WM_POWERBROADCAST messages
f_WM_Monitor(wParam, lParam, msg)
{
Global reg_KeyName, reg_ValueName
Global msg_WM_WTSSESSION_CHANGE, msg_WM_POWERBROADCAST
; Lock or Suspend
if ((msg = msg_WM_WTSSESSION_CHANGE and wParam = 7) or (msg = msg_WM_POWERBROADCAST and wParam = 4))
{
; Get mouse buttons' state and store it in the registry. Required if the mouse buttons were swapped using the
; Control Panel and not by using the script
buttonState := DllCall("user32.dll\SwapMouseButton", "UInt", 1) ; Note: Sets left-handed mouse
if buttonState <> 0 ; If the result is non-zero, the mouse was set to left-handed before the above DLL call
RegWrite, REG_DWORD, %reg_KeyName%, %reg_ValueName%, 1
else
RegWrite, REG_DWORD, %reg_KeyName%, %reg_ValueName%, 0
}
; Unlock
if ((msg = msg_WM_WTSSESSION_CHANGE and wParam = 8) or (msg = msg_WM_POWERBROADCAST and wParam = 7))
{
; Synaptics driver and Windows 10 issues might reset the mouse buttons to right-handed mouse after unlock/wake-up
; The timer is to make sure that the state of the mouse buttons is set to what it was before the computer was locked/suspended
SetTimer, tSetMouseButtons, -1000 ; With negarive period, the timer will run only once
}
}
; Timers
tRemoveToolTip:
ToolTip
Return
tSetMouseButtons:
RegRead, buttonState, %reg_KeyName%, %reg_ValueName%
tmpInt := DllCall("user32.dll\SwapMouseButton", "UInt", buttonState)
Return