2016-07-30 7 views
1

schließen, aber ich bin nicht neu in der Programmierung. Ich versuche eine immer laufende Menüleiste App auf ein bestimmtes Fenster in einer Anwendung zu hören, um geöffnet zu werden und dann dieses Fenster zu schließen, aber nicht die Anwendung. Hier ist mein aktueller Ansatz, es ist meist eine Mischung aus anderen SO Antworten, die ich gefunden habe.Fenster auf der Basis von kCGWindowName Wert

func applicationDidFinishLaunching(aNotification: NSNotification) { 
    // listener for when user switches applications 
    NSWorkspace.sharedWorkspace().notificationCenter.addObserver(self, 
                   selector: #selector(activated), 
                   name: NSWorkspaceDidActivateApplicationNotification, 
                   object: nil) 
} 

func activated(notification: NSNotification) { 

    // i feel like i should be using that NSNotification but I'm not 

    let options = CGWindowListOption(arrayLiteral: CGWindowListOption.ExcludeDesktopElements, CGWindowListOption.OptionOnScreenOnly) 
    let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0)) 
    let infoList = windowListInfo as NSArray? as? [[String: AnyObject]] 

    for item in infoList! { 

     // if i find the window i want to close 
     if item[kCGWindowName as String] == "Warnings" { 
      // close window item[kCGWindowName] 
     } 

    } 

Meine Frage ist, wenn ich noch etwas von diesem Recht tue, wie schließe ich das Fenster basierte weg von seiner windowListInfo zu haben?

Auch die item[kCGWindowName as String] sagt Cannot convert value of type 'AnyObject?' to expected argument type String. Wie würde ich gehen über die Überprüfung von Fenstern für den Namen, den ich möchte, ohne auf eine Zeichenfolge zu werfen? Ich habe print() für alle Objekte in der InfoList aufgerufen und einen kCGWindowName-Wert mit dem Namen des Fensters, nach dem ich suche, gesehen, also weiß ich, dass es dort ist.

Vielen Dank im Voraus.

+1

gibt es keine einfache Möglichkeit, dies zu tun.Ihre beste Wette wäre wahrscheinlich, die Accessibility-APIs anstelle von CGWindowList zu verwenden. –

+0

Danke für das Feedback @KenThomases. Macht es Ihnen etwas aus, mir in die richtige Richtung zu zeigen oder mir ein paar Tipps zur Accessibility API zu geben? Ich habe es noch nie zuvor benutzt. –

Antwort

1

Sie können die Zugänglichkeit API verwenden:

  • Sie benötigen Zugriff auf Ihre Anwendung oder Xcode (wenn Sie testen Ihre Anwendung von Xcode) zu ermöglichen.
  • Öffnen Sie den Bereich "Sicherheit & Datenschutz" im Fenster "Systemeinstellungen" . Klicken Sie auf die Registerkarte "Datenschutz".

  • Wählen Sie "Erreichbarkeit" aus der Liste im linken Bereich.

  • Klicken Sie auf das Schlosssymbol, um Änderungen vorzunehmen.

  • Ziehen Sie Ihre Anwendung oder setzen Sie Xcode in den rechten Bereich.


Hier ist ein Beispiel für den SWIFT-Code (Swift-Version 2.2) mit einem Klick auf dem roten Knopf des Fensters, das der Titel beginnt mit "Warnungen" zu simulieren:

func activated(notification: NSNotification) { 
    if (notification.userInfo![NSWorkspaceApplicationKey]!.localizedName) == "Pages" { // when "Pages" application is active only 
     let myApp = AXUIElementCreateApplication(notification.userInfo![NSWorkspaceApplicationKey]!.processIdentifier).takeUnretainedValue() 
     let val1 = UnsafeMutablePointer<AnyObject?>.alloc(1) 

     if AXUIElementCopyAttributeValue(myApp, kAXWindowsAttribute, val1).rawValue == 0 { // get windows of the "Pages" application 
      let windowList = val1.memory as? [AXUIElement] ?? [] 
      for w in windowList { // loop each window, get the title of the window, and check if the title starts with "Warning" 
       if AXUIElementCopyAttributeValue(w, kAXTitleAttribute, val1).rawValue == 0 && (val1.memory as! String).hasPrefix("Warnings") { 
        if AXUIElementCopyAttributeValue(w, kAXCloseButtonAttribute, val1).rawValue == 0 {// get the red button of the window 
         AXUIElementPerformAction(val1.memory as! AXUIElement, kAXPressAction); // close the window 
        } 
       } 
      } 
     } 
     val1.dealloc(1) 
    } 
} 

Um den Titel gleich zu überprüfen "Warnungen": verwenden Sie val1.memory as! String == "Warnings"


Informationen auf die infoList aus dem Code:

Wie würde ich über das Einchecken Fenster für den Namen gehe ich ohne in einen String Casting will?

eine Zeichenfolge anstelle der Konstante verwenden, wie folgt aus:

if item["kCGWindowName"]! as! String == "Warnings" {