如何在Objective-C中自定义绘制窗口标题栏?
我想自定义在OS X上绘制窗口标题栏的方式。具体来说,我想做一些类似Twitterrific应用程序的事情,其中有一个自定义关闭按钮,没有最小/最大按钮,窗口标题文本是右对齐的。与Twitterrific不同,我不希望自定义绘制整个窗口(尽管我也不完全反对) 我已经在Cocoa With Love上看到了RoundWindow示例以及苹果提供的RoundTransparentTwindow示例,但这两个示例似乎都不合适。提供了关于如何最好地实现自己的如何在Objective-C中自定义绘制窗口标题栏?,objective-c,cocoa,macos,Objective C,Cocoa,Macos,我想自定义在OS X上绘制窗口标题栏的方式。具体来说,我想做一些类似Twitterrific应用程序的事情,其中有一个自定义关闭按钮,没有最小/最大按钮,窗口标题文本是右对齐的。与Twitterrific不同,我不希望自定义绘制整个窗口(尽管我也不完全反对) 我已经在Cocoa With Love上看到了RoundWindow示例以及苹果提供的RoundTransparentTwindow示例,但这两个示例似乎都不合适。提供了关于如何最好地实现自己的NSWindow子类的更多细节,并对大多数常见
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子类,用所述类的实例填充整个窗口,然后从该自定义视图中执行所有适当的窗口绘制
整个事情可能会有点痛苦。您必须重新实现大多数正常的窗口行为,例如通过拖动右下角来调整大小。如果您不想使用无边界窗口类,那么您可以做一些事情 首先,您可以使用
-[NSWindow standardWindowButton::
自定义close/min/max按钮。一旦你得到按钮,你就可以定位/移除它/等等
您可以通过将标题设置为@“
来自定义标题。然后,您可以添加一个NSTextField
来绘制自己的标题,方法是执行以下[[NSWindow contentView]superview]addSubview:textField]
这可能是最简单的方法
另一种方法是自定义绘制所有窗口标题栏的视图,等等
NSWindow的内容视图位于“主题视图”内。您可以对主题视图进行子类化并绘制自己的图形。唯一的问题是主题视图是一个私有类,因此您必须小心。在CoreData Stickies示例项目中有一个自定义窗口实现的示例。谢谢,eJames。你是对的,这种方法(我之前已经开始了)会变得很痛苦。我希望避免它,因为我不寻求完全的定制,也不想实现窗口的所有标准功能。这种方法基本上就是我在问题中引用的示例中使用的方法。这种方法的一个奇怪方面是窗口的阴影似乎无法正常工作。它不像标准窗口上的阴影那样暗,而且焦点改变时也不会改变。我认为这可能是一个无边界窗口样式的错误。阴影问题很奇怪。听起来莱博维森的答案可能是你的出路。祝你好运!影子问题是一个长期存在的问题。苹果没有为有键盘焦点的无边框窗口画出更暗的阴影。以胶粘物为例。据一家苹果公司介绍,解决这个问题的推荐方法是使用普通的窗口类型,然后自己绘制。谢谢你,莱博维森。能否提供有关如何设置NSTextField的更多详细信息?我如何设置它的框架,使其正确地定位在窗口中,并在我的代码中的哪个位置是执行此操作的最佳位置?FWIW,我是在应用程序控制器的awakeFromNib方法中完成的。我相对于窗口的框架定位了textfield的框架。这可能不是最好的方法,但我使用通知来了解窗口何时变为/退出主窗口,并使用它来更改文本的颜色。再次感谢你的建议。