Windows10有没有办法用系统事件触发虚拟桌面切换?

Windows10的那个任务视图/虚拟桌面功能还挺好用的,我一直将其用于对同时进行的不同工作进行分类。

为了便于在不同的虚拟桌面间切换,我用AHK将鼠标的两个侧键(XB1和XB2)与切换虚拟桌面的快捷键(win+ctrl+←/→)绑上了。平时用着还挺顺手,但在使用一些大概是设计上不怎么规范、胡乱占用快捷键的软件时,有时会出现侧键无效的问题,多数时候需要将窗口焦点指向别的窗口才能恢复,偶尔甚至得彻底关闭软件才能恢复正常。

所以我在琢磨着,既然AHK能触发系统事件,那能不能用这类方法绕过快捷键,从而规避这类问题。然而我对此不甚熟悉,翻了半天资料也没找到相关的方法,故而发帖向各位寻求建议。当然如果有别的方法,自然也是非常欢迎的。

最后将目前使用的AHK脚本附于下方,虽然很简陋,但在不碰到上述问题的时候还挺好用的。

#NoEnv
#NoTrayIcon
SendMode Input
XButton1::^#Left
XButton2::^#Right

软件:

使用管理员运行 PowerShell 然后再安装。

导入包遇到的权限错误的解决,使用管理员运行:

Set-ExecutionPolicy RemoteSigned

项目地址及使用示例:

使用 ahk 调用 powershell:

; 示例,测试可用:
!a:: Run powershell -Command "Switch-Desktop 0"
!b:: Run powershell -Command "Switch-Desktop 1"

https://www.autohotkey.com/boards/viewtopic.php?t=51588

给侧键绑定命令即可。


侧键可能失效的问题。

给侧键改快捷键,改为一个复杂的,不会被用到的组合键 a,b,类似键盘重映射,然后再使用 ahk 给组合键 a,b 绑定切换虚拟桌面的命令。

2 Likes

AHK 是监听键鼠的事件,在对应的输入指令被触发后,引发一个中断,去执行自定义的代码。

不使用快捷键,那就只剩下在终端敲命令了吧? :laughing:

使用脚踏板的话,也须可以解决。

1 Like

感谢回复。对AHK我属实是不甚了了,只是依稀记得以前在文档里看见过能触发系统事件,所以才想试试。总之我先去研究一下那个powershell脚本,不行就再倒腾一下复杂快捷键曲线救国。再次感谢指导,帮大忙了。

我是MouseInc的边缘切换实现,鼠标移动到桌面底部时上下滚动滚轮就实现了切换。
主要是方便摸鱼,滚动滚轮不会发出声音,不会每次来人就刚好突兀的出现按键或点鼠标的声音。 :smile:

2 Likes

win10 的虚拟桌面 API

VirtualDesktopManager

具体参见

刚才查了一下, 已经有人写好 AHK 脚本了.

如果您已经迁移到 Windows 10,那么您必须使用新的虚拟桌面环境!不幸的是,Windows 缺少一些键盘快捷键,例如跳转到特定桌面和将程序移动到另一个桌面。该脚本旨在通过为您的所有虚拟桌面管理需求提供一种简单的可定制热键来填补这个漏洞。

要求: 该脚本需要 32 位和 64 位版本的 Autohotkey 可执行文件才能可靠地将窗口发送到其他桌面。

那啥,再请教一个问题。我搞定了Powershell的VirtualDesktop模组,现在经过测试已经能够绕过那些烦人的快捷键占用了。然而新出现了一个问题,那就是每次我按下鼠标侧键都会弹出Powershell窗口,并且启动Poershell然后执行代码会导致按键和切换桌面间有1秒多的延迟,请问这个有什么解决办法吗?附上我目前使用的AHK如下:

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#NoTrayIcon
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
XButton1:: Run powershell -Noninteractive -WindowStyle Hidden -Command "(Get-DesktopIndex) - 1 | Switch-Desktop | Out-Null"
XButton2:: Run powershell -Noninteractive -WindowStyle Hidden -Command "(Get-DesktopIndex) + 1 | Switch-Desktop | Out-Null"

Run, Target [, WorkingDir, Options, OutputVarPID]

Target 是命令,后面中括号内的是以逗号分隔的可选参数,其中 Options 可以有 MaxMinHide,选择 hide 就行,但是前面留个空给 WorkingDir。

所以在后面的 option 的位置添上 hide 就能隐藏 PowerShell 一闪而过的窗口。

这 1s 多的延迟应该无法避免。

XButton1:: Run powershell -Command "(Get-DesktopIndex) - 1 | Switch-Desktop | Out-Null",,hide
XButton2:: Run powershell -Command "(Get-DesktopIndex) + 1 | Switch-Desktop | Out-Null",,hide

1 Like

直接用 win10 API 不香吗?

AHK脚本我分享到楼上的贴子里了.

1 Like

兄弟可以尝试添加以下代码到AHK代码里面

if !A_IsAdmin
	Run *RunAs "%A_AhkPath%" /r "%A_ScriptFullPath%"

具体原理就是使AHK脚本拥有管理员权限,就可以在某些软件下正常操作了。

1 Like

感谢。正在研究那组脚本的代码,看看能不能把我不需要的部分裁剪一下。

感谢。我再研究研究。

感谢。不过也有些占用快捷键的软件本身并不需要管理员权限,这样的情况下我觉得恐怕并不能靠提权解决问题。但管理员权限确实仍然是个需要注意的地方。

我的AHK脚本代码比较多,全局快捷键或者某些软件下的快捷键也是比较多,之前测试的时候也是相同的情况,某些软件下会无效,添加管理员权限后好像没遇到这种问题了。

我的AHK代码实在有点多了,管理或者切换都要来回测试代码有点麻烦甚至莫名奇妙的问题。现在已经逐渐转换到其它软件去管理快捷键了,例如:Clavier+、MouseInc。

你都放弃鼠标的侧键返回功能了,那可以直接用类似罗技游戏软件修改鼠标的侧键为对应的功能快捷键。我就是把鼠标的DPI键改为了Win键来快速呼出菜单打开软件的。

1 Like

汇报一下吧。那个AHK脚本似乎确实能用,是目前我尝试过的几个方案里唯一成功绕过了某个“只要开着就休想使出win+ctrl+←/→快捷键”的软件的。不过这脚本还挺复杂的,目前为止我对它的裁剪全部宣告失败,还得继续研究一下,毕竟现在切桌面的时候总是会在任务栏里闪现一下,而且我还挺不爽里面带着的几个对我来说完全没什么用的dll的。但总之非常感谢~

感谢。不过我的多彩鼠标的驱动程序完全不顶用呢,遗憾。MouseInc看着不错,我之后回去体验一下的,多谢推荐。

折腾了一下将 PSVirtualDesktop 翻译成了 aardio 扩展库,
移除了所有 PowerShell 代码,只保留了导入类型,好处是不再调用 PowerShell 所以速度更快,
也不需要管理权限注册 PowerShell 模块。

aardio 里也可以嵌入 Autohotkey (支持 v1,v2),试了一下挺好用。

import ahk; 
import dotNet.desktop;
import win.ui;
/*DSG{{*/
var winform = win.form(text="虚拟桌面切换";right=599;bottom=399)
winform.add(
edit={cls="edit";left=17;top=18;right=565;bottom=374;edge=1;multiline=1;z=1}
)
/*}}*/

//导出 AutoHotkey 函数
ahk.onSwitch = function(index){ 
	winform.edit.print("已切换桌面到:",index);
	
	//虚拟桌面在键盘钩子中需要通过返回异步函数异步调用。
	return function() {
		dotNet.desktop.get(index).MakeVisible()
	}
}
 
//运行 AutoHotkey 代码注册热键
ahk.run( `
#Persistent
#NoTrayIcon 
#include <aardio> 

^j:: aardio.onSwitch(1)
^k:: aardio.onSwitch(2)
`);

winform.show();
win.loopMessage(); 

1 Like

感谢,我去研究一下怎么用。

您好,我注意到您应当正是aardio的开发者,因此想厚颜请求一些进一步的帮助:
我刚才安装了aardio并在其中测试了代码,然后出于个人用途上的考虑(持续静默运行于后台,鼠标侧键XB1/XB2切换到上一个/下一个桌面),将代码修改为如下:

import ahk; 
import dotNet.desktop;

//导出 AutoHotkey 函数
ahk.onSwitch = function(index){ 
	//虚拟桌面在键盘钩子中需要通过返回异步函数异步调用。
	return function() {
		dotNet.desktop.MakeVisible((dotNet.desktop.index(current())+index)) 
        //我估摸着是这行的函数套娃有问题,ahk代码应该无误。
        //还有导入的.net/desktop库里虽然在注释写了Left/Right,但好像在代码里没有相应的声明?
	}
}
 
//运行 AutoHotkey 代码注册热键
ahk.run( `
#Persistent
#NoTrayIcon 
#include <aardio> 

XButton2:: aardio.onSwitch(1)
XButton1:: aardio.onSwitch(-1)
`);

win.loopMessage();

但在试运行时,报如下错误:


近日我因个人事务而相当忙碌,且我的编程基础颇差,实在无暇从头学习这门语言,所以想请您帮忙改正一下代码,不知可否提供帮助?万分感谢。

不必客气,很高兴能提供一些帮助。
首先 current() 是不存在的,获取当前桌面应当是 dotNet.desktop.current()。
dotNet.desktop.get() 不指定参数也可以获取当前桌面。

正确写法:

//导出 AutoHotkey 函数
ahk.onSwitch = function(index){ 
	return function() {
		
		//转换为相对于当前桌面的索引
		index =  dotNet.desktop.index() + index;
		
		//获取桌面对象
		var desktop = dotNet.desktop.get(index)
		
		//切换到指定桌面
		desktop.MakeVisible();
	}
}

实际上可以通过 Left 获取上一个桌面, Right 获取下一个桌面,所以也可以这样写

ahk.onSwitch = function(index){ 
 
	return function() {
		if(index>0){
			//显示下一个桌面
			dotNet.desktop.current().Right.MakeVisible();
		}
		else {
			//显示上一个桌面
			dotNet.desktop.current().Left.MakeVisible();
		}
	}
}

另外 dotNet.desktop.MakeVisible() 这个函数也是不存在的。
dotNet.desktop 对象才有 MakeVisible() 函数,输入的时候能看到智能提示:

image

1 Like