2009-11-13 108 views
11

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

(我希望通过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来拉动一个进程,但是这并不允许我选择一个进程的特定窗口,如果它有多个。

回答

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. 的当前窗口
  5. 窗口这是积极的

    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相关命令的目标C代码。

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

+0

这些代码示例以几种方式帮助我,因为我想实现与Sami相同的功能。 :) 非常感谢! – 2011-05-16 11:02:50

+0

没问题。我很高兴能够提供帮助 - 这个社区为我提供了很多很好的答案,我很高兴能够提供回馈。 – 2011-05-16 11:35:12

+0

有没有一种方法只关注窗口,无法访问?我的用例是,我的应用程序具有焦点,它列出所有正在运行的应用程序,选择该列表中的应用程序将集中它。目前,如果我使用'activateWithOptions:'它不是最小化窗口,所以如果所有窗口minmized它什么也不做。所以我试图找到另一种方式来集中(不减少) – Noitidart 2016-01-11 11:46:53

0

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

+0

我想要自动化第三方应用程序。为此,我需要能够获取应用程序的当前状态并发送鼠标/键盘事件。 ResizeWindow将帮助我通过屏幕抓取获取当前状态,并且ActivateWindow需要能够可靠地向应用程序发送鼠标/键盘事件。 GetCurrentlyActivatedWindow将用于恢复原始活动窗口,因此自动化工作不会尽可能地与用户交互。 MoveWindow只是开发这件事的一件好事。 – Sami 2009-11-13 18:06:17

+0

好的,您应该查看Accessibility/Scripting API。任何Cocoa应用程序都会提供一定程度的可脚本化,这可能与您需要的程度相同。 – NSResponder 2009-11-13 18:28:37

1

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

有一个第三方共享软件的应用程序,它的名字让我在使用键盘命令移动任何窗口(并且我认为调整它的大小)的时候逃脱了我。

+0

你可能会想到MercuryMover:http://www.heliumfoot.com/mercurymover – 2009-11-13 18:19:55

+0

或Zooom/2:http://coderage-software.com/zooom/ – 2009-11-13 18:25:28

+0

是的,MercuryMover是它。 :-) – 2009-11-13 18:32:33

0

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

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 
2

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

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

+0

嗨bgri请你提供一些示例代码。我已经使用'CGWindowListCopyWindowInfo'获取所有'kCGWindowOwnerPID's,但我无法弄清楚如何通过它聚焦窗口。 – Noitidart 2016-01-11 11:36:44