powershell 注册全局热键
01 前言
在处理一些重复工作问题的时候,想搞一个小工具,配合全局快捷键来提高效率。因为是Windows系统,想到C#,但是又不想用VS开发,因为那样不够灵活,没办法随时修改随时用,所以只能另寻他法。那么,不如用powershell来搞搞。
02 正文
因为涉及到全局热键,所以还是需要写一点C#,引入一些API,同时加了一个简单的窗体。
环境:Windows 11
代码如下:
<#
注册全局热键
by hokis
2024-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 = $False
Write-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 = $False
Write-Host '注册成功!'
})
$cancelBtn.Text = '取消'
$cancelBtn.Size = '40, 30'
$cancelBtn.Location = '60, 5'
$cancelBtn.add_Click({
#取消按钮事件
if($Global:hotkey){
$Global:hotkey.Unregister($mainForm.Handle)
$sureBtn.Enabled = $true
Write-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.5
Get-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------