【问题标题】:How to custom draw window title bar in Objective-C?如何在 Objective-C 中自定义绘制窗口标题栏?
【发布时间】:2010-12-12 12:24:18
【问题描述】:

我想自定义在 OS X 上绘制窗口标题栏的方式。具体来说,我想做一些类似 Twitterrific 应用程序的事情,其中​​有一个自定义关闭按钮,没有最小/最大按钮,以及窗口标题文本是右对齐的。与 Twitterrific 不同,我不希望自定义绘制整个窗口(尽管我也不完全反对)。

我已经看过 Cocoa With Love 上的 RoundWindow 示例以及 Apple 提供的 RoundTransparentWindow 示例,但似乎都不合适。

【问题讨论】:

    标签: objective-c cocoa macos


    【解决方案1】:

    如果您不想使用无边框窗口类,那么您可以做几件事。

    首先,您可以使用-[NSWindow standardWindowButton:] 自定义购买的关闭/最小/最大按钮。一旦你得到按钮,你就可以定位它/删除它/等等......

    您可以通过将标题设置为@"" 来自定义标题。然后你可以添加一个NSTextField来绘制你自己的标题,方法是执行以下[[[NSWindow contentView] superview] addSubview:textField]

    这可能是最简单的方法。

    另一种方法是自定义绘制所有窗口标题栏等的视图...

    NSWindow 的内容视图位于“主题视图”中。您可以子类化主题视图并进行自己的绘图。唯一的问题是主题视图是一个私有类,所以你必须小心。

    【讨论】:

    • 谢谢你,莱博维茨。您能否提供有关如何设置 NSTextField 的更多详细信息?如何设置它的框架,以便它在窗口中正确定位,并且在我的代码中的哪个位置是执行此操作的最佳位置?
    • FWIW,我是在应用程序控制器的 awakeFromNib 方法中完成的。我将文本字段的框架相对于窗口的框架定位。这可能不是最好的方法,但我使用通知来了解窗口何时变为/退出主窗口并使用它来更改文本的颜色。再次感谢您的想法。
    【解决方案2】:

    cocoadev 提供了有关如何最好地实现您自己的 NSWindow 子类的更多详细信息,并描述了大多数常见缺陷。

    其要点是创建NSWindow的子类,并在init方法中将其styleMask设置为NSBorderlessWindowMask

    - (id) initWithContentRect: (NSRect) contentRect
                     styleMask: (unsigned int) aStyle
                       backing: (NSBackingStoreType) bufferingType
                         defer: (BOOL) flag
    {
        if ((self = [super initWithContentRect: contentRect
                                     styleMask: NSBorderlessWindowMask
                                       backing: bufferingType
                                         defer: flag]) == nil) { return nil; }
    
        [super setMovableByWindowBackground:YES];
        [super setLevel:NSNormalWindowLevel];
        [super setHasShadow:YES];
        // etc.
    
        return self;
    }
    

    请注意,您可能应该为 canbecomeKeyWindow 返回 YES,以使您的窗口表现得像一个普通窗口。

    - (BOOL) canBecomeKeyWindow
    {
        return YES;
    }
    

    然后您可以创建一个自定义 NSView 子类,用该类的一个实例填充整个窗口,然后在该自定义视图中执行所有适当的窗口绘制。

    整个过程可能会有些痛苦。您将不得不重新实现大多数正常的窗口行为,例如通过拖动右下角来调整大小。

    【讨论】:

    • 谢谢,eJames。你是对的,这种方法(我之前已经开始使用)可能会很痛苦。我希望避免它,因为我不是在寻找完整的自定义,我不想实现所有窗口的标准功能。这种方法基本上是我在问题中引用的示例中使用的方法。这种方法的一个奇怪方面是窗口的阴影似乎无法正常工作。它不像标准窗口上的阴影那么暗,并且焦点改变时也不会改变。我认为这可能是无边框窗口样式的错误。
    • 阴影问题很奇怪。听起来 Leibowitzn 的回答可能是适合您的方法。祝你好运!
    • 影子问题是一个长期存在的问题。 Apple 不会为具有键盘焦点的无边框窗口绘制较暗的阴影。以 Stickies 为例。根据 Apple 的建议,解决此问题的方法是使用普通的窗口类型,然后自己绘制。
    【解决方案3】:

    CoreData Stickies 示例项目中有一个自定义窗口实现示例。

    【讨论】:

      猜你喜欢
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 2012-02-19
      • 2014-07-05
      • 1970-01-01
      相关资源
      最近更新 更多