I\'m trying to crate a NSWindow
without title bar (NSBorderlessWindowMask
) with round corners and a shadow, similar to the below \"Welcome
There is a sample application on the Apple Developer Site that may help you with that. This sample demonstrates how to create windows with custom shapes, no title bar, and transparent content. It also shows how to change the shape of the window and recalculate the drop shadow around the window border.
You have two options:
Code:
@interface RoundedOuterShadowView : NSView {
}
@end
@implementation RoundedOuterShadowView
- (id)initWithFrame: (NSRect)frameRect
{
self = [super initWithFrame: frameRect];
if (self != nil) {
}
return self;
}
// Shared objects.
static NSShadow *borderShadow = nil;
- (void)drawRect: (NSRect)rect
{
[NSGraphicsContext saveGraphicsState];
// Initialize shared objects.
if (borderShadow == nil) {
borderShadow = [[NSShadow alloc] initWithColor: [NSColor colorWithDeviceWhite: 0 alpha: 0.5]
offset: NSMakeSize(1, -1)
blurRadius: 5.0];
}
// Outer bounds with shadow.
NSRect bounds = [self bounds];
bounds.size.width -= 20;
bounds.size.height -= 20;
bounds.origin.x += 10;
bounds.origin.y += 10;
NSBezierPath *borderPath = [NSBezierPath bezierPathWithRoundedRect: bounds xRadius: 5 yRadius: 5];
[borderShadow set];
[[NSColor whiteColor] set];
[borderPath fill];
[NSGraphicsContext restoreGraphicsState];
}
@end
Objective C example of @Eonil's answer:
[window setBackgroundColor:[NSColor whiteColor]];
[window setOpaque:NO];
[window setStyleMask:NSResizableWindowMask | NSTitledWindowMask | NSFullSizeContentViewWindowMask];
[window setMovableByWindowBackground:YES];
[window setTitlebarAppearsTransparent:YES];
[window setTitleVisibility:NSWindowTitleHidden];
[window setShowsToolbarButton:NO];
[window standardWindowButton:NSWindowFullScreenButton].hidden = YES;
[window standardWindowButton:NSWindowMiniaturizeButton].hidden = YES;
[window standardWindowButton:NSWindowCloseButton].hidden = YES;
[window standardWindowButton:NSWindowZoomButton].hidden = YES;
[window makeKeyWindow];
I just created my own version of the Xcode splash screen for my application, including the recent files list view and all four corners are rounded:
http://www.fizzypopstudios.com/splash.png
The easiest way I found to do this was to create a window using the interface builder. I made the window 800x470 pixles, then I unchecked all the options except "Shadow" and "Restorable". This left me with a blank slate with which to create my splash screen.
In the initWithContentRect:styleMask:backing:defer:
method for the splash window I also set the following properties:
self.opaque = NO
self.backgroundColor = [NSColor clearColor]
self.movableByWindowBackground = YES
If you displayed the window at this point you would have no background, and the window shadow would automatically be set to be behind any non-transparent controls in the window.
When I draw my window background I fill the left 500 pixels with light gray and the remaining 300 pixels on the right with white. If displayed the window would have no rounded corners at this point.
I then use [NSColor clearColor]
to notch squares out all 4 corners of the window (the size of the square is the radius of the rounded corner we will draw next). Then using Bezier Paths I draw in a rounded corner into the notches I just cut out.
I tried to do this by creating a bezier path that when filled with [NSColor clearColor]
would also result in a round corner, however, for some reason the path would not fill with clear, though it would fill with other colors.
Now, if you render the window you will have rounded corners, however, if you drop a table view into the right side of the window the corners will become square again. The easy solution there is to set the NSScrollView
to not draw a background, and then to set the nested NSTableView
background to transparent.
As we are drawing the background behind the table we don't really need the table or scroll view drawing a background, and this then preserves the rounded corners.
If you have any other controls that go near the 4 corners just keep them indented enough to not be in the rounded area. An example of this is I have a button in the lower left of my window, however, since the button has transparency the rounded corner is not removed.
One other consideration is you may want to provide canBecomeKeyWindow
and canBecomeMainWindow
methods in your window subclass to return YES
as the default for these types of windows is NO
.
I hope this info helps you create your window, I saw your question a while ago and thought I would come back and let you know how I created my window in case it could help you! :)
I realised old approach was not able to create precise round corner. So I updated example to make precise round corner.
window1.backgroundColor = NSColor.whiteColor()
window1.opaque = false
window1.styleMask = NSResizableWindowMask
| NSTitledWindowMask
| NSFullSizeContentViewWindowMask
window1.movableByWindowBackground = true
window1.titlebarAppearsTransparent = true
window1.titleVisibility = .Hidden
window1.showsToolbarButton = false
window1.standardWindowButton(NSWindowButton.FullScreenButton)?.hidden = true
window1.standardWindowButton(NSWindowButton.MiniaturizeButton)?.hidden = true
window1.standardWindowButton(NSWindowButton.CloseButton)?.hidden = true
window1.standardWindowButton(NSWindowButton.ZoomButton)?.hidden = true
window1.setFrame(CGRect(x: 400, y: 0, width: 400, height: 500), display: true)
window1.makeKeyAndOrderFront(self)
Here's full working example.
Special treatment is not required at least in OS X 10.10.
import Cocoa
class ExampleApplicationController: NSObject, NSApplicationDelegate {
class ExampleController {
let window1 = NSWindow()
let view1 = NSView()
init(){
window1.setFrame(CGRect(x: 400, y: 0, width: 400, height: 500), display: true)
window1.contentView = view1
window1.backgroundColor = NSColor.clearColor()
window1.opaque = false
window1.styleMask = NSBorderlessWindowMask | NSResizableWindowMask
window1.movableByWindowBackground = true
window1.makeKeyAndOrderFront(self)
view1.wantsLayer = true
view1.layer!.cornerRadius = 10
view1.layer!.backgroundColor = NSColor.whiteColor().CGColor
/// :ref: http://stackoverflow.com/questions/19940019/nswindow-with-round-corners-and-shadow/27613308#21247949
window1.invalidateShadow() // This manual invalidation is REQUIRED because shadow generation is an expensive operation.
}
}
let example1 = ExampleController()
}
You can download a working example from here.