OS X

2011-09-14 27 views
26

'daki etkin pencereyi benzersiz olarak tanımlayın Erişilebilirlik API'sini kullanarak pencereleri yeniden boyutlandıran an application dosyasını yamalamaya çalışıyorum.OS X

Önceki boyuttaki pencereleri olan bir sözlüğü korumam gerekir. Anahtar şu an aktif olan pencereyi tanımlamalıdır. Şu anda bu aktif pencere, bir kısayol tuşuna basılarak NSAccessibilityFocusedWindowAttribute aracılığıyla alınır.

Ancak, her seferinde bu yöntem çağrıldığında, numaralı pencereyi tanımlayan döndürülen AXUIElementRef farklı! Bu, onu bir sözlük anahtarı olarak kullanamayacağım anlamına gelir - sözlük karşılık gelen girişi bulamıyor.

-(IBAction)testWindowIdentification:(id)sender{ 
    AXUIElementRef focusedApp; 
    AXUIElementRef focusedWindow; 

    AXUIElementCopyAttributeValue(_systemWideElement, 
            (CFStringRef) kAXFocusedApplicationAttribute, 
            (CFTypeRef*) &focusedApp); 
    AXUIElementCopyAttributeValue((AXUIElementRef) focusedApp, 
            (CFStringRef) NSAccessibilityFocusedWindowAttribute, 
            (CFTypeRef*) &focusedWindow); 
    CFShow(focusedWindow); 
} 

_systemWideElementAXUIElementCreateSystemWide() bir çağrı kullanarak init yöntemi başlatıldı edilmiştir:

Aşağıdaki kod sorunu yeniden üretir. documentation on AXUIElement benzersiz bir özelliği alır bir yöntem göstermez

<AXUIElement 0x47e850> {pid=42463} 
<AXUIElement 0x47e890> {pid=42463} 
<AXUIElement 0x47e2c0> {pid=42463} 
… 

:

CFShow ifadesi açıkça farklı kimlikleri benim için işe yaramaz yöntemi denir her zaman (aynı pencere aktif olsa bile), gösterir UI öğesi için ve that of the NSAccessibility protocol. Benzersiz PID, benim için yeterli olan değil, çünkü bir işlem birden çok pencereye sahip olabilir.

Kakao'da etkin pencerenin bazı benzersiz tanımlayıcılarını nasıl alabilirim?

(Bu arada, gerçek kod yukarıdaki aramalar dönüş kodları kontrol ediyor, hiçbir hata var, çağrılar başarılı.)

+1

@JeremyBanks Orijinal yanıtlayıcı burada doğru fikre sahiptir. Eğer gerçekten [bu cevap] (http://stackoverflow.com/a/312099/517815) olduğuna inanılırsa, odaklanmış pencereyi belirledikten sonra bir 'CGWindowID' almak için Quartz kullanabilirsiniz. Bu _should_ size umuduyorsunuz benzersiz pencere tanımlayıcısı, mevcut uygulamanızın bağlamında cezasızlıkla geçebilirsiniz. Bunun gerçek bir cevap olarak daha tutarlı ve tam bir versiyonunu öğrenmek isterseniz bana bildirin. – MrGomez

+0

@MrGomez Elbette, bunun gibi bir cevap harika olurdu. :) –

+0

@JeremyBanks Yapacak. Bugün biraz fazla yüklü durumdayım, ama bu akşam daha sonra bu akşam (PST) bir cevap almaya çalışacağım. :) – MrGomez

cevap

16

Rob Keniger, his answer here ile doğru stratejiye sahiptir. Bu cevabın eksikliğinden (ve aslında, ödülün yerleştirilmesinin nedenlerinden) gelen tek şey, mevcut aktif pencereyi alan ve onu mevcut çalışma uygulaması bağlamında indekslemeye uygun benzersiz bir anahtar haline dönüştüren uygulanabilir bir uygulamadır.

Rob'in çözümü, Quartz Pencere Servisleri bağlamında verilen CGWindowID'u kullanarak bunu ortaya çıkarır. Tabii ki, bu pencere referansının only useful for your current application olduğunu kuvvetle ima ediyor.

Erişilebilirlik API'si ve Quartz Pencere Hizmetleri arasında güçlü bir garanti olmadığı için bu pencereyi başvurmak zor bir işlemdir. Ancak, aşağıdaki şekillerde bu çalışabilirsiniz:

  1. Kullanım extern "C" AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out);, documented here olarak.Bu, çalışmak için garantili değildir, ancak OSX sürümünüzde çalışıyorsa işleri başlatmak için bir zemin kat testi olarak çalışır.

  2. Doğrudan HIWindowGetCGWindowID() kullanarak CGWindowID numaralı telefonu alın. Etkin pencerenin seçilmesi ve kimliğin çıkarılması ile ilgili daha fazla ayrıntı the reference manual for the Carbon Window Manager'da bulunabilir (uyarı: büyük PDF).

  3. CGWindowListCreateDescriptionFromArray gibi bir araç kullanarak CGWindowID setini, Rob'un önerdiği gibi kullanarak ayarlayın. Buradaki amaç, Erişilebilirlik API'sı ve Kuvars'ı birleştirme planını bulmaktır, ancak bu, geçerli aktif pencerenizin bağlamına bağlı bir geri arama kullanarak düşünülebilir. Bununla birlikte, doğru bir şekilde geleceğe yönelik olan 'un optimal bir örneğini bilmiyorum. Eğer pencere bunları özel olarak tanımlamak için diğer bazı dekoratör oluşturamıyor iseniz seçeneklerden

, ben, mevcut ihtiyaçları için 2. ile devam tavsiye. Şu anda eski kod tabanında tanımlanmıştır, ancak istediğiniz şeyi yapacağız.

Uygulamanızla iyi şanslar.

+0

Hiçbir pencerenin seçilmediği veya tüm pencerelerin etkin olmadığı (yani kontrol masaüstünde) nasıl algılanır? –

+0

Özür dileriz, "extern" C nasıl kullanılır "AXError _AXUIElementGetWindow (AXUIElementRef, CGWindowID * dışarı);" Swift'de mi? – allenlinli

8

Sana Kuvars Pencere Hizmetleri işlevlerini kullanmak mümkün olabilir düşünüyorum Belirli bir uygulamada şu anda aktif olan pencereleri sıralamak için özellikle CGWindowListCreateDescriptionFromArray.

Bu çağrı, AppKit'ten daha düşük düzeydedir ve etkin pencerenin hangisi olduğunu söylemeyecektir, ancak geçerli kullanıcı oturumu için benzersiz olan pencere kimliklerini size verecektir. Bu harika bir çözüm değil, ancak pencere sınırları bilgilerini, gerçek kimlikleriyle pencereleri ilişkilendirmek için erişilebilirlik API'larından aldığınız bilgilerle karşılaştırabilirsiniz.