如何写窗口管理脚本

wen 实用脚本 23

本文目录导读:

如何写窗口管理脚本

  1. 通用脚本逻辑设计
  2. Windows 平台详解:AutoHotkey (首选)
  3. macOS 平台详解:Hammerspoon (推荐)
  4. Linux 平台 (X11 / Wayland)
  5. 总结与建议

编写窗口管理脚本可以极大提升工作效率,特别是当你需要快速布局、切换多个应用程序时,根据你使用的操作系统(Windows、macOS 或 Linux),方法会有所不同。

以下是针对 Windows(AutoHotkey)macOS(AppleScript/ Hammerspoon) 两个主流平台的详细指南,以及一个通用的脚本逻辑框架。


通用脚本逻辑设计

无论用什么语言或系统,一个成熟的窗口管理脚本通常包含以下核心功能:

  1. 窗口发现与定位: 找到目标程序的进程名、窗口标题或窗口句柄。
  2. 窗口状态修改: 修改位置(X,Y)、大小(W,H)、状态(最大化、最小化、置顶)。
  3. 事件触发: 通过热键(快捷键)、定时任务或特定窗口事件(如某程序打开时自动布局)。
  4. 规则匹配: 特定程序使用特定的位置或大小。

一个简单的伪代码示例(仅用于理解逻辑):

当按下 "Win+1" 时 {
    找到 "Chrome" 窗口
    如果窗口存在 {
        设置窗口位置为 左半屏 (0,0,960,1080)
    }
}
当 "Slack" 窗口 被创建时 {
    等待 0.5秒
    设置 "Slack" 窗口位置为 右上角 (960,0,960,540)
}

Windows 平台详解:AutoHotkey (首选)

AutoHotkey(AHK) 是 Windows 上最强大、最灵活的窗口管理脚本工具,它免费、开源、语法简单。

基本安装与语法

  • 安装:autohotkey.com 下载并安装。
  • 脚本文件: 创建一个 .ahk 文件(WindowManager.ahk),用记事本编辑。
  • 结构: 热键:: 命令

核心命令

  • WinMove, WinTitle, X, Y, Width, Height:移动并调整窗口大小。
  • WinActivate, WinTitle:激活窗口到前台。
  • WinMinimize / WinMaximize / WinRestore:最小化/最大化/恢复。
  • WinGetActiveStats, Title, Width, Height, X, Y:获取当前激活窗口的信息。
  • WinGetPos, X, Y, Width, Height, WinTitle:获取指定窗口的位置和大小(非常实用,可以获取当前窗口宽高用来计算新位置)。

实战示例:一个全能的窗口管理脚本

; ==================== 配置文件头 ====================
#NoEnv
#SingleInstance Force
; ====================================================
; ---------- 功能1:窗口快速排列(左半屏/右半屏) ----------
; Win+Left 将窗口移到左半屏,Win+Right 移到右半屏
#Left::
    WinGet, ActiveWindow, ID, A
    WinGetPos, X, Y, Width, Height, ahk_id %ActiveWindow%
    SysGet, MonitorWorkArea, MonitorWorkArea
    NewWidth := MonitorWorkAreaRight / 2
    WinMove, ahk_id %ActiveWindow%, , 0, 0, NewWidth, MonitorWorkAreaBottom
    WinActivate, ahk_id %ActiveWindow%
return
#Right::
    WinGet, ActiveWindow, ID, A
    WinGetPos, X, Y, Width, Height, ahk_id %ActiveWindow%
    SysGet, MonitorWorkArea, MonitorWorkArea
    NewWidth := MonitorWorkAreaRight / 2
    WinMove, ahk_id %ActiveWindow%, , MonitorWorkAreaRight - NewWidth, 0, NewWidth, MonitorWorkAreaBottom
    WinActivate, ahk_id %ActiveWindow%
