【问题标题】:How can I move/resize windows programmatically from another application?如何以编程方式从另一个应用程序移动/调整窗口大小?
【发布时间】:2010-11-20 03:43:14
【问题描述】:

我知道,我可以使用 Apple 事件对象模型来移动和调整 Cocoa 应用程序窗口的大小。但是我可以将什么用于 Carbon 应用程序?

【问题讨论】:

    标签: macos macos-carbon


    【解决方案1】:

    Peter 是对的,您可以使用以下 AppleScript 访问任何窗口的边界:

    tell application "System Events"
        set allProcesses to application processes
        repeat with i from 1 to count allProcesses
            tell process i
                repeat with x from 1 to (count windows)
                    position of window x
                    size of window x
                end repeat
            end tell
        end repeat
    end tell
    

    【讨论】:

      【解决方案2】:

      您还可以使用辅助功能 API。这就是我认为 Optimal Layout 的做法。

      首先,您必须确保您的应用有权使用它。

      BOOL checkForAccessibility()
      {
          NSDictionary *options = @{(__bridge id) kAXTrustedCheckOptionPrompt : @YES};
          return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef) options);
      }
      

      接下来,使用 NSWorkspace::RunningApplications 获取您要操作其窗口的应用程序的 PID。

      NSArray<NSRunningApplication *> *runningApps =[[NSWorkspace sharedWorkspace] runningApplications];
      for( NSRunningApplication *app in runningApps )
      {
          if( [app bundleIdentifier] != nil && [[app bundleIdentifier] compare:@"IdentifierOfAppYouWantToFindHere"] == 0 )
          {
              PID = [app processIdentifier];
          }
      }
      

      然后使用 PID 通过 Accessibility API 访问主窗口引用。

      AXUIElementRef app = AXUIElementCreateApplication( PID );
      AXUIElementRef win;
      AXError error = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, ( CFTypeRef* )&win );
      while( error != kAXErrorSuccess )   // wait for it... wait for it.... YaY found me a window! waiting while program loads.
          error = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, ( CFTypeRef* )&win );
      

      现在您可以使用以下方式设置大小和位置:

      CGSize windowSize;
      CGPoint windowPosition;
      windowSize.width = width;
      windowSize.height = height;
      windowPosition.x = x;
      windowPosition.y = y;
      AXValueRef temp = AXValueCreate( kAXValueCGSizeType, &windowSize );
      AXUIElementSetAttributeValue( win, kAXSizeAttribute, temp );
      temp = AXValueCreate( kAXValueCGPointType, &windowPosition );
      AXUIElementSetAttributeValue( win, kAXPositionAttribute, temp );
      CFRelease( temp );
      CFRelease( win );
      

      【讨论】:

      • 我有类似的代码,我试图根据鼠标移动控制调整大小,但我无法让它像拉角一样平滑/快速;知道为什么吗?
      • 我不建议再使用上面的代码了。自 Mojave 以来,在我的应用程序中使用上述代码时,我遇到了严重的性能问题。它导致似乎整个系统冻结。 Apple 曾表示尝试使用 Applescript 方法,但我仍在努力解决这个问题。我不认为这种方法可以很好地完成您尝试调整鼠标大小的操作。
      • 我提到的代码实际上是您上面的代码,但用于移动应用程序窗口 - 我没有看到任何性能问题;它几乎是即时的。但是当我尝试时调整大小是一个问题。我可能只是捕捉到一个值的倍数来隐藏滞后。感谢回复!
      【解决方案3】:

      同样的事情。您可以在任何可编写脚本的应用程序上使用 Apple Events,而且 Apple Events 和可编写脚本比 Carbon 早了很多。

      【讨论】:

      • 但是对于不支持脚本功能的应用程序(如跨平台应用程序)我该怎么办?
      • 跨平台并不意味着无法编写脚本。但无论如何:什么都没有。该应用程序控制着它自己的窗口,因此您必须要求它移动或调整它们的大小。如果它没有为您提供执行此操作的方法,那么您无法移动或调整该应用程序的窗口大小。
      • 我不同意。例如。我有一个名为“PyCharm”的应用程序——跨平台的 python IDE。当我通过“系统事件”询问“有脚本术语”时,它返回 false。但是,它的窗口可以通过“优化布局”之类的应用程序移动/调整大小。
      • 那我建议联系Optimal Layout的开发者,问问他们是怎么做的。 (也许将您问题的链接传递给他们,以便他们可以为每个人发布答案。)除了 Apple 事件管理器及其 Cocoa 和 OSAKit 等效项之外,我想不出任何公共 API 来移动另一个应用程序的窗口。跨度>
      猜你喜欢
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 2011-01-19
      • 2011-04-22
      相关资源
      最近更新 更多