15

我正在使用辅助功能 API 来检测某个应用程序何时打开窗口、关闭窗口、何时移动或调整窗口大小,或者何时成为主窗口和/或焦点窗口。但是,客户端应用程序似乎将一个窗口移到了前面,而没有触发 Accessibility API 通知。

我的应用程序如何检测另一个应用程序何时将一个窗口置于前面而不使其成为关键?

我希望找到适用于 OS X 10.4 和 10.5 的解决方案

更多信息:我目前正在使用这些语句。当用户手动选择一个窗口将其置于前面时,它们可以正常工作。但是当应用程序本身将窗口带到前面时,它就不起作用了。

AXObserverAddNotification(observer, element, kAXMainWindowChangedNotification, 0);
AXObserverAddNotification(observer, element, kAXFocusedWindowChangedNotification, 0);
4

4 回答 4

9

我一直无法订阅当前窗口的变化,但你可以询问当前应用程序的辅助功能API,以及当前应用程序最前台的窗口。

假设您有一个名为 CurrentAppData 的类,其中包含以下数据:

@interface CurrentAppData : NSObject {
    NSString* _title;
    AXUIElementRef _systemWide;
    AXUIElementRef _app;
    AXUIElementRef _window;
}

查找当前应用程序的代码如下所示:

-(void) updateCurrentApplication {
   // get the currently active application  
   _app = (AXUIElementRef)[CurrentAppData
                           valueOfExistingAttribute:kAXFocusedApplicationAttribute 
                                        ofUIElement:_systemWide];

   // Get the window that has focus for this application
   _window = (AXUIElementRef)[CurrentAppData 
                              valueOfExistingAttribute:kAXFocusedWindowAttribute 
                                           ofUIElement:_app];

   NSString* appName = [CurrentAppData descriptionOfValue:_window
                                             beingVerbose:TRUE];    

   [self setTitle:appName];
}

在本例中,_systemWide 变量在类 init 函数中被初始化为: _system = AXUIElementCreateSystemWide();

类函数 valueOfExistingAttribute 如下所示:

// -------------------------------------------------------------------------------
//  valueOfExistingAttribute:attribute:element
//
//  Given a uiElement and its attribute, return the value of an accessibility
//  object's attribute.
// -------------------------------------------------------------------------------
+ (id)valueOfExistingAttribute:(CFStringRef)attribute ofUIElement:(AXUIElementRef)element
{
    id result = nil;
    NSArray *attrNames;

    if (AXUIElementCopyAttributeNames(element, (CFArrayRef *)&attrNames) == kAXErrorSuccess) 
    {
        if ( [attrNames indexOfObject:(NSString *)attribute] != NSNotFound
                &&
            AXUIElementCopyAttributeValue(element, attribute, (CFTypeRef *)&result) == kAXErrorSuccess
        ) 
        {
            [result autorelease];
        }
        [attrNames release];
    }
    return result;
}

前面的函数取自 Apple UIElementInspector示例,这也是学习 Accessibility API 的一个很好的资源。

于 2009-03-09T02:53:45.770 回答
5

在 Mac OS X 中,应用程序和窗口是完全独立的事物,应用程序包含窗口;它们与以前在 Microsoft Windows 中不同。您需要检测每个应用程序的激活和停用。

你可以通过观察 forkAXApplicationActivatedNotification和来做到这一点kAXApplicationDeactivatedNotification。这些通知的对象是被激活和停用的应用程序。您还需要检测应用程序的启动和退出;您可以使用 Process Manager 或 NSWorkspace 来执行此操作。这两个 API 都可以为您提供进程 ID,您可以使用它来创建 AXApplication 对象。

于 2009-03-09T03:52:55.813 回答
5

查看开发人员文档中的iChatStatusFromApplication示例。这正是你需要的:)

于 2011-02-16T11:17:54.553 回答
2

NSAccessibilityFocusedUIElementChangedNotification怎么样?

于 2009-03-14T23:45:54.513 回答