2009-11-03 62 views
11

我想定制我在OS X上绘制窗口标题栏的方式。具体来说,我想要做一些类似于Twitterrific的应用程序,其中有一个自定义关闭按钮,没有最小/最大按钮,窗口标题文本是正确的。与Twitterrific不同,我不想自定义绘制整个窗口(尽管我并不完全反对)。如何在Objective-C中自定义绘制窗口标题栏?

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

回答

6

如果你不想使用无边框窗口类,那么你可以做一些事情。

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

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

这可能是最简单的方法。

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

NSWindow的内容视图的是一个“主题图”里。您可以继承主题视图并进行自己的绘制。唯一的问题是主题视图是私人类,所以你必须小心。

+0

谢谢你,莱博维茨。你能否提供一些关于如何设置NSTextField的更多细节?我如何设置它的框架,使其正确定位在窗口中,以及我的代码中哪里是最好的地方? – sam 2009-11-03 18:05:35

+0

FWIW,我是在应用控制器的awakeFromNib方法中完成的。我将文本框的框架相对于窗口的框架进行了定位。这可能不是最好的办法,但我使用通知来了解窗口何时变为/退出主窗口并用它来更改文本的颜色。再次感谢这个想法。 – sam 2009-11-04 23:00:02

5

cocoadev提供了一些关于如何最好地实现自己的NSWindow子类的更多细节,并完成了对大多数常见陷阱的描述。

它的要点是建立NSWindow一个子类,并设置其styleMaskNSBorderlessWindowMask在init方法:

- (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; 
} 

请注意,你应该为了返回YES为canbecomeKeyWindow,使你的窗口的行为像一个正常的窗口。

- (BOOL) canBecomeKeyWindow 
{ 
    return YES; 
} 

然后,您可以创建自定义的NSView子类,与所述类的一个实例填满整个窗口,然后执行所有相应的窗口从该自定义视图中绘制的。

整件事情可能会有点痛苦。您将不得不重新实现大部分常规窗口行为,例如通过拖动右下角来调整大小。

+0

谢谢,eJames。你说得对,这种方法(之前我已经开始)可能会很痛苦。我希望避免它,因为我不想完全定制,我不想实现所有窗口的标准功能。这个方法基本上是我在问题中引用的示例中使用的。这种方法的一个奇怪的方面是窗口的阴影似乎不能正常工作。它不像标准窗口上的阴影那样黑暗,并且焦点改变时它不会改变。我认为这可能是一个无边界窗口风格的错误。 – sam 2009-11-03 17:21:41

+0

阴影问题是奇怪的。听起来Leibowitzn的答案可能是适合你的方式。祝你好运! – 2009-11-03 18:48:29

+0

阴影问题是一个长期存在的问题。苹果公司并没有为有键盘焦点的无边界窗口绘制较暗的阴影。例如,看一下Stickies。根据Apple的建议,解决这个问题的方法是使用普通窗口类型,然后执行所有自己的绘图。 – Leibowitzn 2009-11-05 00:14:13

2

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

相关问题