【问题标题】:Resizing Windows of Unscriptable Applications in AppleScript在 AppleScript 中调整不可编写脚本的应用程序的窗口大小
【发布时间】:2011-09-04 02:00:44
【问题描述】:

我正在开发一个可以在 OSX 上移动和调整其他应用程序窗口大小的应用程序。 主应用程序是用 Cocoa 编写的,但大小调整部分是用 AppleScript 完成的,因为 Cocoa 似乎没有这种功能。

这是对 ActionScript 的常规调用的结果(作为字符串传递给 NSAppleScript):

tell application "TextEdit"
    set currentWindow to the window id 5184
    set bounds of the currentWindow to {2855, 218, 3790, 578}
end tell

Window ID 是使用 OSX 10.6 中引入的 CGWindowListCopyWindowInfo API 获得的。

这种方法适用于大多数窗口,但不适用于无法编写脚本的应用程序。 最突出的例子是 OSX 自己的 Preview。

我尝试使用此代码的变体“告诉”系统事件而不是预览

tell application "System Events"
    set bounds of window 5184 to {1920, -502, 2855, 578}
end tell

但是,OSX 给了我一条错误消息:

"System Events got an error: Can’t set bounds of window 5184 to {1920, -502, 2855, 578}."

在尝试获取对窗口的引用时也会发生同样的情况:

tell application "System Events"
    get window 5184
end tell

我已经仔细检查了窗口存在并且窗口 ID 是正确的。

在 OSX 上以编程方式调整不可脚本窗口大小的正确方法是什么? 我可以从moom等应用程序中看到它是可能的。

任何建议 - 无论是基于 Cocoa 还是基于 AppleScript 或完全其他的东西 - 都非常受欢迎。

