Cocoa 在AppleScript中调整不可编写应用程序的窗口大小

Cocoa 在AppleScript中调整不可编写应用程序的窗口大小,cocoa,macos,resize,window,applescript,Cocoa,Macos,Resize,Window,Applescript,我正在开发一个应用程序,它可以移动和调整OSX上其他应用程序的窗口大小。 主应用程序是用Cocoa编写的,但调整大小部分是用AppleScript完成的,因为Cocoa似乎没有这种功能 以下是对ActionScript的常规调用(作为字符串传递给NSAppleScript)的结果: 窗口ID是使用OSX 10.6中引入的CGWindowListCopyWindowInfo API获得的 这种方法适用于大多数windows,但不适用于不可编写的应用程序。 最突出的例子是OSX自己的预览 我尝试过“

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

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

窗口ID是使用OSX 10.6中引入的CGWindowListCopyWindowInfo API获得的

这种方法适用于大多数windows,但不适用于不可编写的应用程序。 最突出的例子是OSX自己的预览

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

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上以编程方式调整不可编辑窗口大小的正确方法是什么? 我可以从以下应用程序看出这是可能的


任何建议——无论是Cocoa建议还是基于AppleScript的建议或其他建议——都是非常受欢迎的。

您提到了预览,所以请在预览中打开一个窗口并运行此脚本

tell application "System Events"
    tell process "Preview"
        set theWindows to windows
        return properties of (item 1 of theWindows)
    end tell
end tell
查看返回的属性。没有“id”属性,因此无法以这种方式访问windows。没有“界限”属性,因此无法设置界限。还要注意,您必须从系统事件调用中的“进程”获取窗口。因此,如果你想使用系统事件,你的代码是相当遥远的

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


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

不幸的是,描述应用程序窗口的应用程序取决于应用程序的开发人员——一般来说,没有干净的方法可以做到这一点。看看我几年前为所有特殊情况编写的脚本:

    -- 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

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

在我的例子中,我需要调整应用程序的大小以匹配屏幕大小,我发现如果您授予脚本编辑器,您可以使用“系统事件”。如果您需要授予该应用程序访问权限,请改为

下面的脚本只需获取屏幕大小,重新打开应用程序以确保其处于打开状态,然后使用“系统事件”设置前窗口的大小

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


感谢您提供脚本,并深入了解使用AppleScript完成此任务的复杂性。我决定改用可访问性API。虽然它有更大的开销,但为了调整大小,它可以跨应用程序工作。您是否可以解释或发送资源来解释您是如何通过可访问性实现这一点的?我在苹果的文档或在线上找不到任何东西。
没有“界限”属性,因此无法设置界限我尝试使用“谷歌浏览器”进程。也没有“边界”属性,但我可以设置边界。
    -- 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
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