Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to custom draw window title bar in Objective-C?

I'd like to customize the way I draw the window title bar on OS X. Specifically, I'd like to do something like the Twitterrific app where there is a custom close button, no min/max buttons, and the window title text is right-justified. Unlike Twitterrific, I'm not looking to custom draw the entire window (though I'm not completely opposed to that either).

I've already seen the RoundWindow sample on Cocoa With Love as well as the RoundTransparentWindow example Apple provides, but neither seems appropriate.

like image 739
sam Avatar asked Nov 03 '09 03:11

sam


3 Answers

If you don't want to use a borderless window class then you can do a couple of things.

First, you can customize the close/min/max buttons buy using -[NSWindow standardWindowButton:]. Once you get the button you can position it/remove it/etc...

You can customize the title by setting the title to @"". Then you can add a NSTextField to draw your own title by doing the following [[[NSWindow contentView] superview] addSubview:textField].

This is probably the easiest way to do things.

Another way to do this is to customize the view that draws all the window title bar, etc...

NSWindow's content view's is inside a "theme view". You can subclass the theme view and do your own drawing. The only problem is that the theme view is a private class so you'll have to be careful.

like image 173
Leibowitzn Avatar answered Nov 10 '22 03:11

Leibowitzn


cocoadev provides some more detail on how best to implement your own NSWindow subclass, complete with a description of most of the common pitfalls.

The gist of it is to create a subclass of NSWindow, and set its styleMask to NSBorderlessWindowMask in the init method:

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

Note that you should probably return YES for canbecomeKeyWindow in order to make your window behave like a normal window.

- (BOOL) canBecomeKeyWindow
{
    return YES;
}

You can then create a custom NSView subclass, fill the entire window with an instance of said class, and then perform all of the appropriate window drawing from within that custom view.

The whole thing can get a bit painful. You will have to re-implement most of the normal window behaviours such as resizing by dragging the bottom right corner.

like image 26
e.James Avatar answered Nov 10 '22 04:11

e.James


There's an example of a custom window implementation in the CoreData Stickies sample project.

like image 2
NSResponder Avatar answered Nov 10 '22 03:11

NSResponder