2009-11-13 13 views
11

Estoy tratando de controlar ventanas de aplicaciones OSX extranjeras desde mi aplicación. Me gustaría a 1. Desplazamiento en las ventanas en la pantalla 2. cambiar el tamaño de las ventanas en la pantalla 3. El cambio de la ventana activa en ese momento de la aplicación 4. obtener la ventana activa en ese momento.Control de ventanas OSX

(Y me gustaría hacer esto ya sea a través ObjC/C/++ API C).

¿Cuáles son las llamadas a la API que yo debería estar buscando, teniendo en cuenta que tengo los CGWindowIDs de las ventanas que desea controlar? Es decir, yo esperaría encontrar funciones con las firmas de algo como: MoveWindow(CGWindowID winId, int x, int y), ResizeWindow(CGWindowID winId, int width, int height), Activatewindow(CGWindowID winId), CGWindowID GetCurrentlyActivatedWindow().

Para 3, ya estoy usando SetFrontProcess para hacer que un proceso esté en primer plano, pero esto no me permite seleccionar la ventana específica de un proceso si tiene múltiples.

Respuesta

11

Una forma de hacer esto es utilizar las API de accesibilidad.

Una aplicación que estoy desarrollando está haciendo justamente esto para obtener la ventana frontal, la ruta del documento de la ventana frontal y muchos otros atributos.

La forma en que lo hago es a través de AppleScript. Puede ser torpe a veces, pero parece ser bastante confiable. Uso AppScript para enviar AppleScript desde mi aplicación Cocoa. Es seguro para hilos y más estable que las alternativas, ya sea Scripting Bridge o NSAppleScript.

La parte difícil será identificar una ventana usando su ID de ventana en AppleScript: AppleScript no parece tener una propiedad de ID de ventana que coincida con CGWindowID. Sin embargo, puede obtener cualquier ventana que desee utilizando AppleScript.

  1. Mover Ventana del primer plano a 100, 100

    tell application "System Events" 
    set theprocess to the first process whose frontmost is true 
    set thewindow to the value of attribute "AXFocusedWindow" of theprocess 
        set position of thewindow to {100, 100} 
    end tell 
    
  2. Redimensionar ventana del primer plano a 200, 300

    tell application "System Events" 
        set theprocess to the first process whose frontmost is true 
        set thewindow to the value of attribute "AXFocusedWindow" of theprocess 
        set size of thewindow to {200, 300} 
    end tell 
    
  3. Cambio ventana actual de la aplicación en primer plano

    tell application "System Events" 
        set theprocess to the first process whose frontmost is true 
        set thewindow to the value of attribute "AXFocusedWindow" of theprocess 
        set size of thewindow to {200, 300} 
        windows of theprocess 
        -- Code to get ID of window you want to activate 
        tell window 2 of theprocess -- assuming it's window 2 
          perform action "AXRaise" 
        end tell 
    end tell 
    
  4. ventana que está activa

    tell application "System Events" 
    set theprocess to the first process whose frontmost is true 
    set thewindow to the value of attribute "AXFocusedWindow" of theprocess 
    end tell 
    

No es una aplicación disponible para AppScript llama ASTranslate que convertirá este AppleScript en el código Objective C que llama a los comandos correspondientes en AppScript.

Para obtener más información sobre cómo obtener el tamaño y los límites de las ventanas (estos son solo de lectura), vea la aplicación de ejemplo Son of Grab.

+0

Estos ejemplos de código me han ayudado de varias maneras, ya que quiero lograr lo mismo que Sami. :) ¡Muchas gracias! –

+0

Sin problemas. Fue un placer ayudar - esta comunidad me ha dado tantas respuestas excelentes a mis preguntas que fue agradable poder ofrecer algo de vuelta. –

+0

¿Hay algún método para enfocar solo la ventana, sin accesibilidad? Mi caso de uso es que mi aplicación tiene foco, enumera todas las aplicaciones en ejecución, seleccionar una aplicación en esa lista la enfocará. Actualmente, si uso 'activateWithOptions:' no está minimizando las ventanas minimizadas, por lo que si todas las ventanas están minimizadas, no hace nada. Así que estoy tratando de encontrar otra manera de enfocarme (lo cual minimiza) – Noitidart

