2009-10-22 15 views

risposta

12

Qualche referenza potenzialmente utili:

CGSGetWindowProperty è 0.123., ma credo che lo si può utilizzare con l'un capo di NSWindowList() come segue (completamente non testata):

OSErr err; 
CGSValue titleValue; 
char *title; 
CGSConnection connection = _CGSDefaultConnection(); 
int windowCount, *windows, i; 

NSCountWindows(&windowCount); 
windows = malloc(windowCount * sizeof(*windows)); 
if (windows) { 
    NSWindowList(windowCount, windows); 
    for (i=0; i < windowCount; ++i) { 
     err = CGSGetWindowProperty(connection, windows[i], 
        CGSCreateCStringNoCopy("kCGSWindowTitle"), 
        &titleValue); 
     title = CGSCStringValue(titleValue); 
    } 
    free(windows); 
} 

In AppleScript, è davvero facile:

tell application "System Events" to get the title of every window of every process 

È possibile chiamare AppleScript dall'interno di un applicazione utilizzando NSAppleScript o utilizzare appscript come un bridge ObjC-AppleScript. Con Leopard, è possibile utilizzare il (codice più non testato) Scripting Bridge:

SystemEventsApplication *systemEvents = [SBApplication applicationWithBundleIdentifier:@"com.apple.systemevents"]; 
SBElementArray *processes = [systemEvents processes]; 
for (SystemEventsProcess* process in processes) { 
    NSArray *titles = [[process windows] arrayByApplyingSelector:@selector(title)]; 
} 

Si potrebbe anche provare in una lunga telefonata, se non si cura di leggibilità.

SystemEventsApplication *systemEvents = [SBApplication applicationWithBundleIdentifier:@"com.apple.systemevents"]; 
NSArray *titles = [[[systemEvents processes] 
        arrayByApplyingSelector:@selector(windows)] 
       arrayByApplyingSelector:@selector(arrayByApplyingSelector:) 
       withObject:@selector(title)]; 

Il compilatore lamentano che @selector(title) è il tipo sbagliato, ma dovrebbe funzionare. Consegnare alcune delega a mano e trasformare la chiamata in [[[systemEvents processes] windows] title].

+2

Nota che AppleScript sta utilizzando le interfacce di accessibilità, che sono pubbliche e hanno equivalenti C (vedi http://developer.apple.com/mac/library/documentation/Accessibility/Reference/AccessibilityLowlevel/). Le API CGS * non solo non sono documentate, possono cambiare in qualsiasi momento. (Quindi, usali solo se sei disposto a testare in anticipo e spesso su nuove versioni del SO e non hai altra scelta.) –

+1

Hai un esempio di utilizzo per l'API di accessibilità? Speravo di includerlo, ma non ho abbastanza familiarità con esso per fornire come usarlo. – outis

+0

Inoltre, richiede che l'accessibilità sia abilitata. – outis

8

L'intestazione CGSPrivate.h che gira intorno non è direttamente compatibile con OS X 10.8 in quanto CGSGetWindowProperty() non esiste più (beh, lo fa, ma non è più possibile collegarsi ad esso). Quindi aggiungere queste due righe al file CGSPrivate.h - sono andato avanti e capito questo io stesso dopo molte ore alla ricerca di Google - per farlo funzionare:

extern CGSConnection CGSDefaultConnectionForThread(void); 
extern CGError CGSCopyWindowProperty(const CGSConnection cid, NSInteger wid, CFStringRef key, CFStringRef *output); 

Adattare il codice di Outis, ecco un modo di scorrere attraverso il titolo di ogni finestra. Ho testato questo con clangore 4.2 su Mountain Lion:

CFStringRef titleValue; 
CGSConnection connection = CGSDefaultConnectionForThread(); 
NSInteger windowCount, *windows; 

NSCountWindows(&windowCount); 
windows = (NSInteger*) malloc(windowCount * sizeof(NSInteger)); 
if (windows) { 
    NSWindowList(windowCount, windows); 
    for (int i = 0; i < windowCount; ++i) 
    { 
     CGSCopyWindowProperty(connection, windows[i], CFSTR("kCGSWindowTitle"), &titleValue); 

     if(!titleValue) //Not every window has a title 
      continue; 

     //Do something with titleValue here 
    } 
    free(windows); 
} 

alcune altre cose ho scoperto che include quanto segue:

  1. Nessun titolo della finestra supera 127 byte.
  2. titoli della finestra sono codificati con kCFStringEncodingMacRoman

Quindi, se si vuole come un C-string, scrivere qualcosa di simile:

char *cTitle[127] = {0}; 
CFStringGetCString(titleValue,cTitle,127,kCFStringEncodingMacRoman); 

Personalmente, mi consiglia di farlo in questo modo in quanto l'API di accessibilità è un dolore totale e richiede autorizzazioni extra.

Spero che questo aiuti qualcuno! Saluti!

+0

Grazie per questa risposta, ma per quanto riguarda la portabilty? 'CGS_xx' non può essere trovato e/o deprecato da' 10.6'. Codice per 10.8.2 ML e certamente non posso contare su cose deprecate. –

+0

Bene, il codice che ho dato sopra è stato testato su Mountain Lion. Non è che non possa essere trovato tanto quanto è cambiato. Il lavoro di inversione che ho fatto sopra fornisce le firme corrette che ti permetteranno di risolvere ** questo particolare problema ** usando 'CGS_xx'. Non ho provato nulla di diverso dai titoli delle finestre. Se ritieni di doverlo utilizzare, probabilmente dovresti rilasciare più versioni del pacchetto (ad es. Per 10.6 o inferiore o per 10.7+) –

Problemi correlati