【问题讨论】:

    标签: cocoa macos resize window applescript


    【解决方案1】:

    不幸的是,应用程序窗口的 AppleScripting 取决于应用程序的开发人员 - 通常没有干净的方法来做到这一点。看看我几年前为所有特殊情况编写的这个脚本:

        -- Get screen bounds and origins
    set f to (path to preferences from local domain as Unicode text) & "com.apple.windowserver.plist"
    tell application "System Events" to set {{|Width|:w1, |Height|:h1, |OriginX|:OX1, |OriginY|:OY1}, {|Width|:w2, |Height|:h2, |OriginX|:OX2, |OriginY|:OY2}} to value of property list items of property list item 1 of property list item "DisplaySets" of property list file f
    set SecondaryScreenBounds to {OX2, OY2, OX2 + w2, OY2 + h2}
    set RHedge to OX1
    set BOTedge to OY1
    
    tell application "Finder"
        -- Get the running apps (excluding those with special windows)
        set |running| to name of processes whose visible is true and name is not "Finder" and name is not "QuickSilver" and name is not "CopyPaste" and name is not "DropCopy" and name is not "iPulse"
        repeat with anApp in |running|
            try -- for a scriptable App with window bounds property
                tell application anApp
                    set allWindows to (every window)
                    repeat with aWindow in allWindows
                        set Wbounds to (get bounds of aWindow)
                        if item 1 of Wbounds > RHE or item 2 of Wbounds > BoE then my moveWindows(contents of anApp)
                    end repeat
                end tell
            on error -- for an App with window position & size properties
                tell application "System Events"
                    tell application process anApp
                        set allWindows to (every window)
                        repeat with aWindow in allWindows
                            set {p1, p2} to aWindow's position
                            if p1 ≥ RHedge or p2 ≥ BOTedge then my moveWindows(contents of anApp)
                        end repeat
                    end tell
                end tell
            end try
        end repeat
        -- for the Finder
        set allWindows to (every window whose visible is true)
        repeat with aWindow in allWindows
            set Wbounds to bounds of aWindow
            if (item 1 of Wbounds) > RHedge or (item 2 of Wbounds) > BOTedge then
                set bounds of aWindow to {200, 200, 1200, 800}
            end if
        end repeat
    end tell
    -- for Safari
    if "Safari" is in |running| then tell application "Safari"
        set Wind to name of windows
        set Wbounds to bounds of windows
        repeat with k from 1 to count Wind
            set W to item k of Wind
            set B to item k of Wbounds
            if (item 1 of B) ≥ RHedge or (item 2 of B) ≥ BOTedge then
                set bounds of window W to {200, 200, 1200, 800}
            end if
        end repeat
    end tell
    -- for HoudahSpot
    if "HoudahSpot" is in |running| then tell application "System Events" to tell process "HoudahSpot"
        set W to name of windows
        set B to position of windows
        repeat with k from 1 to count W
            if item k of W is not missing value and (item 1 of item k of B) ≥ RHedge then set position of window (item k of W) to {100, 100}
        end repeat
    end tell
    
    -- for Activity Monitor
    if "Activity Monitor" is in |running| then tell application "System Events" to tell process "Activity Monitor"
        set W to name of windows
        set B to position of windows
        repeat with k from 1 to count W
            if item k of W is not missing value and (item 1 of item k of B) ≥ RHedge then set position of window (item k of W) to {100, 100}
        end repeat
    end tell
    -- for 1Password
    if "1Password" is in |running| then tell application "System Events" to tell process "1Password"
        set W to name of windows
        set B to position of windows
        repeat with k from 1 to count W
            if item k of W is not missing value and (item 1 of item k of B) ≥ RHedge then set position of window (item k of W) to {100, 100}
        end repeat
    end tell
    -- for iCal
    if "iCal" is in |running| then tell application "iCal"
        set iCB to bounds of window "iCal"
        if item 1 of iCB ≥ RHedge or item 2 of iCB ≥ BOTedge then
            set bounds of window "iCal" to {100, 100, 1200, 1000}
        end if
    end tell
    -- for a Help Window
    tell application "System Events"
        if exists process "Help Viewer" then tell process "Help Viewer"
            set W to windows
            repeat with w1 in W
                set position of w1 to {200, 200}
            end repeat
        end tell
    end tell
    
    to moveWindows(anApp)
        tell application "System Events"
            if anApp is "ScriptLight" then
                tell process "ScriptLight" to set position of window 1 to {200, 200}
            else if anApp is "PowerKey" then
                tell process "PowerKey" to set position of window "PowerKey" to {200, 200}
            else if anApp is "Script Debugger 4" then
                tell application process "Script Debugger 4"
                    set allWindows to (every window)
                    repeat with aWindow in allWindows
                        set {p1, p2} to aWindow's position
                        if p1 ≥ 1680 or p2 > 1050 then set aWindow's position to {100, 100}
                    end repeat
                end tell
            end if
        end tell
    end moveWindows
    

    【讨论】:

    • 感谢您提供脚本并深入了解使用 AppleScript 执行此任务的复杂性。我决定改用 Accessibility API。虽然它的开销较大,但它可以跨应用程序调整大小。
    • 您能否解释或发送资源来解释您如何通过辅助功能实现这一目标?我在 Apple 的文档或网上找不到任何内容。
    【解决方案2】:

    你提到了预览,所以在预览中打开一个窗口并运行这个脚本。

    tell application "System Events"
        tell process "Preview"
            set theWindows to windows
            return properties of (item 1 of theWindows)
        end tell
    end tell
    

    查看返回的属性。没有“id”属性,因此您无法以这种方式访问​​窗口。没有“边界”属性,因此您无法设置边界。另请注意,您必须从系统事件调用中的“进程”获取窗口。因此,如果您想使用系统事件,您的代码就离我们很远了。

    最好的办法是找到您要定位的窗口的名称。然后在applescript中你得到了我上面的Windows,然后遍历它们检查它们的名字。当您找到正确的名称时,您已经找到了相应的窗口。然后您可以设置该窗口的“大小”和“位置”属性。

    祝你好运,因为你的任务很大!

    【讨论】:

    • There is no "bounds" property so you can't set the bounds. 我尝试使用进程“Google Chrome”。也没有“边界”属性,但我能够设置边界。
    【解决方案3】:

    我在尝试使用与您使用的逻辑相似的逻辑来调整应用程序大小时遇到​​了同样的问题。

    在我的情况下,我需要调整应用程序的大小以匹配屏幕大小,我发现如果您授予脚本编辑器assistive access,您可以使用“系统事件”。如果您save the script as an app,则需要授予该应用访问权限。

    以下脚本只是抓取屏幕大小,重新打开应用程序以确保它已打开,然后使用“系统事件”设置前窗口的大小。

    注意:我的目标是下面名为“cefclient”的应用程序

    set theApp to "cefclient"
    
    tell application "Finder"
        set screenResolution to bounds of window of desktop
    end tell
    
    set screenWidth to item 3 of screenResolution
    set screenHeight to item 4 of screenResolution
    
    tell application theApp
        activate
        reopen
    end tell
    
    tell application "System Events"
        tell process theApp
            set the size of front window to {screenWidth, screenHeight}
        end tell
    end tell
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-19
      • 2013-02-15
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 2011-04-24
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多