关闭窗口基于kCGWindowName值

时间:2016-07-30 07:38:30

标签: swift macos

但我对编程并不陌生。我试图让一个总是运行的菜单栏应用程序监听要打开的应用程序中的特定窗口,然后关闭该窗口,而不是应用程序。这是我目前的方法,它主要是我找到的其他SO答案的混合。

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]
        }

    }

我的问题是,如果我正在做任何这样的权利,我如何根据其windowListInfo关闭窗口?

此外,item[kCGWindowName as String]正在说Cannot convert value of type 'AnyObject?' to expected argument type String.如何在不转换为字符串的情况下检查窗口中是否存在我想要的名称?我在infoList中的所有对象上调用了print(),并且看到了一个kCGWindowName值,其中包含我正在寻找的窗口的名称,所以我知道它在那里。

提前致谢。

1 个答案:

答案 0 :(得分:1)

您可以使用辅助功能API:

  • 您需要启用应用程序的辅助功能或 Xcode (如果 你从Xcode测试你的应用程序。)
  • 打开“系统偏好设置”中的“安全和隐私”窗格 窗口。点击“隐私”标签。

  • 从左侧窗格的列表中选择“辅助功能”。

  • 点击锁定图标进行更改。

  • 在右侧窗格中拖放您的应用程序或 Xcode

以下是swift代码( Swift版本2.2 )的示例,用于模拟窗口红色按钮的点击,其标题以“警告”开头“:

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

要检查标题等于“警告”:请使用val1.memory as! String == "Warnings"

您代码中infoList的信息:

  

如何在不使用我想要的名称的情况下检查窗口   转换为String?

使用字符串而不是常量,如下所示:

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