2009-10-22 14 views

Respuesta

12

Algunas referencias potencialmente útiles:

CGSGetWindowProperty es not officially documented, pero yo creo que se puede utilizar con el un elemento de NSWindowList() de la siguiente manera (no está comprobado):

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); 
} 

En AppleScript, que es muy fácil:

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

Usted puede llamar applescript desde dentro de una aplicación usando NSAppleScript o use appscript como un puente ObjC-AppleScript. Con Leopard, puede utilizar el (código más no probado) 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)]; 
} 

Incluso se puede probar en una llamada de larga, si no se preocupan por la legibilidad.

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

El compilador se quejará de que @selector(title) es el tipo equivocado, pero debería funcionar. Mano rodar algunas delegaciones y puede convertir la llamada en [[[systemEvents processes] windows] title].

+2

Tenga en cuenta que AppleScript está utilizando las interfaces de accesibilidad, que son públicas y tienen C equivalentes (consulte http://developer.apple.com/mac/library/documentation/Accessibility/Reference/AccessibilityLowlevel/). Las API CGS * no solo no están documentadas, sino que pueden cambiar en cualquier momento. (Por lo tanto, utilícelos solo si está dispuesto a probar temprano y con frecuencia en nuevas versiones del sistema operativo y no tiene otra opción). –

+1

¿Tiene un ejemplo de uso para la API de accesibilidad? Tenía la esperanza de incluirlo, pero no estoy lo suficientemente familiar como para proporcionar cómo usarlo. – outis

+0

Además, requiere que la accesibilidad esté habilitada. – outis

8

El encabezado CGSPrivate.h que está flotando no es directamente compatible con OS X 10.8 en el sentido de que CGSGetWindowProperty() ya no existe (bueno, sí, pero ya no puede vincularlo). Por lo que añadir estas dos líneas al archivo CGSPrivate.h - Me adelanté y cuenta de esto a mí mismo después de muchas horas de búsqueda en Google - para conseguir que funcione:

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

Adaptación de código de Outis, aquí está una manera de iterar a través de cada título de ventana. He probado esto con el sonido metálico de 4,2 león de montaña:

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); 
} 

algunas otras cosas que descubrí incluye lo siguiente:

  1. Sin título de la ventana supera 127 bytes.
  2. nombres de ventanas están codificados con kCFStringEncodingMacRoman

Por lo tanto, si quieres como un C-secuencia, escribir algo como esto:

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

Personalmente, le recomiendo hacerlo de esta manera, ya la API de accesibilidad es un dolor total y requiere permisos adicionales.

Espero que esto ayude a alguien! ¡Aclamaciones!

+0

Gracias por esta respuesta, pero ¿qué tal portabilidad? El 'CGS_xx' no se puede encontrar y/o está obsoleto por' 10.6'. Codigo 10.8.2 ML y ciertamente no puedo confiar en cosas en desuso. –

+0

Bueno, el código que di más arriba fue probado en Mountain Lion. No es que no se pueda encontrar tanto como haya cambiado. El trabajo de inversión que hice arriba proporciona las firmas correctas que le permitirán resolver ** este problema en particular ** usando 'CGS_xx'. No intenté con nada más que títulos de ventanas. Si cree que necesita usar esto, probablemente debería liberar varias versiones de su paquete (es decir, para 10.6 y por debajo o para 10.7+) –

Cuestiones relacionadas