【问题标题】:Getting the position of my application's dock icon using Cocoa's Accessibility API使用 Cocoa 的 Accessibility API 获取我的应用程序停靠图标的位置
【发布时间】:2011-10-04 18:50:26
【问题描述】:

如何使用 Accessibility API 获取应用程序停靠图标的位置?

【问题讨论】:

    标签: cocoa accessibility dock


    【解决方案1】:

    对于 Mac OS El Capitan,看起来您不应该使用 Accessibility API 来获取图标的位置。问题是图标不在应用程序的可访问性对象层次结构中——它可以在系统 Dock 应用程序的层次结构中找到。沙盒应用不应访问其他应用的辅助功能对象。

    已批准答案中的代码不会在控制台中产生任何sandboxd 守护程序的警告,看起来它没有违反任何规则。它使用函数AXUIElementCreateApplication 创建顶级可访问性对象。文档指出,它:

    Creates and returns the top-level accessibility object for the
    application with the specified process ID.
    

    不幸的是,这个顶级对象不是 Dock 图标的祖先。 我尝试运行代码,它会计算第一个应用程序主菜单项的位置(与应用程序本身具有相同的标题)。比较发生在这一行:

    if ([titleValue isEqual:appName]) {
    

    所以我的应用程序的输出总是相同的:

    position: (45.000000, 0.000000)
    

    尝试访问其他应用的辅助功能对象时在控制台中产生了警告。我想必须找到另一种计算图标位置的方法。

    【讨论】:

      【解决方案2】:

      找到了!使用this forum post 作为参考,我能够将给定的示例代码塑造成我需要的样子:

      - (NSArray *)subelementsFromElement:(AXUIElementRef)element forAttribute:(NSString *)attribute
      {
          NSArray *subElements = nil;
          CFIndex count = 0;
          AXError result;
      
          result = AXUIElementGetAttributeValueCount(element, (CFStringRef)attribute, &count);
          if (result != kAXErrorSuccess) return nil;
          result = AXUIElementCopyAttributeValues(element, (CFStringRef)attribute, 0, count, (CFArrayRef *)&subElements);
          if (result != kAXErrorSuccess) return nil;
      
          return [subElements autorelease];
      }
      
      - (AXUIElementRef)appDockIconByName:(NSString *)appName
      {
          AXUIElementRef appElement = NULL;
      
          appElement = AXUIElementCreateApplication([[[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"] lastObject] processIdentifier]);
          if (appElement != NULL)
          {
              AXUIElementRef firstChild = (__bridge AXUIElementRef)[[self subelementsFromElement:appElement forAttribute:@"AXChildren"] objectAtIndex:0];
              NSArray *children = [self subelementsFromElement:firstChild forAttribute:@"AXChildren"];
              NSEnumerator *e = [children objectEnumerator];
              AXUIElementRef axElement;
              while (axElement = (__bridge AXUIElementRef)[e nextObject])
              {
                  CFTypeRef value;
                  id titleValue;
                  AXError result = AXUIElementCopyAttributeValue(axElement, kAXTitleAttribute, &value);
                  if (result == kAXErrorSuccess)
                  {
                      if (AXValueGetType(value) != kAXValueIllegalType)
                          titleValue = [NSValue valueWithPointer:value];
                      else
                          titleValue = (__bridge id)value; // assume toll-free bridging
                      if ([titleValue isEqual:appName]) {
                          return axElement;
                      }
                  }
              }
          }
      
          return nil;
      }
      
      - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
      {
          AXUIElementRef dockIcon = [self appDockIconByName:@"MYAPPNAME"];
          if (dockIcon) {
              CFTypeRef value;
              CGPoint iconPosition;
              AXError result = AXUIElementCopyAttributeValue(dockIcon, kAXPositionAttribute, &value);
              if (result == kAXErrorSuccess)
              {
                  if (AXValueGetValue(value, kAXValueCGPointType, &iconPosition)) {
                      NSLog(@"position: (%f, %f)", iconPosition.x, iconPosition.y);
                  }
              }
          }
      }
      

      【讨论】:

      • 如果您的目标是 10.6,则获取 Dock 进程标识符要容易得多:[[[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"] lastObject] processIdentifier]
      • @0xced:谢谢!根据您的建议,我对代码进行了一些清理。
      • 注意:建议的代码不适用于 ARC。我的演员阵容有问题...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      • 2011-01-06
      • 2014-08-10
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      相关资源
      最近更新 更多