In Cocoa sul Mac, vorrei rilevare quando una finestra appartenente a un'altra app viene spostata, ridimensionata o ridipinta. Come posso fare questo?Come può la mia app rilevare una modifica alla finestra di un'altra app?
risposta
È 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));
ulteriori ricerche alzato "Servizi di visualizzazione quarzo"
La funzione interessante per le mie esigenze è CGRegisterScreenRefreshCallback.
- 1. Come può la mia app Android rilevare una chiamata interrotta?
- 2. Come collego la mia estensione alla mia app per Android?
- 3. Vai alla schermata App permessi app della mia app
- 4. Come aggiungere la mia app alla ricerca locale di Google?
- 5. La mia app può accedere alla cartella Notes (app Apple) in iOS?
- 6. Apertura di App Store alla tariffa dall'interno della mia app
- 7. Quali vantaggi può offrire Vaadin alla mia app GWT Appengine?
- 8. Ottenere il link alla mia app su play.google prima di pubblicare la mia app
- 9. Mac/Cocoa: incorporare una finestra di terminale nella mia app
- 10. link di interruzione alla mia app
- 11. Aggiunta di una hot-key alla mia app Delphi
- 12. Come posso aggiungere una scheda app alla mia pagina Facebook?
- 13. Come limitare la mia app alla modalità orizzontale?
- 14. Come posso ottenere dati in tempo reale dalla mia app di App Engine di produzione alla mia app dev locale?
- 15. In che modo la mia app Parse.com può inviare un'email?
- 16. Come concedere le autorizzazioni di sistema alla mia app Android?
- 17. Heroku rileva erroneamente la mia app Node come app Ruby
- 18. NSLog rallenterà la mia app?
- 19. La mia app per Android può rilevare se è stata avviata da Eclipse?
- 20. Come posso condividere un'immagine alla mia app Cordova/PhoneGap da un'altra app?
- 21. SDK iOS di Facebook che non torna alla mia app
- 22. Come devo testare la mia app Rails?
- 23. Come posso mantenere la mia app inattiva?
- 24. Come aggiungere "Ricordami" alla mia app con passaporto
- 25. Come aprire l'immagine nella mia app ios da un'altra app?
- 26. Perché la mia app Qt 4.5 apre una finestra della console sotto Windows?
- 27. Come rendere la mia app rimasta su app a schermo intero
- 28. Posso rilevare che è stata rimossa una particolare autorizzazione per la mia app Android?
- 29. Come evitare una condizione di competizione nella mia app Rails?
- 30. Come evitare di visualizzare la mia app nell'elenco delle app utilizzate di recente
Risposta molto dettagliata e interessante. Grazie! –
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
anche l'esempio di UIElementInspector i progetti sembrano essere molto utili https://developer.apple.com/library/mac/#samplecode/UIElementInspector/Introduction/Intro.html – vinzenzweber