2011-05-30 13 views
19

Üçüncü parti uygulamaların pencerelerini ekran üzerinde hareket ettiren bir uygulama üzerinde çalışıyorum. Pencere Numarasını OSX Erişilebilirlik API'sı Yoluyla Kullanma

, ben Bu, her pencereyi açık tanımlayan sözlükler dizisini döndürür

CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); 

kullanan tüm anda açık pencerelerin genel bir bakış elde etmek.

{ 
    kCGWindowAlpha = 1; 
    kCGWindowBounds =   { 
     Height = 442; 
     Width = 475; 
     X = 3123; 
     Y = "-118"; 
    }; 
    kCGWindowIsOnscreen = 1; 
    kCGWindowLayer = 0; 
    kCGWindowMemoryUsage = 907184; 
    kCGWindowName = Untitled; 
    kCGWindowNumber = 7328; 
    kCGWindowOwnerName = TextEdit; 
    kCGWindowOwnerPID = 20706; 
    kCGWindowSharingState = 1; 
    kCGWindowStoreType = 2; 
    kCGWindowWorkspace = 3; 
}, 

Sözlük başka yerde kullanılan iyi bilgi dolu ama windows' pozisyonlarını değiştirmek için kullanılabilecek bir erişilebilirlik nesnesi yoksun: İşte örnek bir sözlük döndü bu. Pencereler Pencere Numarası ile açıkça tanımlanmıştır.

Şimdi pencerenin uygulaması için bir erişilebilirlik nesnesi oluşturmak için PID (kCGWindowOwnerPID) kullanıyorum:

NSArray *result; 

AXUIElementCopyAttributeValues(
           (AXUIElementRef) app, 
           kAXWindowsAttribute, 
           0, 
           99999, 
           (CFArrayRef *) &result 
           ); 
: Uygulama AXUIElementCopyAttributeValues ​​kullanarak açtı bütün pencerelerin listesini almak Ardından

AXUIElementRef app = AXUIElementCreateApplication(pid); 

Bu, çalışır ve bir dizi AXUIElements döndürür. Burada sıkışıp kaldım. Erişilebilirlik nesnesinin Pencere Numarasını almak için API çağrısı yok gibi görünüyor. Ya

a) Aksi takdirde açıkça tarif pencereyi eşleşir) sonuçta sağ pencere)

veya

b diziyi sürekli tekrarlanması ve bulmak için erişilebilirlik nesnenin Pencere Numarası (Bulma herhangi bir yolu var mı CGWindowListCopyWindowInfo tarafından AXUIElementCopyAttributeValues ​​tarafından döndürülen Erişilebilirlik Nesneleri tarafından döndürülen dizi?

cevap

21

Bu görev için özel bir Erişilebilirlik Geliştirici'yi işe aldık.

Belgelenmemiş API'leri kullanmadan bunu yapmanın bir yolu yok (bizim durumumuzda bir yok).

Döngü uygulamasının tüm açık pencereler üzerinde:

Neyse ki, pratik bir çözüm vardır.

AXUIElementCopyAttributeValue(target, kAXPositionAttribute, CFTypeRef*)&posValue); 
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue); 
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue); 

Sonraki fiili CGPoint ve CGSize değerlere konumunu ve boyutunu dönüştürmek:

AXValueGetValue(posValue, kAXValueCGPointType, &point); 
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size); 

nesne tarafından döndürülen değerlerin karşı boyutu, konumu ve başlığı karşılaştırın konumlarını, boyut ve başlığı alın CGWindowListCopyWindowInfo(). Eşleşirse, aradığınız pencereyi güvenli bir şekilde varsayabilir ve zaten açık olan AXUIElement'i (bizim durumumuzda target) kullanabilirsiniz.

Tüm açık pencerelerden geçiş için ek yük OSX'te göz ardı edilebilir. Aynı anda kaç pencerenin açık olduğu üzerinde oldukça düşük bir kapak var.

Ayrıca, bu% 100 doğru olmasa da (2 pencerenin aynı konumda, boyutta ve başlıkta olması mümkündür), gerçek kullanımda bu durumun gerçekleştiği herhangi bir durumla karşılaşmadık.

+9

Belgelenmemiş API'leri kullananlar için nasıl yapılmalı? – Samuel

8

Pencere için belirli bir AX nesnesi için CG pencere numarasının alınması için özel bir işlev vardır: _AXUIElementGetWindow. SO tartışmasında daha fazla ayrıntı Uniquely identify active window on OS X Görevi% 100 olasılıkla yapmak için ortak bir API yok gibi görünüyor. Pencerelerin başlık ve çerçeve ile tanımlanması (yukarıda açıklandığı gibi) vakaların% 99,9'unda çalışacaktır.