改变NSWindow标题文本的颜色

时间:2012-09-07 17:25:33

标签: cocoa nswindow

我知道这不是一个受欢迎的问题,有些人不喜欢具有非标准外观的应用,但它对我的应用非常有用。

是否可以以“标准”非私有API方式更改NSWindow标题栏文本的颜色?

我知道我可以使用私有API(as mentioned in this answer)但我认为可以在没有私有API的情况下进行,因为Pixelmator已经完成并且没有被MAS拒绝。我知道也可以这样做通过创建一个无边框窗口并自己绘制所有内容,但我不认为Pixelmator是如何做的,因为它们仍然可以获得标准NSWindow标题栏附带的所有附加位;可拖动图标,重命名窗口,下拉菜单文档修订和全屏按钮。

基本上,我使用setBackgroundColor创建了一个黑色窗口:但是文本仍然显示为黑色,但在黑色背景上不起作用。

那么有没有人知道这样做的方法,或者Pixelmator是如何做到的?

3 个答案:

答案 0 :(得分:11)

从OS X 10.10开始,将窗口的外观更改为NSAppearanceNameVibrantDark

就足够了
  window.appearance = NSAppearance(named:NSAppearanceNameVibrantDark)

认为值得一提,因为您可以找到的大部分答案都已过时。

答案 1 :(得分:2)

这是Swift的解决方案。已经很晚了,我累了,所以这可能不是最佳的,但它确实有效。

首先,这是一个在层次结构中查找视图的功能,可以选择跳过特定视图。 (如果我们要搜索window.contentView.superview.subviews并且我们想在contentView中忽略您自己的观点

,这会非常有用
func findViewInSubview(subviews: [NSView], #ignoreView: NSView, test: (NSView) -> Bool) -> NSView? {
    for v in subviews {
        if test(v) {
            return v
        } else if v != ignoreView {
            if let found = findViewInSubview(v.subviews as [NSView], ignoreView: ignoreView, test) {
                return found
            }
        }
    }
    return nil
}

以下是您将如何使用它,例如来自NSViewController子类。请注意,您需要在窗口可见时执行此操作,因此您无法在viewDidLoad中执行此操作。

override func viewDidAppear() {
    if let windowContentView = view.window?.contentView as? NSView {
        if let windowContentSuperView = windowContentView.superview {
            let titleView = findViewInSubview(windowContentSuperView.subviews as [NSView], ignoreView: windowContentView) { (view) -> Bool in
                // We find the title by looking for an NSTextField. You may
                // want to make this test more strict and for example also
                // check for the title string value to be sure.
                return view is NSTextField
            }
            if let titleView = titleView as? NSTextField {
                titleView.attributedStringValue = NSAttributedString(string: "Hello", attributes: [NSForegroundColorAttributeName: NSColor.redColor()])
            }
        }
    }
}

请注意你正在玩火。像这样的内部结构是没有说明的原因。

答案 2 :(得分:0)

您可以使用某些私有API对问题的评论中提到的问题进行解决 - 但是,您无法将该应用提交到AppStore。

其他解决方案是获取[[myWindow contentView] superview] - 它可以获得前面提到的NSThemeView实例。您需要做的就是搜索NSTextField的任何实例的视图(实际上称为帧视图)子视图的子视图并修改它们。请注意,这些私有视图的层次结构可能随OS X的每个版本而变化,可能会破坏您的代码。

最好的解决方案是子类化(只有子类,没有其他自定义)NSWindow并实现-title-setTitle:方法 - 对于每个窗口,你要设置实际的标题到@""(通过调用[super setTitle:@""]),然后将您自己的,以编程方式创建的NSTextField实例放入框架视图(即[[[self contentView] superview] addSubview:myTextField],其中myTextField是文本字段。您需要弄清楚字段的确切位置等,但这是最简单的部分。