-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSet-Mouse.ps1
More file actions
360 lines (309 loc) · 14.2 KB
/
Set-Mouse.ps1
File metadata and controls
360 lines (309 loc) · 14.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
<# TODOs:
#TODO: Investigate UserPreferences more
#TODO: Add SonarOff and Trails Off command
#TODO: Add more examples
#TODO: Allow choosing User Defined Cursor Schemes (scheme source other than 0)
#TODO: ScrollLines doesn't appear to work until you change windows, display a warning
#TODO: Add authour information, etc
#TODO: For gods sake, COMMENT YOUR CODE!!!!
#TODO: Do something with the get-mouse function
#TODO: Stop the system call displaying True/False (either | Out-Null or check it and do error handling)
Although be aware that calling setcursor with both SendChange and UpdateIniFile set will return
false but still work (well apart from the cursor size). Selecting only one of them will return
true, so not holding out for much there
#TODO: why won;t cursor size work?
#TODO: Just noticed, cursors set using Ease of Access in Settings actually have a _eoa suffix and are in
%LocalAppData%\Microsoft\Windows\Cursors instead of %WinDir%\Cursors, they also have modified times
of only a few hours ago. Could they be dynamically generated by Ease of Access when you select the
size (it would explain the delay)
#TODO: Add -UseEOACursors option to use the _eoa.cur files. No handy registry entry with a list of these files
though, so you will have to manually create a seperate CURSOR_NAMES array (has more cursors) and hard-code
the file name (they are in %LocalAppData%\Microsoft\Windows\Cursors)
#TODO: Find a way to not Hard-code the CURSOR_NAMES array
#TODO: When writing pairs to registry in CursorScheme, do a check to make sure the two arrays are they same size
I'm not doing it now just for ease of debugging surprisingly
#TODO: Change the number of files to remove from raw SchemeFiles to a constant
#TODO: Create an option to set Text Indicator:
Reg Location: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Accessibility\CursorIndicator
Set Colour Key: IndicatorColor (RGB Hex nice purple is 0xff00bf)
Set size Key: IndicatorType int 1-5
#TODO: Create a Set-Font function to set windows font sizes and weights for Windows
Titles, Status Bars, Menus, Icons, Messages, etc
#TODO: Upload this to github
#TODO: How do I set Workspace titles?
#>
<#
.SYNOPSIS
Sets mouse parameters.
.DESCRIPTION
Sets the mouse speed, cursor scheme, mouse trails,
scroll lines and sonar (effect on pressing ctrl)
via the SystemParametersInfo and stores the speed
in the registry
.PARAMETER Speed
Integer between 1 (slowest) and 20 (fastest).
.PARAMETER ScrollLines
Integer between -1 (slowest) and 100.
.PARAMETER MouseTrailsOn
Switch to turn Mouse Trails on
.PARAMETER MouseTrailsLength
Imteger between 2 and 15 (longest) for length of trail
.PARAMETER MouseSonarOn
Switch to turn on Mouse Sonar (Find cursor by pressing the ctrl key)
.PARAMETER CursorScheme
String Name of Cursor Scheme to use (Validated against default windows schemes listed in registry)
.PARAMETER CursorSize
Integer between 1 and 15 of cursor size to use
.EXAMPLE
Sets the mouse speed to the value 10.
PS C:\> Set-Mouse -Speed 10
.EXAMPLE
Sets the mouse WheelScrollLines to the value 5.
PS C:\> Set-Mouse -ScrollLines 5
.EXAMPLE
Turn on Mouse Trails and set them to longest
PS C:\> Set-Mouse -MouseTrailsOn -MouseTrailsLength 15
.EXAMPLE
Turn on the Mouse Sonar feature (find cursor by tapping ctrl key)
PS C:\> Set-Mouse -MouseSonarOn
.INPUTS
System.int
.NOTES
See Get-Mouse also.
.LINK
about_functions_advanced
.LINK
about_comment_based_help
.LINK
https://msdn.microsoft.com/en-us/library/ms724947(v=VS.85).aspx
.LINK
https://github.com/raevilman/windows-scripts/edit/master/mouse/speed/ps_scripts/MouseSpeed.ps1
.LINK
https://www.strichnet.com/edit-and-apply-registry-settings-via-powershell/
.LINK
http://thecomputermanagersden.blogspot.com/2014/05/powershell-script-to-customize-windows.html
.LINK
https://devblogs.microsoft.com/scripting/use-powershell-to-change-the-mouse-pointer-scheme/
.LINK
https://stackoverflow.com/questions/60104778/change-and-update-the-size-of-the-cursor-in-windows-10-via-powershell
.LINK
https://stackoverflow.com/questions/41713827/programmatically-change-custom-mouse-cursor-in-windows
.LINK
https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/writing-registry-key-default-values
.LINK
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7
#>
#common constants
if (-NOT (Test-Path variable:SPI_SETMOUSETRAILS))
{
New-Variable -Name SPI_SETMOUSETRAILS -Value ([Int]0x005D) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SPI_SETMOUSESONAR))
{
New-Variable -Name SPI_SETMOUSESONAR -Value ([Int]0x101D) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SPI_SETCURSORS))
{
New-Variable -Name SPI_SETCURSORS -Value ([Int]0x0057) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SPI_SETMOUSESPEED))
{
New-Variable -Name SPI_SETMOUSESPEED -Value ([Int]0x0071) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SPI_SETWHEELSCROLLLINES))
{
New-Variable -Name SPI_SETWHEELSCROLLLINES -Value ([Int]0x0069) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:TRAILS_OFF))
{
New-Variable -Name TRAILS_OFF -Value ([Int]0) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SPIF_UPDATEINIFILE))
{
New-Variable -Name SPIF_UPDATEINIFILE -Value ([Int]0x01) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SPIF_SENDCHANGE))
{
New-Variable -Name SPIF_SENDCHANGE -Value ([Int]0x02) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:WINDOWS_DEFAULT_SCHEME))
{
New-Variable -Name WINDOWS_DEFAULT_SCHEME -Value ([Int]0) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:USER_SCHEME))
{
New-Variable -Name USER_SCHEME -Value ([Int]1) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:SYSTEM_SCHEME))
{
New-Variable -Name SYSTEM_SCHEME -Value ([Int]2) -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:REG_PATH_MOUSE))
{
New-Variable -Name REG_PATH_MOUSE -Value ([String]"Registry::HKEY_CURRENT_USER\Control Panel\Mouse") -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:REG_PATH_CURSORS))
{
New-Variable -Name REG_PATH_CURSORS -Value ([String]"Registry::HKEY_CURRENT_USER\Control Panel\Cursors") -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:REG_PATH_ACCESSIBILITY))
{
New-Variable -Name REG_PATH_ACCESSIBILITY -Value ([String]"Registry::HKEY_CURRENT_USER\Software\Microsoft\Accessibility") -Option Constant -Scope Script
}
if (-NOT (Test-Path variable:REG_PATH_CURSOR_SCHEMES))
{
New-Variable -Name REG_PATH_CURSOR_SCHEMES -Value ([String]"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cursors\Schemes") -Option Constant, AllScope
}
if (-NOT (Test-Path variable:REG_PATH_DESKTOP))
{
New-Variable -Name REG_PATH_DESKTOP -Value ([String]"Registry::HKEY_CURRENT_USER\Control Panel\Desktop") -Option Constant, AllScope
}
if (-NOT (Test-Path variable:MOUSE_SONAR_ARRAY_INDEX))
{
New-Variable -Name MOUSE_SONAR_ARRAY_INDEX -Value ([Int]1) -Option Constant, AllScope
}
if (-NOT (Test-Path variable:MOUSE_SONAR_BITMASK))
{
New-Variable -Name MOUSE_SONAR_BITMASK -Value ([Int]64) -Option Constant, AllScope
}
#if (-NOT (Test-Path variable:CURSOR_NAMES))
#{
[String[]]$CURSOR_NAMES = @("Arrow", "Help", "AppStarting", "Wait", "Crosshair", "IBeam", "NWPen", "No", "SizeNS", "SizeWE", "SizeNWSE", "SizeNESW", "SizeAll", "UpArrow", "Hand", "Pin", "Person")
#}
#validation check to make sure a valid theme/scheme name is used (doesn;t include user defined schemes
#but easy enough just make another array of user scheems, add arrays together (just use +) amd return the result)
Class CursorSchemes : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues() {
$CursorSchemes = (Get-Item -Path "$Script:REG_PATH_CURSOR_SCHEMES" |
Select-Object -ExpandProperty Property)
return [String[]] $CursorSchemes
}
}
function Set-Mouse() {
[cmdletbinding()]
Param(
[ValidateRange(1, 20)]
[Int]
$Speed,
[ValidateRange(0, 100)]
[Int]
$ScrollLines,
[Switch]
$MouseTrailsOn,
[ValidateRange(2, 15)]
[Int]
$MouseTrailsLength=15,
[Switch]
$MouseSonarOn,
[String]
[ValidateNotNullOrEmpty()]
[ValidateSet([CursorSchemes],ErrorMessage="Scheme '{0}' does not exist. Possible values are: {1}")]
$CursorScheme,
[ValidateRange(1, 150)]
[Int]
$CursorSize
)
$MethodDefinition = @"
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni);
"@
$User32 = Add-Type -MemberDefinition $MethodDefinition -Name "User32Set" -Namespace Win32Functions -PassThru
Write-Verbose "Speed: [$Speed]"
Write-Verbose "ScrollLines: [$ScrollLines]"
Write-Verbose "CursorScheme: [$CursorScheme]"
Write-Verbose "CursorSize: [$CursorSize]"
Write-Verbose "MouseTrailsOn: [$MouseTrailsOn]"
Write-Verbose "MouseTrailsLength: [$MouseTrailsLength]"
Write-Verbose "MouseSonarrOn: [$MouseSonarOn]"
Write-Verbose ("Parameters: [" + ($PSBoundParameters.GetEnumerator().ForEach({ "$($_.Key)=$($_.Value)" })) + "]")
if ($PSBoundParameters.ContainsKey('Speed')) {
Write-Verbose "Setting new mouse speed: [$Speed]"
Set-ItemProperty -Path "$REG_PATH_MOUSE" -Name MouseSensitivity -Value $Speed
$User32::SystemParametersInfo($SPI_SETMOUSESPEED, 0, $Speed, $SPIF_UPDATEINIFILE -bor $SPIF_SENDCHANGE)
}
if ($PSBoundParameters.ContainsKey('ScrollLines')) {
Write-Verbose "Setting new mouse scrollLines: [$ScrollLines]"
Set-ItemProperty -Path "$REG_PATH_MOUSE" -Name WheelScrollLines -Value $ScrollLines
$User32::SystemParametersInfo($SPI_SETWHEELSCROLLLINES, $ScrollLines, $null, $SPIF_UPDATEINIFILE -bor $SPIF_SENDCHANGE)
}
if ($PSBoundParameters.ContainsKey('CursorScheme')) {
Write-Verbose "Setting new cursor scheme: [$CursorScheme]"
Set-Item -Path "$REG_PATH_CURSORS" -Value $CursorScheme
Set-ItemProperty -Path "$REG_PATH_CURSORS" -Name "Scheme Source" -Value $SYSTEM_SCHEME
[System.Collections.ArrayList]$SchemeFiles = (Get-ItemPropertyValue -Path "$REG_PATH_CURSOR_SCHEMES" -Name "$CursorScheme").Split(',')
#Last two elements are not points, but dll calls or something
$SchemeFiles.RemoveRange(($SchemeFiles.Count - 2),2)
Write-Verbose "Number of Cursor Files: [$($SchemeFiles.Count)]"
Write-Verbose "Number of Cursor Names: [$($CURSOR_NAMES.length)]"
#now write the pairs to the registry
for ($i = 0; $i -lt $SchemeFiles.Count ; $i++) {
Write-Verbose "Setting Cursor $($i + 1)/$($SchemeFiles.Count): [$($CURSOR_NAMES[$i])] = [$($SchemeFiles[$i])]"
Set-ItemProperty -Path "$REG_PATH_CURSORS" -Name "$($CURSOR_NAMES[$i])" -Value "$($SchemeFiles[$i])"
}
$User32::SystemParametersInfo($SPI_SETCURSORS, 0, $null, $SPIF_UPDATEINIFILE -bor $SPIF_SENDCHANGE)
}
if ($PSBoundParameters.ContainsKey('CursorSize')) {
Write-Verbose "Setting new cursor size: [$CursorSize]"
Set-ItemProperty -Path "$REG_PATH_ACCESSIBILITY" -Name "CursorSize" -Value $CursorSize
#CursorBaseSize is a hex value 0x00000X00 where X is Cursorsize +1 bitshifted (so 15 is 0x00001000 as a bad example)
$BaseSize="0x" + (($CursorSize+1) | Format-Hex).HexBytes.Replace('00', '').Replace(' ', '').PadRight(3,'0')
Write-Verbose "Setting new cursor base size: [$BaseSize]"
Set-ItemProperty -Path "$REG_PATH_CURSORS" -Name "CursorBaseSize" -Value $BaseSize
$User32::SystemParametersInfo($SPI_SETCURSORS, 0, $null, $SPIF_SENDCHANGE)
}
if ($PSBoundParameters.ContainsKey('MouseTrailsOn')) {
Write-Verbose "Mouse Trails are activated with a length of [$MouseTrailsLength]"
Set-ItemProperty -Path "$REG_PATH_MOUSE" -Name "MouseTrails" -Value $MouseTrailsLength
$User32::SystemParametersInfo($SPI_SETMOUSETRAILS, $MouseTrailsLength, $null, $SPIF_UPDATEINIFILE -bor $SPIF_SENDCHANGE)
}
if ($PSBoundParameters.ContainsKey('MouseSonarOn')) {
Write-Verbose "Mouse Sonar is activated."
$UserPrefs = Get-ItemPropertyValue -Path "$REG_PATH_DESKTOP" -Name "UserPreferencesMask"
<# The value is actually Big Endian, so we should reverse it, but that would just mean a different
bit needs setting, so I've cheated and just pretended it's little endian #>
$UserPrefs[$MOUSE_SONAR_ARRAY_INDEX] = $UserPrefs[$MOUSE_SONAR_ARRAY_INDEX] -bor $MOUSE_SONAR_BITMASK
Set-ItemProperty -Path "$REG_PATH_DESKTOP" -Name "UserPreferencesMask" -Value "$UserPrefs"
$User32::SystemParametersInfo($SPI_SETMOUSESONAR, 0, $true, $SPIF_UPDATEINIFILE -bor $SPIF_SENDCHANGE)
}
}
<#
.SYNOPSIS
Gets the mouse settings.
.DESCRIPTION
Gets the mouse settings via the SystemParametersInfo
.EXAMPLE
Gets the current mouse
PS C:\> Get-Mouse
.Outputs
System.int
.NOTES
See Set-Mouse also.
.LINK
about_functions_advanced
.LINK
about_comment_based_help
.LINK
https://msdn.microsoft.com/en-us/library/ms724947(v=VS.85).aspx
.LINK
https://github.com/raevilman/windows-scripts/edit/master/mouse/speed/ps_scripts/MouseSpeed.ps1
#>
function Get-Mouse {
[cmdletbinding()]
param()
# $SPI_GETMOUSETRAILS = 0x005E
# $SPI_GETMOUSESPEED = 0x0070
$# SPI_GETWHEELSCROLLLINES = 0x0068
$MethodDefinition = @"
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref uint pvParam, uint fWinIni);
"@
$User32 = Add-Type -MemberDefinition $MethodDefinition -Name "User32Get" -Namespace Win32Functions -PassThru
[Int32]$Speed = 0
$User32::SystemParametersInfo(0x0070, 0, [ref]$Speed, 0) | Out-Null
[Int32]$ScrollLines = 0
$User32::SystemParametersInfo(0x0068, 0, [ref]$ScrollLines, 0) | Out-Null
return [pscustomobject]@{
"speed" = $Speed;
"scrollLines" = $ScrollLines
}
}