Golang中如何使用RobotGo处理屏幕分辨率与鼠标移动问题
Golang中如何使用RobotGo处理屏幕分辨率与鼠标移动问题
我正在尝试获取(主)显示器的分辨率。目前,我正在为一个类似VNC的应用程序使用以下代码——其中mouse.X和mouse.Y是0…1的范围,分别对应从左到右和从下到上。
width, height := robotgo.GetScreenSize()
x := int(*mouse.X * float32(width))
y := int(*mouse.Y * float32(height))
robotgo.Move(x, y)
当系统(PC Win10)只有一个显示器时,这段代码工作正常。但是当有多个显示器时,分辨率被设置为所有显示器的整体宽度和高度——即整个桌面的分辨率。
请问有人知道robotgo是否可以获取单个(可能是主)显示器的分辨率吗?
如果不行——是否有办法简单地且跨平台地获取主显示器的分辨率?
顺便说一下,我知道SDL——但它似乎需要与robotgo不同的编译器(32位与64位)——尽管我自己还没有验证这一点。
谢谢。
更多关于Golang中如何使用RobotGo处理屏幕分辨率与鼠标移动问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang中如何使用RobotGo处理屏幕分辨率与鼠标移动问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在RobotGo中直接获取单个显示器分辨率的功能目前确实有限。不过,我们可以通过系统调用或使用其他库来获取主显示器分辨率,然后与RobotGo配合使用。以下是跨平台的解决方案:
Windows平台示例(使用syscall):
package main
import (
"fmt"
"syscall"
"unsafe"
)
type Rect struct {
Left int32
Top int32
Right int32
Bottom int32
}
func GetPrimaryMonitorRect() (int, int, error) {
user32 := syscall.NewLazyDLL("user32.dll")
getMonitorInfo := user32.NewProc("GetMonitorInfoW")
monitorFromPoint := user32.NewProc("MonitorFromPoint")
getSystemMetrics := user32.NewProc("GetSystemMetrics")
// 获取主显示器句柄
point := uintptr(0) // 屏幕左上角
monitor, _, _ := monitorFromPoint.Call(point, 0)
var monitorInfo struct {
cbSize uint32
rcMonitor Rect
rcWork Rect
dwFlags uint32
}
monitorInfo.cbSize = uint32(unsafe.Sizeof(monitorInfo))
ret, _, _ := getMonitorInfo.Call(monitor, uintptr(unsafe.Pointer(&monitorInfo)))
if ret == 0 {
// 回退到系统指标
width, _, _ := getSystemMetrics.Call(0) // SM_CXSCREEN
height, _, _ := getSystemMetrics.Call(1) // SM_CYSCREEN
return int(width), int(height), nil
}
rect := monitorInfo.rcMonitor
width := rect.Right - rect.Left
height := rect.Bottom - rect.Top
return int(width), int(height), nil
}
macOS平台示例:
// +build darwin
package main
import (
"os/exec"
"strconv"
"strings"
)
func GetPrimaryMonitorRect() (int, int, error) {
cmd := exec.Command("system_profiler", "SPDisplaysDataType")
output, err := cmd.Output()
if err != nil {
return 0, 0, err
}
lines := strings.Split(string(output), "\n")
for i, line := range lines {
if strings.Contains(line, "Resolution:") {
parts := strings.Fields(line)
if len(parts) >= 2 {
res := strings.Split(parts[1], "x")
if len(res) == 2 {
width, _ := strconv.Atoi(res[0])
height, _ := strconv.Atoi(res[1])
return width, height, nil
}
}
}
}
// 回退方案
cmd = exec.Command("bash", "-c", "system_profiler SPDisplaysDataType | grep Resolution | head -1 | awk '{print $2}'")
output, err = cmd.Output()
if err == nil {
res := strings.Split(strings.TrimSpace(string(output)), "x")
if len(res) == 2 {
width, _ := strconv.Atoi(res[0])
height, _ := strconv.Atoi(res[1])
return width, height, nil
}
}
return 1920, 1080, nil // 默认值
}
Linux平台示例(使用xrandr):
// +build linux
package main
import (
"os/exec"
"strconv"
"strings"
)
func GetPrimaryMonitorRect() (int, int, error) {
cmd := exec.Command("xrandr")
output, err := cmd.Output()
if err != nil {
return 0, 0, err
}
lines := strings.Split(string(output), "\n")
for _, line := range lines {
if strings.Contains(line, " connected") && strings.Contains(line, "primary") {
parts := strings.Fields(line)
for _, part := range parts {
if strings.Contains(part, "x") && strings.Contains(part, "+0+0") {
res := strings.Split(part, "+")[0]
dims := strings.Split(res, "x")
if len(dims) == 2 {
width, _ := strconv.Atoi(dims[0])
height, _ := strconv.Atoi(dims[1])
return width, height, nil
}
}
}
}
}
return 1920, 1080, nil // 默认值
}
与RobotGo集成的完整示例:
package main
import (
"fmt"
"runtime"
"github.com/go-vgo/robotgo"
)
func main() {
// 获取主显示器分辨率
primaryWidth, primaryHeight, err := GetPrimaryMonitorRect()
if err != nil {
// 回退到RobotGo的全屏分辨率
primaryWidth, primaryHeight = robotgo.GetScreenSize()
}
fmt.Printf("主显示器分辨率: %dx%d\n", primaryWidth, primaryHeight)
// 使用主显示器分辨率进行鼠标移动
mouseX := float32(0.5) // 示例:屏幕水平中心
mouseY := float32(0.5) // 示例:屏幕垂直中心
x := int(mouseX * float32(primaryWidth))
y := int(mouseY * float32(primaryHeight))
robotgo.Move(x, y)
fmt.Printf("鼠标移动到: (%d, %d)\n", x, y)
// 获取当前鼠标位置(相对于整个桌面)
currentX, currentY := robotgo.GetMousePos()
fmt.Printf("当前鼠标位置: (%d, %d)\n", currentX, currentY)
}
// 根据平台选择相应的实现
func GetPrimaryMonitorRect() (int, int, error) {
switch runtime.GOOS {
case "windows":
return GetPrimaryMonitorRectWindows()
case "darwin":
return GetPrimaryMonitorRectMac()
case "linux":
return GetPrimaryMonitorRectLinux()
default:
return 1920, 1080, nil
}
}
替代方案:使用go-ole(仅Windows,但更稳定):
// +build windows
package main
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
func GetPrimaryMonitorRectOLE() (int, int, error) {
ole.CoInitialize(0)
defer ole.CoUninitialize()
unknown, _ := oleutil.CreateObject("WScript.Shell")
ws, _ := unknown.QueryInterface(ole.IID_IDispatch)
defer ws.Release()
// 获取屏幕宽度和高度
widthVar, _ := oleutil.CallMethod(ws, "RegRead",
"HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics\\AppliedDPI")
dpi := int(widthVar.Val)
// 计算实际分辨率(基于DPI缩放)
sysWidth, _ := oleutil.GetProperty(ws, "ScreenWidth")
sysHeight, _ := oleutil.GetProperty(ws, "ScreenHeight")
width := int(sysWidth.Val) * 96 / dpi
height := int(sysHeight.Val) * 96 / dpi
return width, height, nil
}
这些解决方案提供了跨平台获取主显示器分辨率的方法,可以与RobotGo的鼠标移动功能配合使用。对于多显示器环境,建议将鼠标坐标限制在主显示器范围内,或者实现显示器识别逻辑来确定目标显示器。

