Skip to content

Instantly share code, notes, and snippets.

@sba923
Last active February 26, 2024 15:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sba923/7ea3d013b1f758a947eea6c2e4f89f73 to your computer and use it in GitHub Desktop.
Save sba923/7ea3d013b1f758a947eea6c2e4f89f73 to your computer and use it in GitHub Desktop.
Utilities to help working with Sysinternals ZoomIt
# this is one of Stéphane BARIZIEN's public domain scripts
# the most recent version can be found at:
# https://gist.github.com/sba923/7ea3d013b1f758a947eea6c2e4f89f73#file-get-zoomithelp-ps1
<#
.SYNOPSIS
Show help for ZoomIt functions, with currently configured hotkeys
.DESCRIPTION
This script outputs help information the ZoomIt functions
that can be accessed via keyboard and/or mouse.
It calls Get-ZoomItOption.ps1 to extract information from the registry.
It outputs warnings about hotkeys that might be problematic to use or remember
e.g., because they might override AltGr+key combinations or because the main function
is Shift+something and another function is Shift+that function.
.PARAMETER SortByFunction
Sort the objects by 'Function'.
If not specified, help is output in logical functional groups.
.PARAMETER OnlyShowWarnings
If specified, only outputs (via Write-Host) warnings about hotkeys that might be problematic.
.INPUTS
None
.OUTPUTS
An array of PSCustomObject's with properties 'Function' and 'HelpText'
.EXAMPLE
PS> Get-ZoomItHelp.ps1
WARNING: hotkey for 'Record window' is 'Ctrl+Alt+(', will override 'AltGr+('
WARNING: hotkey for 'Save screen region' is 'Ctrl+R'
Function HelpText
-------- --------
Zoom toggle Ctrl+& [user-configurable]
Copy screen during zoom Ctrl+C
Save screen during zoom Ctrl+S
Copy screen region during zoom Ctrl+Shift+C
Save screen region during zoom Ctrl+Shift+S
Live Zoom toggle Ctrl+' [user-configurable]
Live Zoom zoom-in Ctrl+Up
Live Zoom zoom-out Ctrl+Down
Change pen width / font size Ctrl+<mousewheel>, Up, Down
Set pen color R (red) G (green) B (blue) O (orange) Y (yellow) P (pink) X (blur)
Translucent highlighter color Shift+<color key [RGBOYP]>
Draw line Shift+<mouse>
Draw rectangle Ctrl+<mouse>
Draw ellipse Tab+<mouse>
Draw arrow Ctrl+Shift+<mouse>
Draw text t
Draw right-aligned text Shift+t
Clear screen W (white) K (black)
Draw without zoom Ctrl+é [user-configurable]
Enter timer mode Ctrl+" [user-configurable]
Record screen Ctrl+( [user-configurable]
Record screen region Ctrl+Shift+( [user-configurable]
Record window Ctrl+Alt+( [user-configurable]
Copy screen region Ctrl+Shift+R [user-configurable]
Save screen region Ctrl+R [user-configurable]
Undo Ctrl+Z
Erase E
Exit drawing mode RightClick
#>
param([switch]$SortByFunction, [switch]$OnlyShowWarnings)
# Add help entries from array of hashtables (for non-configurable functions)
function Get-HelpEntries([hashtable[]]$HelpEntries)
{
$HelpEntries | Foreach-Object {
$helpentry = $_
if ($helpentry.Keys.Count -ne 1)
{
throw "INTERNAL ERROR: Get-HelpEntries needs array of single-key hashtable"
}
foreach ($key in $helpentry.Keys)
{
[PSCustomObject]@{
Function = $key
HelpText = $helpentry[$key]
}
}
}
}
# Add help for a hotkey
# This rewrites the string representation for a hotkey
# 1. account for duplicate modifiers e.g., Shift+Ctrl+Shift+R becomes Ctrl+R (with a warning)
# 2. sort modifiers in Ctrl, Alt, Shift order
function Get-HelpForConfigurableFunction([Parameter(Mandatory = $true)][string] $Function, [Parameter(Mandatory = $true)][string]$HotkeyString)
{
# parse the string
if ($HotkeyString -match '^(.*)\+([^\+]+\+$)')
{
$tokens = $Matches[1] -split '\+'
$tokens += , $Matches[2]
}
else
{
$tokens = $HotkeyString -split '\+'
}
# extract the character
$character = $tokens[$tokens.Count - 1]
$modifiers = $tokens[0..($tokens.Count - 2)]
$newmodifiers = @()
$warning = $false
$modifiers | Group-Object | Foreach-Object {
if ($_.Count -eq 1)
{
$newmodifiers += $_.Name
}
elseif ($_.Count -eq 2)
{
$warning = $true
$null = $warning # $null assignment to avoid PSSA 'not used' warning
}
else
{
throw "INTERNAL ERROR: cannot have more than 2 occurrences of modifier: {0}" -f $HotkeyString
}
}
$newhotkeystring = (($newmodifiers | Sort-Object -Property { "CtrlAltShift".IndexOf($_) }) -join '+') + '+' + $character
if ($warning)
{
Write-Host -ForegroundColor Magenta ("WARNING: hotkey for '{0}' is '{1}'" -f $Function, $newhotkeystring)
}
# warn if Ctrl+Alt+<not a letter>, will override AltGr+<key>
if ($newhotkeystring -match 'Ctrl\+Alt\+(?:.*\+|)([^a-z])$')
{
Write-Host -ForegroundColor Magenta ("WARNING: hotkey for '{0}' is '{1}', will override 'AltGr+{2}'" -f $Function, $newhotkeystring, $Matches[1])
}
[PSCustomObject] @{
Function = $Function
HelpText = $newhotkeystring + ' [user-configurable]'
}
}
# create help for ZoomIt functions, either fixed or extracted from the registry via Get-ZoomItOption.ps1
#TODO error handling e.g., Get-ZoomItOption.ps1 not found or fails
$zoomitoptions = Get-ZoomItOption.ps1
$help = @()
$help += Get-HelpForConfigurableFunction -Function 'Zoom toggle' -HotkeyString $zoomitoptions.ToggleKey
$help += Get-HelpEntries -HelpEntries @(
@{'Copy screen during zoom' = 'Ctrl+C' }
@{'Save screen during zoom' = 'Ctrl+S' }
@{'Copy screen region during zoom' = 'Ctrl+Shift+C' }
@{'Save screen region during zoom' = 'Ctrl+Shift+S' }
)
$help += Get-HelpForConfigurableFunction -Function 'Live Zoom toggle' -HotkeyString $zoomitoptions.LiveZoomToggleKey
$help += Get-HelpEntries -HelpEntries @(
@{'Live Zoom zoom-in' = 'Ctrl+Up' }
@{'Live Zoom zoom-out' = 'Ctrl+Down' }
@{'Change pen width / font size' = 'Ctrl+<mousewheel>, Up, Down' }
@{'Set pen color' = 'R (red) G (green) B (blue) O (orange) Y (yellow) P (pink) X (blur)' }
@{'Translucent highlighter color' = 'Shift+<color key [RGBOYP]>' }
@{'Draw line' = 'Shift+<mouse>' }
@{'Draw rectangle' = 'Ctrl+<mouse>' }
@{'Draw ellipse' = 'Tab+<mouse>' }
@{'Draw arrow' = 'Ctrl+Shift+<mouse>' }
@{'Draw text' = 't' }
@{'Draw right-aligned text' = 'Shift+t' }
@{'Clear screen' = 'W (white) K (black)' }
)
$help += Get-HelpForConfigurableFunction -Function 'Draw without zoom' -HotkeyString $zoomitoptions.DrawToggleKey
$help += Get-HelpForConfigurableFunction -Function 'Enter timer mode' -HotkeyString $zoomitoptions.BreakTimerKey
$help += Get-HelpForConfigurableFunction -Function 'Record screen' -HotkeyString $zoomitoptions.RecordToggleKey
$help += Get-HelpForConfigurableFunction -Function 'Record screen region' -HotkeyString ('Shift+' + $zoomitoptions.RecordToggleKey)
$help += Get-HelpForConfigurableFunction -Function 'Record window' -HotkeyString ('Alt+' + $zoomitoptions.RecordToggleKey)
$help += Get-HelpForConfigurableFunction -Function 'Copy screen region' -HotkeyString $zoomitoptions.SnipToggleKey
$help += Get-HelpForConfigurableFunction -Function 'Save screen region' -HotkeyString ('Shift+' + $zoomitoptions.SnipToggleKey)
$help += Get-HelpEntries -HelpEntries @(
@{'Undo' = 'Ctrl+Z' }
@{'Erase' = 'E' }
@{'Exit drawing mode' = 'RightClick' }
)
if (!$OnlyShowWarnings)
{
# output 'as is' or sorted by function name
if (!$SortByFunction)
{
$help
}
else
{
$help | Sort-Object -Property 'Function'
}
}
# this is one of Stéphane BARIZIEN's public domain scripts
# the most recent version can be found at:
# https://gist.github.com/sba923/7ea3d013b1f758a947eea6c2e4f89f73#file-get-zoomitoption-ps1
<#
.SYNOPSIS
Get ZoomIt configuration information from the registry
.DESCRIPTION
This extracts the configuration information for ZoomIt from the registry in human-usable form
.INPUTS
None
.OUTPUTS
A PSCustomObject whose properties are the registry values under HKEY_CURRENT_USER\Software\Sysinternals\ZoomIt,
some of which (e.g., Font, hotkeys, PenColor) are rewritten to be human-usable.
#>
#TODO error handling e.g., if ZoomIt has never been run (registry entries not present)
$_ZoomItOptionWin32TypeName = "ZoomItOptionWin32"
# # avoid an error if sourcing the script multiple times e.g., when debugging in VScode
# if (-not ([System.Management.Automation.PSTypeName]$_ZoomItOptionWin32TypeName).Type)
# {
$_ZoomItOptionWin32Type = Add-Type -MemberDefinition @"
[DllImport("user32.dll")]
public static extern int MapVirtualKeyEx(int uCode, int uMapType, int dwhkl, ref uint lpChar, int uFlags);
"@ -Name $_ZoomItOptionWin32TypeName -Namespace "User32" -PassThru
# }
# else
# {
# Write-Host -ForegroundColor 'Magenta' ("Type '{0}' already defined" -f $_ZoomItOptionWin32TypeName)
# }
function Convert-KeycodeToString([int]$Keycode)
{
$modifier = ""
if (($Keycode -band 0x200) -ne 0)
{
$modifier = "Ctrl+" + $modifier
}
if (($Keycode -band 0x400) -ne 0)
{
$modifier = "Alt+" + $modifier
}
if (($Keycode -band 0x100) -ne 0)
{
$modifier = "Shift+" + $modifier
}
# $scanCode = 0
# $keyboardState = New-Object byte[] 256
$charBuffer = New-Object char[] 1
# $bufferSize = $charBuffer.Length
$flags = 0
$layout = [System.Globalization.CultureInfo]::CurrentCulture.KeyboardLayoutId
$char = $_ZoomItOptionWin32Type::MapVirtualKeyEx($Keycode -band 0xFF, 2, $layout, [ref]$charBuffer[0], $flags)
if (($Keycode -band 0xF0) -eq 0x60)
{
$modifier + 'NumPad' + [char]$char
}
else
{
$modifier + [char]$char
}
}
$zoomitoptions = Get-ItemProperty 'HKCU:\Software\Sysinternals\ZoomIt'
# convert keycodes to human-readable strings
$zoomitoptions.PSObject.Properties.Name -match 'Key$' | Foreach-Object {
$optionname = $_
$zoomitoptions.$optionname = (Convert-KeycodeToString -Keycode $zoomitoptions.$optionname)
}
# convert pen color to #nnnnnn hex value
$zoomitoptions.PenColor = "#{0:x6}" -f $zoomitoptions.PenColor
# convert fontname to string
$zoomitoptions.Font = [System.Text.Encoding]::Unicode.GetString($zoomitoptions.Font[28..($zoomitoptions.Font.Count - 1)])
$zoomitoptions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment