window上开发没有ubuntu下的方便,经常在window主机和ubuntu虚拟机直接切换太麻烦,每次得ctrl+alt从虚拟机释放鼠标才可以切换,经过折腾发现以下几种方法可行
方法1 虚拟机监听切换按键并通知主机进行切换桌面
虚拟主机放在单独的一个桌面上并全屏,在ubuntu虚拟机中配置一个Py脚本,把监听的按键写入主机中(tcp方式更麻烦,这里采用写入文件传递的方法)
import os
from pynput import keyboard
import time
# 定义组合键,例如 Ctrl + Alt + A、Ctrl + Alt + S、Ctrl + Alt + Z
COMBINATIONS = {
frozenset([keyboard.Key.ctrl, keyboard.Key.alt, keyboard.KeyCode(char='a')]): "SWITCH_DESKTOP_A",
frozenset([keyboard.Key.ctrl, keyboard.Key.alt, keyboard.KeyCode(char='s')]): "SWITCH_DESKTOP_S",
frozenset([keyboard.Key.ctrl, keyboard.Key.alt, keyboard.KeyCode(char='z')]): "SWITCH_DESKTOP_Z"
}
current_keys = set()
triggered = False # 防止重复触发
def on_press(key):
global triggered
current_keys.add(key)
for combination, command in COMBINATIONS.items():
if combination.issubset(current_keys) and not triggered:
# 根据按键组合写入不同的内容到共享文件
with open("/home/vm/Desktop-win11/switch_command.txt", "w") as f:
f.write(command)
triggered = True # 设置标志位,防止重复触发
break
def on_release(key):
global triggered
if key in current_keys:
current_keys.remove(key)
# 如果所有按键都释放,重置标志位
if not current_keys:
triggered = False
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
在主机上使用autohotkeys进行多桌面切换
VDA_PATH := "./VirtualDesktopAccessor.dll"
hVirtualDesktopAccessor := DllCall("LoadLibrary", "Str", VDA_PATH, "Ptr")
GoToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GoToDesktopNumber", "Ptr")
GoToDesktopNumber(num) {
global GoToDesktopNumberProc
Send, ^{Alt}
DllCall(GoToDesktopNumberProc, "Int", num)
}
; vmware 切换回win
; 定义共享文件路径
sharedFilePath := "C:\Users\marswen\Desktop\switch_command.txt"
lastModified := "" ; 用于存储上次检测到的文件修改时间
SetTimer, CheckSwitchFile, 100
CheckSwitchFile:
if FileExist(sharedFilePath) {
; 获取当前文件的最后修改时间
FileGetTime, currentModified, %sharedFilePath%, M
if (lastModified=""){
lastModified := currentModified ; 第一次读取文件内容,记录修改时间
}
else if(currentModified != lastModified) {
; 如果文件的修改时间不同于上次记录的时间,则读取文件内容并执行操作
lastModified := currentModified ; 更新记录的修改时间
; 读取文件内容
FileRead, content, %sharedFilePath%
; 根据内容执行不同的操作
if (content = "SWITCH_DESKTOP_A") {
GoToDesktopNumber(0) ; 切换到桌面 1
} else if (content = "SWITCH_DESKTOP_S") {
GoToDesktopNumber(1) ; 切换到桌面 2
} else if (content = "SWITCH_DESKTOP_Z") {
GoToDesktopNumber(2) ; 切换到桌面 3
}
}
}
return
; 使用快捷键 Ctrl + Alt + 字母
^!A::GoToDesktopNumber(0) ; 切换到第 1 个桌面
^!S::GoToDesktopNumber(1) ; 切换到第 2 个桌面
^!Z::GoToDesktopNumber(2) ; 切换到第 3 个桌面
; #:WIN ^:Ctrl !:Alt +:Shift
; 映射window终端中键为 Ctrl + Shift + V
#IfWinActive ahk_exe WindowsTerminal.exe ; 针对 Windows Terminal
MButton::Send ^+v ; 将中键设置为 Ctrl + Shift + V
#IfWinActive
; 映射window终端中键为 WIN+V
; ctrl+alt+G -> WIN+V
^!G::Send #v ; 将 ctrl+alt+G 映射为 WIN+V
把这两个文件设置分别开机启动即可
方法2 通过vmware-kvm.exe配置参数,window主机和vmware共用一个桌面
进入C:\Program Files (x86)\VMware\VMware Workstation,该目录下有vmware-kvm.exe,在该目录下配置vmware-kvm.exe的切换回window的快捷键
vmware-kvm.exe --preferences
这里我设置的ctrl+alt+x
把vmware-kvm.exe快捷方式发送到桌面,找到你对应的虚拟机.vmx文件,复制其路径到快捷方式的参数中
例如
"C:\Program Files (x86)\VMware\VMware Workstation\vmware-kvm.exe" "D:\win\Ubuntu20\Ubuntu20.vmx"
双击这个快捷方式启动虚拟机,使用快捷键就可以方便在win和vm之间切换
方法三 使用hook获取系统底层输入
请参考WinDeskSwitch,真正可以随心所欲切换
#include Lib\AutoHotInterception.ahk
VDA_PATH := "./Lib/VirtualDesktopAccessor.dll"
hVirtualDesktopAccessor := DllCall("LoadLibrary", "Str", VDA_PATH, "Ptr")
GoToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GoToDesktopNumber", "Ptr")
GoToDesktopNumber(num) {
global GoToDesktopNumberProc
DllCall(GoToDesktopNumberProc, "Int", num)
}
AHI := new AutoHotInterception()
keyboardId := 1
AHI.SubscribeKey(keyboardId, GetKeySC("Control"), false, Func("KeyEvent").Bind("ctrl"))
AHI.SubscribeKey(keyboardId, GetKeySC("Alt"), false, Func("KeyEvent").Bind("alt"))
AHI.SubscribeKey(keyboardId, GetKeySC("a"), false, Func("KeyEvent").Bind("a"))
AHI.SubscribeKey(keyboardId, GetKeySC("s"), false, Func("KeyEvent").Bind("s"))
AHI.SubscribeKey(keyboardId, GetKeySC("z"), false, Func("KeyEvent").Bind("z"))
ctrl_state := "Released"
alt_state := "Released"
a_state := "Released"
s_state := "Released"
z_state := "Released"
KeyEvent(keyName, state) {
global ctrl_state, alt_state, a_state, s_state, z_state, hLvKeyboard
Gui, ListView, % hLvKeyboard
stateText := (state = 1) ? "Pressed" : "Released"
if (keyName = "ctrl") {
ctrl_state := stateText
} else if (keyName = "alt") {
alt_state := stateText
} else if (keyName = "a") {
a_state := stateText
} else if (keyName = "s") {
s_state := stateText
} else if (keyName = "z") {
z_state := stateText
}
; ToolTip, %ctrl_state% %alt_state% %a_state% %s_state% %z_state%
if (ctrl_state= "Pressed" && alt_state== "Pressed" ) {
if(a_state== "Pressed" ){
GoToDesktopNumber(0) ; 切换到桌面 1
}
else if(s_state== "Pressed" ){
GoToDesktopNumber(1) ; 切换到桌面 2
}
else if(z_state== "Pressed" ){
GoToDesktopNumber(2) ; 切换到桌面 3
}
}
}