0

Creo que deberías explicar por qué quieres hacer esto. Las únicas utilidades que conozco que mueven las ventanas de todas las otras aplicaciones son Spaces y Expose, ambas suministradas por Apple. Si desea tomar una pantalla completa, hay una API pública para eso, pero mover las ventanas de otra aplicación suena sospechoso.

+0

Estoy queriendo automatizar una aplicación de terceros. Para hacer esto, necesito poder obtener el estado actual de la aplicación y enviar eventos de mouse/teclado. ResizeWindow me ayudará a obtener el estado actual mediante el raspado de la pantalla, y se necesita ActivateWindow para poder enviar eventos de mouse/teclado de manera confiable a la aplicación. GetCurrentlyActivatedWindow se usaría para recuperar la ventana activa original, de modo que la automatización funcione sin interferir con el usuario tanto como sea posible. MoveWindow sería simplemente algo 'bueno tener' para desarrollar esto. – Sami

+0

Bueno, ese es el caso en el que deberías consultar la API de Accesibilidad/Scripting. Cualquier aplicación Cocoa recoge algún grado de capacidad de escritura, que puede ser tanto como sea necesario. – NSResponder

1

Basado en su comentario, usted puede hacer esto con el sistema operativo X API de accesibilidad, pero creo que "el acceso a los dispositivos de ayuda" debe estar activada en las preferencias de accesibilidad del usuario.

Hay una aplicación shareware de terceros cuyo nombre no recuerdo en este momento que le permite moverse alrededor de cualquier ventana (y creo que cambiar su tamaño) con los comandos del teclado.

+0

Probablemente estés pensando en MercuryMover: http://www.heliumfoot.com/mercurymover –

+0

o Zooom/2: http://coderage-software.com/zooom/ –

+0

Sí, MercuryMover era. :-) –

0

Soy nuevo aquí, por lo que este tiene que ser presentada como una respuesta en lugar de un comentario. Escribí una aplicación .NET (PlaceMint) hace exactamente esto en Windows y no es sospechoso en absoluto. PlaceMint le ayuda a organizar sus ventanas de una manera estructurada definida por el usuario. Todo lo que hace es hacer cosas como mover o redimensionar ventanas según las reglas definidas por el usuario. Alguien me preguntó si podía hacer un puerto a OSX, pero nunca llegué demasiado lejos porque no pude encontrar una definición de API como la proporcionada en Windows (mapeando llamadas a DLL a user32.dll como SetWindowPos()).

1

Debe habilitarse la accesibilidad en Preferencias del Sistema para que esto funcione. Es un AppleScript, pero podría usarse en Objective-C con el puente de secuencias de comandos.

-- Moves safari window by deltaposition 
tell application "System Events" 
    tell application "Safari" 
     set win to first window 
     set b to bounds of win 
     set deltaposition to {50, 0} 
     set bounds of first window to {(item 1 of b) + (item 1 of deltaposition), (item 2 of b) + (item 2 of deltaposition), (item 3 of b) + (item 1 of deltaposition), (item 4 of b) + (item 2 of deltaposition)} 
    end tell 
end tell 
2

Uso CGWindowListCopyWindowInfo para agarrar el kCGWindowOwnerPID de cada ventana. Luego puede usar "objetos distribuidos" si quiere acceder a material de ObjectiveC, o Mach RPC para otras cosas. Todo esto está documentado en http://developer.apple.com

Existen muchas buenas razones para querer enviar mensajes a otras aplicaciones, por ejemplo cuando se desarrollan interfaces de usuario novedosas que no son ni ratones ni teclados.

+0

Hola bgri, por favor, pueden darme un ejemplo de código. He usado 'CGWindowListCopyWindowInfo' para obtener todos los' kCGWindowPinners ', pero no sé cómo enfocar las ventanas. – Noitidart

Cuestiones relacionadas