return
; ---------- 功能2:窗口置顶与取消置顶 ----------
; Win+Space 切换窗口置顶
#Space::
    Winset, AlwaysOnTop, toggle, A
    ; 显示一个简单的提示框(可选)
    WinGetTitle, Title, A
    ToolTip, 当前窗口已切换置顶状态: %Title%
    SetTimer, RemoveToolTip, 2000
return
RemoveToolTip:
    ToolTip
return
; ---------- 功能3:多显示器支持(将窗口移动到第二个显示器) ----------
; Win+Shift+Right 将窗口移到次显示器中心
#+Right::
    WinGet, ActiveWindow, ID, A
    ; 获取所有显示器的坐标(简化版,假设只有两个显示器)
    SysGet, Monitor1, Monitor, 1
    SysGet, Monitor2, Monitor, 2
    ; 如果存在第二个显示器,将窗口移动到其中心
    if (Monitor2Right > Monitor1Right) {
        NewX := Monitor2Left + (Monitor2Right - Monitor2Left - 800) // 2
        NewY := Monitor2Top + (Monitor2Bottom - Monitor2Top - 600) // 2
        WinMove, ahk_id %ActiveWindow%, , NewX, NewY, 800, 600
    }
return
; ---------- 功能4:启动特定程序并定位(如打开notepad并居中) ----------
#n::  ; Win+N
    Run, notepad.exe
    WinWait, ahk_class Notepad, , 3  ; 等待窗口出现,最多3秒
    if ErrorLevel {
        MsgBox, 无法启动记事本
        return
    }
    WinActivate
    ; 将记事本居中(屏幕宽800,高600)
    WinGetPos, , , WinW, WinH, A
    MonWidth := A_ScreenWidth
    MonHeight := A_ScreenHeight
    NewX := (MonWidth - 800) // 2
    NewY := (MonHeight - 600) // 2
    WinMove, A, , NewX, NewY, 800, 600
return

进阶技巧

  • 进程检测: IfWinExist, ahk_exe chrome.exeIfWinActive, ahk_exe chrome.exe
  • 窗口类: 使用 Window Spy 工具(AHK自带)查看窗口的类名和进程名。
  • 定时任务: SetTimer, CheckWindow, 1000 每1秒检查一次窗口状态。
  • 循环动作: 配合 Loop 可以批量调整多个窗口。

macOS 平台详解:Hammerspoon (推荐)

macOS 自带的 AppleScript 处理窗口很繁琐,Hammerspoon 是一个用 Lua 语言编写的窗口管理工具,功能强大且现代。

安装与配置

  • 安装: brew install hammerspoon 或从官网下载。
  • 配置文件: 打开 Hammerspoon -> Preferences -> 勾选 Launch Hammerspoon at login,配置文件位于 ~/.hammerspoon/init.lua

核心概念与命令

  • hs.window:窗口对象。
  • hs.geometry:几何形状(位置和大小)。
  • hs.hotkey:热键绑定。
  • hs.screen:屏幕对象。
  • window:move(rect):移动窗口到指定矩形。
  • window:maximize():最大化。

实战示例(快速窗口管理)

-- ~/.hammerspoon/init.lua
-- 基础配置
hs.logger.defaultLogLevel = "info"
-- 设置模态快捷键:按下 Ctrl+Option+Cmd 激活窗口控制模式
hs.hotkey.bind({"ctrl", "alt", "cmd"}, "space", function()
    -- 可以在这里切换不同的布局模式,简单示例:直接触发以下热键
    hs.alert.show("窗口模式已激活")
end)
-- ---------- 功能1:窗口快速定位 ----------
-- Ctrl + Option + H (左半屏)
hs.hotkey.bind({"ctrl", "alt"}, "H", function()
    local win = hs.window.focusedWindow()
    local screen = win:screen()
    local rect = screen:frame()
    win:move(rect:fromUnitRect(hs.geometry.rect(0, 0, 0.5, 1)), nil, true)
end)
-- Ctrl + Option + L (右半屏)
hs.hotkey.bind({"ctrl", "alt"}, "L", function()
    local win = hs.window.focusedWindow()
    local screen = win:screen()
    local rect = screen:frame()
    win:move(rect:fromUnitRect(hs.geometry.rect(0.5, 0, 0.5, 1)), nil, true)
end)
-- Ctrl + Option + K (居中 800x600)
hs.hotkey.bind({"ctrl", "alt"}, "K", function()
    local win = hs.window.focusedWindow()
    local screen = win:screen()
    local frame = screen:frame()
    local newSize = hs.geometry.size(800, 600)
    local newOrigin = hs.geometry.point(
        frame.x + (frame.w - newSize.w) / 2,
        frame.y + (frame.h - newSize.h) / 2
    )
    win:move(hs.geometry.rect(newOrigin, newSize))
end)
-- ---------- 功能2:窗口置顶 ----------
-- Ctrl + Option + T (切换置顶)
hs.hotkey.bind({"ctrl", "alt"}, "T", function()
    local win = hs.window.focusedWindow()
    if win then
        local isFloating = win:isAlwaysOnTop()
        win:setAlwaysOnTop(not isFloating)
        hs.alert.show(win:title() .. " 置顶状态: " .. tostring(not isFloating))
    end
end)
-- ---------- 功能3:自动布局特定程序 ----------
-- 当Safari打开时,自动放置到左半屏
hs.window.filter.new():subscribe(hs.window.filter.windowCreated, function(win)
    local appName = win:application():name()
    if appName == "Safari" then
        hs.timer.doAfter(0.2, function() -- 延迟一下确保窗口已完全初始化
            local screen = win:screen()
            local rect = screen:frame()
            win:move(rect:fromUnitRect(hs.geometry.rect(0, 0, 0.5, 1)), nil, true)
        end)
    end
end)
-- 当iTerm打开时,放置到右半屏
hs.window.filter.new():subscribe(hs.window.filter.windowCreated, function(win)
    local appName = win:application():name()
    if appName == "iTerm2" then
        hs.timer.doAfter(0.3, function()
            local screen = win:screen()
            local rect = screen:frame()
            win:move(rect:fromUnitRect(hs.geometry.rect(0.5, 0, 0.5, 1)), nil, true)
        end)
    end
end)

Linux 平台 (X11 / Wayland)

Linux 下使用窗口管理器自带的脚本功能或 wmctrl + xdotool(用于 X11)。

# 安装
sudo apt install wmctrl xdotool   # Debian/Ubuntu
# 将当前窗口移动到左上角,宽度为屏幕一半
xdotool getactivewindow windowmove 0 0
xdotool getactivewindow windowsize $(xdotool getdisplaygeometry | awk '{print $1/2}') $(xdotool getdisplaygeometry | awk '{print $2}')
# 或者更简单的wmctrl(需要知道窗口ID)
wmctrl -l                                   # 列出所有窗口
wmctrl -r "Chrome" -e 0,0,0,960,1080        # 将标题包含Chrome的窗口移动到左半屏

对于 Wayland(较新的发行版),wmctrl 不兼容,推荐使用 sway(平铺窗口管理器,自带快捷键配置)或 hyprctl(Hyprland 窗口管理器的脚本接口)。


总结与建议

  1. 新手入门:Windows + AutoHotkeymacOS + Hammerspoon 开始,它们社区活跃、文档齐全。
  2. 按需定制: 不要一次性写很复杂的脚本,先写一个核心功能(比如左右分屏),然后再添加置顶、多显示器等功能。
  3. 调试技巧:
    • Windows: 使用 ToolTip 输出变量或状态信息。
    • macOS: 使用 hs.alert.show("消息")
    • 通用: 确保脚本没有语法错误,AHK 可以双击托盘图标重新加载脚本;Hammerspoon 可以在菜单栏点击 Reload Config
  4. 安全注意: 下载第三方窗口管理脚本前,请先审查代码,避免恶意操作。 能帮你写出适合自己的窗口管理脚本!如果还有具体问题(比如特定软件的处理),可以进一步提问。

抱歉,评论功能暂时关闭!