2009-05-12 12 views

risposta

41

È necessario utilizzare le API di accessibilità, che sono plain-C, situate all'interno del framework ApplicationServices. Per esempio:

Prima si crea un oggetto applicazione:

AXUIElementRef app = AXUIElementCreateApplication(targetApplicationProcessID); 

Quindi si ottiene la finestra da questo. È possibile richiedere l'elenco di finestre ed eseguire l'enumerazione oppure è possibile ottenere la finestra in primo piano (consultare AXAttributeConstants.h per tutti i nomi di attributo che si utilizzano).

AXUIElementRef frontWindow = NULL; 
AXError err = AXUIElementCopyAttributeValue(app, kAXMainWindowAttribute, &frontWindow); 
if (err != kAXErrorSuccess) 
    // it failed -- maybe no main window (yet) 

Ora è possibile richiedere la notifica tramite una funzione di richiamata C quando viene modificata una proprietà di questa finestra. Si tratta di un processo in quattro fasi:

prima cosa è necessario una funzione di callback per ricevere le notifiche:

void MyAXObserverCallback(AXObserverRef observer, AXUIElementRef element, 
          CFStringRef notificationName, void * contextData) 
{ 
    // handle the notification appropriately 
    // when using ObjC, your contextData might be an object, therefore you can do: 
    SomeObject * obj = (SomeObject *) contextData; 
    // now do something with obj 
} 

Dopodiché è necessario un AXObserverRef, che gestisce la routine di callback. Ciò richiede lo stesso ID di processo utilizzato per creare l'elemento 'app' sopra:

AXObserverRef observer = NULL; 
AXError err = AXObserverCreate(applicationProcessID, MyObserverCallback, &observer); 
if (err != kAXErrorSuccess) 
    // handle the error 

Dopo aver ottenuto il vostro osservatore, il passo successivo è quello di richiedere la notifica di certe cose. Vedere AXNotificationConstants.h per l'elenco completo, ma per cambiare la finestra avrete probabilmente bisogno solo questi due:

AXObserverAddNotification(observer, frontWindow, kAXMovedNotification, self); 
AXObserverAddNotification(observer, frontWindow, kAXResizedNotification, self); 

Si noti che l'ultimo parametro si sta passando un oggetto 'sé' assunto come contextData. Questo non viene mantenuto, quindi è importante chiamare AXObserverRemoveNotification quando questo oggetto scompare.

Dopo aver ottenuto il vostro osservatore e ha aggiunto le richieste di notifica, ora si desidera collegare l'osservatore al runloop modo da poter essere inviato queste notifiche in modo asincrono (o addirittura affatto):

CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop], 
        AXObserverGetRunLoopSource(observer), 
        kCFRunLoopDefaultMode); 

AXUIElementRef s sono oggetti in stile CoreFoundation, quindi è necessario utilizzare CFRelease() per eliminarli in modo pulito. Ad esempio, per la pulizia, ad esempio, dovresti utilizzare CFRelease(app) dopo aver ottenuto l'elemento frontWindow, dal momento che non avrai più bisogno dell'app.

Una nota su immondizia-Collection: Per mantenere un AXUIElementRef come variabile membro, dichiarare questo modo:

__strong AXUIElementRef frontWindow; 

Questo indica al garbage collector per tenere traccia di questo riferimento. Quando lo si assegna, per compatibilità con GC e non GC, utilizzare questo:

frontWindow = (AXUIElementRef) CFMakeCollectable(CFRetain(theElement)); 
+0

Risposta molto dettagliata e interessante. Grazie! –

+1

ottimo punto di partenza! Non dimenticare di dare un'occhiata alla documentazione https://developer.apple.com/library/mac/documentation/Accessibility/Reference/AccessibilityLowlevel/AccessibilityLowlevel.pdf e l'applicazione di esempio https://developer.apple.com/library/mac/#samplecode/iChatStatusFromApplication/Introduction/Intro.html – vinzenzweber

+2

anche l'esempio di UIElementInspector i progetti sembrano essere molto utili https://developer.apple.com/library/mac/#samplecode/UIElementInspector/Introduction/Intro.html – vinzenzweber

3

ulteriori ricerche alzato "Servizi di visualizzazione quarzo"

La funzione interessante per le mie esigenze è CGRegisterScreenRefreshCallback.

Problemi correlati