powershell 注册全局热键
01 前言
在处理一些重复工作问题的时候,想搞一个小工具,配合全局快捷键来提高效率。因为是Windows系统,想到C#,但是又不想用VS开发,因为那样不够灵活,没办法随时修改随时用,所以只能另寻他法。那么,不如用powershell来搞搞。
02 正文
因为涉及到全局热键,所以还是需要写一点C#,引入一些API,同时加了一个简单的窗体。
环境:Windows 11
代码如下:
<#
注册全局热键by hokis2024-04-30 21:35#>$code = @'
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;public class GlobalHotkey
{public const int MOD_ALT = 0x0001; // Alt键public const int MOD_CTRL = 0x0002; // Ctrl键public const int MOD_SHIFT = 0x0004; // Shift键public const int MOD_WIN = 0x0008; // Windows键private const int WM_HOTKEY = 0x0312;private Action<object, EventArgs> hotkeyAction;private int id;[DllImport("user32.dll")]private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, Keys vk);[DllImport("user32.dll")]private static extern bool UnregisterHotKey(IntPtr hWnd, int id);public GlobalHotkey(IntPtr hWnd, Keys key, int modifier, Action<object, EventArgs> action){hotkeyAction = action;id = this.GetHashCode();RegisterHotKey(hWnd, id, modifier, key);Application.AddMessageFilter(new MessageFilter(this));}public void Unregister(IntPtr hWnd){UnregisterHotKey(hWnd, id);}private class MessageFilter : IMessageFilter{private GlobalHotkey hotkey;public MessageFilter(GlobalHotkey hotkey){this.hotkey = hotkey;}public bool PreFilterMessage(ref Message m){if (m.Msg == WM_HOTKEY && (int)m.WParam == hotkey.id){hotkey.hotkeyAction(null, EventArgs.Empty);return true;}return false;}}}
'@Add-Type -TypeDefinition $code -ReferencedAssemblies 'System.Windows.Forms'Add-Type -AssemblyName 'System.Windows.Forms'#全局对象
[GlobalHotkey]$Global:hotkey = $null<#热键被按下,事件处理#>
$action = [System.Action[System.Object,System.EventArgs]]{param($obj,$er)Write-Host '热键被按下了...'#提醒[System.Media.SystemSounds]::Beep.Play()
}<#.Synopsis窗体结构.DESCRIPTION窗体结构#>
function Get-Windows
{[CmdletBinding()]Param(# title 窗口标题[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=0)][string]$title,[int]$width = 100,[int]$height = 50,# 不透明度,1为不透明,0为透明[double]$opacity = 1,[System.Action[System.Object,System.EventArgs]]$hotkeyAction,#是否置顶[switch]$toTop)Begin{}Process{#主窗体[System.Windows.Forms.Application]::EnableVisualStyles()[System.Windows.Forms.Form]$mainForm = New-Object 'System.Windows.Forms.Form'#控件[System.Windows.Forms.Button]$sureBtn = New-Object 'System.Windows.Forms.Button'[System.Windows.Forms.Button]$cancelBtn = New-Object 'System.Windows.Forms.Button'#大小$mainForm.ClientSize=('{0},{1}' -f $width,$height)#最大化按钮$mainForm.MaximizeBox = $False#最小化按钮$mainForm.MinimizeBox = $False#名称$mainForm.Name = "mainForm"#显示icon$mainForm.ShowIcon = $False#透明度$mainForm.Opacity = $opacity#标题$mainForm.Text = $title#是否置顶$mainForm.TopMost = $toTop#不可调整大小$mainForm.FormBorderStyle=[System.Windows.Forms.BorderStyle]::FixedSingle#显示位置,屏幕居中$mainForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen#加入控件$mainForm.Controls.Add($sureBtn)$mainForm.Controls.Add($cancelBtn)#确定按钮$sureBtn.Text = '确定'$sureBtn.Size = '40, 30'$sureBtn.Location = '5, 5'$sureBtn.add_Click({#确定按钮事件if($Global:hotkey -and $sureBtn.Enabled){$sureBtn.Enabled = $FalseWrite-Host '热键已注册~'return}#创建热键 F10#$Global:hotkey = [GlobalHotkey]::new($mainForm.Handle,[System.Windows.Forms.Keys]::F10,0,$hotkeyAction)#创建热键 Ctrl+F10#$Global:hotkey = [GlobalHotkey]::new($mainForm.Handle,[System.Windows.Forms.Keys]::F10,[GlobalHotkey]::MOD_CTRL,$hotkeyAction)#创建热键 Alt+F10#$Global:hotkey = [GlobalHotkey]::new($mainForm.Handle,[System.Windows.Forms.Keys]::F10,[GlobalHotkey]::MOD_ALT,$hotkeyAction)#创建热键 Ctrl+Alt+F10$Global:hotkey = [GlobalHotkey]::new($mainForm.Handle,[System.Windows.Forms.Keys]::F10,[GlobalHotkey]::MOD_CTRL + [GlobalHotkey]::MOD_ALT ,$hotkeyAction)$sureBtn.Enabled = $FalseWrite-Host '注册成功!'})$cancelBtn.Text = '取消'$cancelBtn.Size = '40, 30'$cancelBtn.Location = '60, 5'$cancelBtn.add_Click({#取消按钮事件if($Global:hotkey){$Global:hotkey.Unregister($mainForm.Handle)$sureBtn.Enabled = $trueWrite-Host '已取消热键..'}$Global:hotkey = $null})$mainForm.add_FormClosed({#窗体关闭事件if($Global:hotkey){$Global:hotkey.Unregister($mainForm.Handle)$Global:hotkey = $null}})#显示窗口[void]$mainForm.ShowDialog() $mainForm = $null}End{}
}#标题
#Get-Windows -title '全局热键' -hotkeyAction $action#置顶
#Get-Windows -title '全局热键' -hotkeyAction $action -toTop#透明度
#Get-Windows -title '全局热键' -hotkeyAction $action -opacity 0.5Get-Windows -title '全局热键' -hotkeyAction $action -opacity 1 -toTop
脚本使用说明
- powershell
5.1
下测试通过- 代码另存为
run.ps1
,右键,“使用 PowerShell 运行”。弹出界面后,点“确定”按钮注册全局热键,点“取消”可以取消热键。- 如果不能执行脚本,提示“无法加载文件 C:\XXX\run.ps1,因为在此系统上禁止运行脚本……”。请先修改powershell执行策略(参考此处)
修改说明
- 本例中注册的全局热键为:
Ctrl
+Alt
+F10
,如需修改,请修改$sureBtn.add_Click({...})
中的部分内容。- 窗体的样式可以在最后部分调整
- 热键被按下的事件处理,在
$action = [System.Action[System.Object,System.EventArgs]]{
param(
$obj,
$er
)
# 热键被按下时,事件处理
Write-Host ‘热键被按下了…’
#声音提醒
[System.Media.SystemSounds]::Beep.Play()
}
中修改。- 窗体还可以增加输入框等控件,以适应不同的场景,有条件可以自行扩展。
效果图
-
运行界面:
-
点“确定”注册热键
-
按下热键
-
取消热键
03 后记
搞完这个,马上做事效率就高了。不说了,继续打工了。
欢迎留言交流~
------END------