12

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

(而且我想通过 ObjC/C/C++ api 来做到这一点)。

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

对于 3,我已经在使用SetFrontProcess将一个进程拉到前面,但这并不能让我选择一个进程的特定窗口,如果它有多个。

4

6 回答 6

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
    

有一个可用于 AppScript 的应用程序,称为ASTranslate,它将将此 AppleScript 转换为调用 AppScript 中相关命令的 Objective C 代码。

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

于 2009-11-14T03:31:56.703 回答
2

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

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

于 2010-08-26T05:39:51.623 回答
1

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

有一个第三方共享软件应用程序,它的名字现在让我无法理解,它可以让你使用键盘命令移动任何窗口(我认为调整它的大小)。

于 2009-11-13T18:18:58.337 回答
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
于 2009-11-14T03:44:00.967 回答
-1

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

于 2009-11-13T17:57:14.790 回答
-1

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

于 2009-11-13T18:28:13.220 回答