Objective c 控制OSX窗口

Objective c 控制OSX窗口,objective-c,cocoa,macos,macos-carbon,Objective C,Cocoa,Macos,Macos Carbon,我正在尝试从我的应用程序控制一个外部OSX应用程序的窗口。我想 到 1.移动屏幕上的窗口 2.调整屏幕上窗口的大小 3.更改应用程序的当前活动窗口 4.获取当前活动的窗口 (我想通过ObjC/C/C++api来实现这一点) 考虑到我拥有想要控制的窗口的CGWindowID,我应该寻找哪些API调用?也就是说,我希望找到具有以下签名的函数:MoveWindow(CGWindowID winId,int x,int y),调整窗口大小(CGWindowID winId,int width,int h

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

(我想通过ObjC/C/C++api来实现这一点)

考虑到我拥有想要控制的窗口的CGWindowID,我应该寻找哪些API调用?也就是说,我希望找到具有以下签名的函数:
MoveWindow(CGWindowID winId,int x,int y)
调整窗口大小(CGWindowID winId,int width,int height)
激活窗口(CGWindowID winId)
CGWindowID GetCurrentlyActivateDWOW()


对于3,我已经在使用
SetFrontProcess
将一个进程拉到最前面,但是如果一个进程有多个窗口,这不允许我选择该进程的特定窗口。

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

根据你的评论,你可以使用OS X辅助设备API来实现这一点,但我相信“辅助设备访问”必须在用户的辅助设备首选项中打开


有一个第三方共享软件应用程序,它的名字让我一时想不起来,它可以让你用键盘命令移动任何窗口(我想可以调整它的大小)。

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

实现这一点的一种方法确实是使用可访问性API

我正在开发的一个应用程序就是这样来获取前窗口、前窗口的文档路径和许多其他属性

我这样做的方式是通过AppleScript。它有时可能很笨拙,但似乎相当可靠。我使用Cocoa应用程序发送AppleScript。它是线程安全的,比脚本桥或NSAppleScript更稳定

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

  • 将最前面的窗口移动到100100

    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
    
  • 将最前面的窗口调整为200300

    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
    
  • 更改最前面应用程序的当前窗口

    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
    
  • 激活的窗口

    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,它将把这个AppleScript转换为调用AppScript中相关命令的目标C代码


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

    需要在系统首选项中启用可访问性才能使其工作。它是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
    

    使用CGWindowListCopyWindowInfo获取每个窗口的KCGWindowerPID。然后,如果您想要访问ObjectiveC内容,或者对于其他内容,您可以使用“分布式对象”。所有这些都记录在


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

    我想要自动化第三方应用程序。为此,我需要能够获取应用程序的当前状态并向其发送鼠标/键盘事件。ResizeWindow将帮助我通过屏幕抓取获取当前状态,并且需要ActivateWindow才能可靠地将鼠标/键盘事件发送到应用程序。GetCurrentlyActivatedWidow将用于恢复原始的活动窗口,以便在不与用户尽可能多地交互的情况下让自动化工作。MoveWindow将是开发此应用程序的“好东西”。好的,在这种情况下,您应该研究可访问性/脚本API。任何Cocoa应用程序都具有一定程度的可编写性,这可能是您所需要的。是的,MercuryMover就是它。:-)这些代码示例在几个方面对我有所帮助,因为我希望实现与Sami相同的功能:谢谢!没问题。很高兴能为我提供帮助-这个社区为我的问题提供了很多很好的答案,能够提供一些反馈真是太好了。有没有一种方法可以只关注窗口,而不需要访问?我的用例是,我的应用程序有焦点,它列出了所有正在运行的应用程序,在该列表中选择一个应用程序将聚焦它。当前,如果我使用
    activateWithOptions:
    则不会取消最小化窗口的动画,因此如果所有窗口都最小化,则不会执行任何操作。因此,我试图找到另一种方法来关注(这是uniminimizes)Hi bgri,请您提供一些示例代码。我使用了
    CGWindowListCopyWindowInfo
    来获取所有的
    kCGWindowOwnerPID
    s,但我不知道如何通过它来聚焦窗口。