控制OSX窗口

时间:2009-11-13 17:49:01

标签: objective-c cocoa macos macos-carbon

我正在尝试从我的应用程序控制外部OSX应用程序的窗口。我想要 至 1.移动屏幕上的窗口 2.调整屏幕上的窗口大小 3.更改应用程序的当前活动窗口 4.获取当前活动的窗口。

(我想通过ObjC / C / C ++ apis这样做。)

考虑到我有想要控制的窗口的CGWindowID,我应该寻找什么样的API调用?也就是说,我希望找到具有以下特征的函数:MoveWindow(CGWindowID winId, int x, int y)ResizeWindow(CGWindowID winId, int width, int height)Activatewindow(CGWindowID winId)CGWindowID GetCurrentlyActivatedWindow()

对于3,我已经使用SetFrontProcess来提前处理流程,但如果流程有多个,则不允许我选择流程的特定窗口。

6 个答案:

答案 0 :(得分:11)

这样做的一种方法确实是使用辅助功能API。

我正在开发的应用程序就是为了获得前窗,前窗的文档路径和许多其他属性。

我这样做的方式是通过AppleScript。它有时可能很笨拙,但似乎相当可靠。我使用AppScript从我的Cocoa应用程序中发送AppleScript。它的线程安全且比其他选择更稳定 - 无论是Scripting Bridge还是NSAppleScript。

困难的一点是使用AppleScript中的窗口ID识别窗口 - AppleScript似乎没有与CGWindowID匹配的窗口ID属性。但是,您可以使用AppleScript获得所需的任何窗口。

  1. 将最前面的窗口移动到100,100

    tell application "System Events"
     set theprocess to the first process whose frontmost is true
     set thewindow to the value of attribute "AXFocusedWindow" of theprocess
        set position of thewindow to {100, 100}
    end tell
    
  2. 将最前面的窗口调整为200,300

    tell application "System Events"
      set theprocess to the first process whose frontmost is true
      set thewindow to the value of attribute "AXFocusedWindow" of theprocess
         set size of thewindow to {200, 300}
    end tell
    
  3. 更改最前面的应用程序的当前窗口

    tell application "System Events"
      set theprocess to the first process whose frontmost is true
      set thewindow to the value of attribute "AXFocusedWindow" of theprocess
         set size of thewindow to {200, 300}
         windows of theprocess
         -- Code to get ID of window you want to activate
         tell window 2 of theprocess -- assuming it's window 2
               perform action "AXRaise"
         end tell
    end tell
    
  4. 活跃的窗口

    tell application "System Events"
     set theprocess to the first process whose frontmost is true
     set thewindow to the value of attribute "AXFocusedWindow" of theprocess
    end tell
    
  5. AppScript中有一个名为ASTranslate的应用程序可以将AppleScript转换为在AppScript中调用相关命令的Objective C代码。

    有关如何获取窗口大小和边界的更多信息(据我所知,这些只读)请参阅Son of Grab示例应用程序。

答案 1 :(得分:2)

使用CGWindowListCopyWindowInfo获取每个窗口的kCGWindowOwnerPID。然后,如果要访问ObjectiveC内容,可以使用“分布式对象”,或者使用Mach RPC来访问其他内容。所有这些都记录在http://developer.apple.com

想要向其他应用程序发送消息有很多充分的理由 - 例如在开发既不是鼠标也不是键盘的新用户界面时。

答案 2 :(得分:1)

根据您的评论,您可以使用OS X辅助功能API执行此操作,但我相信必须在用户的辅助功能首选项中启用“辅助设备访问”。

有一个第三方共享软件应用程序,其名称让我逃脱,让您可以使用键盘命令移动任何窗口(我认为调整大小)。

答案 3 :(得分:1)

需要在“系统偏好设置”中启用辅助功能才能使其生效。它是applescript,但可以在objective-c中使用脚本桥。

-- Moves safari window by deltaposition
tell application "System Events"
    tell application "Safari"
        set win to first window
        set b to bounds of win
        set deltaposition to {50, 0}
        set bounds of first window to {(item 1 of b) + (item 1 of deltaposition), (item 2 of b) + (item 2 of deltaposition), (item 3 of b) + (item 1 of deltaposition), (item 4 of b) + (item 2 of deltaposition)}
    end tell
end tell

答案 4 :(得分:0)

我认为您应该解释为什么要这样做。我所知道的唯一可以移动所有其他应用程序窗口的工具是Spaces和Expose,它们都是由Apple提供的。如果您想接管整个屏幕,那么就有公共API,但移动其他应用程序的窗口听起来很可疑。

答案 5 :(得分:0)

我是新来的,所以这必须作为答案而不是评论提交。我写了一个.NET应用程序(PlaceMint)在Windows中完成了这一点,并且完全没有怀疑。 PlaceMint可帮助您以用户定义的结构化方式组织窗口。它所做的就是根据用户定义的规则执行移动或调整窗口大小等操作。有人问我是否可以为OSX做一个端口,但是我从来没有走得太远,因为我找不到像Windows中提供的那样的API定义(封送dll调用user32.dll,如SetWindowPos())。