2012-07-09 89 views
3

当您从笔记本电脑上拔下具有较高分辨率的外接显示器时,Windows大多保留其宽度,但其大小会被剪裁到macbook屏幕的(较小)高度。当你重新插入显示器时,它们的尺寸仍然很小。有没有办法在Mac OS X中遍历所有打开的窗口?

我的问题是:有什么办法可以遍历所有打开的窗口,保存它们的大小,并在显示器重新插入后还原它们?

回答

9

下面的AppleScript展示如何:

    • 遍历所有窗口检索和更改窗口位置
    • 找回并更改窗口大小

    代码:

    tell application "System Events" 
        set theProcesses to application processes 
        repeat with theProcess from 1 to count theProcesses 
         tell process theProcess 
          repeat with x from 1 to (count windows) 
           set windowPosition to position of window x 
           set windowSize to size of window x 
           set position of window x to {0, 0} 
           set size of window to {100, 100} 
          end repeat 
         end tell 
        end repeat 
    end tell 
    

    注:脚本需要辅助装置(AFAD)访问:
    “系统偏好设置”→“通用艾策斯”→“启用辅助设备的访问”

    编辑(应答评论)

    启用来自AppleScipt的AfAD可能会改善用户体验,但不要在每次脚本执行时都这样做,只有在禁用了AfAD的情况下才启用AfAD。在不通知用户的情况下启用功能不是很好的做法,请提示用户启用AfAD。

    例子:

    set AccesEnables to do shell script "[ -e \"/private/var/db/.AccessibilityAPIEnabled\" ] && echo \"Yes\" || echo \"No\"" 
    if (AccesEnables is equal to "No") then 
        set askUser to display dialog "This application requires access for assistive devices. Enable this feature?" default button 2 
        set answer to button returned of askUser 
        if answer is equal to "OK" then 
         do shell script "touch /private/var/db/.AccessibilityAPIEnabled" with administrator privileges 
        else 
         close 
        end if 
    end if 
    
  • +0

    +1,但它可能是值得展示如何以编程的辅助访问通过要求授权(做shell脚本......具有管理员权限)转动。 – abarnert 2012-07-09 21:19:23

    +0

    太糟糕了,我不能再+1 ......但“以管理员权限”已经弹出一个对话框,询问是否给予许可,让你不想弹出一个对话框,询问是否要弹出对话框,要求准予,除非你是Windows Vista的忠实粉丝。 :) – abarnert 2012-07-09 22:17:45

    +1

    这并非完全正确。第一个对话框通知用户需要启用其他功能才能使用该应用程序。第二个对话框只需要输入密码,但不能解释原因。使用这两个对话框,用户知道发生了什么,并可以阉选择启用该功能与否。此外,您可以第一个对话框,需要具有管理员权限,并在下一个窗口中暖用户会要求输入密码。通知用户永久更改设置是不好的做法,这就是为什么应该使用附加对话框。 – Anne 2012-07-09 22:27:31

    2

    的AppleScript的解决方案,用于其见安妮的回答,是迄今为止最容易的。

    如果你想要把这个交给谁不能上依赖的朋友要弄清楚如何启用辅助访问,或者更广泛地分发,只需添加这行:

    do shell script ¬ 
        "touch /private/var/db/.AccessibilityAPIEnabled" ¬ 
        with administrator privileges 
    

    这会弹出通常的验证对话框,然后使用权限打开辅助访问。

    实际上可以在没有辅助访问的情况下执行此操作,但它需要在CoreGraphics/Quartz Window Services中使用私有函数,即CGSPrivate.h

    随着公共API,你可以轻松地枚举所有的窗户:

    CFArrayRef windows = 
        CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | 
              kCGWindowListExcludeDesktopElements, 
              kCGNullWindowID); 
    

    这将返回字典的数组,每个字典包含kCGWindowBounds字典,它具有高度,宽度,X和Y整值。

    但是这些公共API是严格只读的。实际移动的窗口,你必须动用CGSPrivate.h做这样的事情:

    CGSConnection conn = _CGSDefaultConnection(); 
    for (NSDictionary *window in windows) { 
        CGSWindow wid = (CGSWindow)[[window objectForKey:@"kCGWindowNumber"] intValue]; 
        CGRect bounds; 
        CGRectMakeWithDictionaryRepresentation([window objectForKey:@"kCGWindowBounds"], 
                 &bounds); 
        CGSMoveWindow(conn, wid, bounds.origin); 
    } 
    

    显然,这是非常讨厌的,你应该只考虑它,如果你真的需要分发应用程序,可以不要求辅助访问。

    你也反向工程窗口服务器协议,并直接与之对话,但这是令人讨厌连。

    相关问题