【问题标题】:How can I use Cocoa's Accessibility API to detect that a window is brought to front?如何使用 Cocoa 的 Accessibility API 来检测窗口是否被置于前面?
【发布时间】:2008-12-07 08:51:45
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: cocoa accessibility-api


    【解决方案1】:

    我一直无法订阅当前窗口的变化,但是你可以询问当前应用程序的辅助功能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 的绝佳资源。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:
          猜你喜欢
          • 1970-01-01
          • 2021-11-28
          • 1970-01-01
          • 1970-01-01
          • 2011-01-06
          • 2010-10-25
          • 1970-01-01
          • 1970-01-01
          • 2017-05-11
          相关资源
          最近更新 更多