How do I create a Cocoa window programmatically? - objective-c

My Cocoa app needs some small dynamically generated windows. How can I programmatically create Cocoa windows at runtime?
This is my non-working attempt so far. I see no result whatsoever.
NSRect frame = NSMakeRect(0, 0, 200, 200);
NSUInteger styleMask = NSBorderlessWindowMask;
NSRect rect = [NSWindow contentRectForFrameRect:frame styleMask:styleMask];
NSWindow * window = [[NSWindow alloc] initWithContentRect:rect styleMask:styleMask backing: NSBackingStoreRetained defer:false];
[window setBackgroundColor:[NSColor blueColor]];
[window display];

The problem is that you don't want to call display, you want to call either makeKeyAndOrderFront or orderFront depending on whether or not you want the window to become the key window. You should also probably use NSBackingStoreBuffered.
This code will create your borderless, blue window at the bottom left of the screen:
NSRect frame = NSMakeRect(0, 0, 200, 200);
NSWindow* window = [[[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO] autorelease];
[window setBackgroundColor:[NSColor blueColor]];
[window makeKeyAndOrderFront:NSApp];
//Don't forget to assign window to a strong/retaining property!
//Under ARC, not doing so will cause it to disappear immediately;
// without ARC, the window will be leaked.
You can make the sender for makeKeyAndOrderFront or orderFront whatever is appropriate for your situation.

A side note, if you want to programatically instantiate the application without a main nib, in the main.m file / you can instantiate the AppDelegate as below. Then in your apps Supporting Files / YourApp.plist Main nib base file / MainWindow.xib delete this entry. Then use Jason Coco's approach to attach the window in your AppDelegates init method.
#import "AppDelegate.h":
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[NSApp setDelegate:appDelegate];
[NSApp run];
[pool release];
return 0;
}

Try
[window makeKeyAndOrderFront:self];
instead of
[window display];
Is that what you're aiming for?

Translating the top rated answer to modern swift (5) gives you something akin to this:
var mainWindow: NSWindow!
...
mainWindow = NSWindow(
contentRect: NSMakeRect(0, 0, 200, 200),
styleMask: [.titled, .resizable, .miniaturizable, .closable],
backing: .buffered,
defer: false)
mainWindow.backgroundColor = .blue
mainWindow.makeKeyAndOrderFront(mainWindow)

This is what I've come up with myself:
NSRect frame = NSMakeRect(100, 100, 200, 200);
NSUInteger styleMask = NSBorderlessWindowMask;
NSRect rect = [NSWindow contentRectForFrameRect:frame styleMask:styleMask];
NSWindow * window = [[NSWindow alloc] initWithContentRect:rect styleMask:styleMask backing: NSBackingStoreBuffered defer:false];
[window setBackgroundColor:[NSColor blueColor]];
[window makeKeyAndOrderFront: window];
This displays a blue window. I hope this is the optimal approach.

Related

NSWindow crashes after close and reopen

I have created an NSWindow
self.storeWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 800, 660) styleMask:NSWindowStyleMaskResizable|NSWindowListOrderedFrontToBack|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:false];
[self.storeWindow setDelegate:self];
Which opens fine and closes fine. However if I call if again of even check for nil it crashes with EXC_BAD_ACCESS.
I declare it as a string property in the header
#property (strong,nonatomic) NSWindow *storeWindow;
if (self.storeWindow.contentView == nil) {
self.storeWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 800, 660) styleMask:NSWindowStyleMaskResizable|NSWindowListOrderedFrontToBack|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:false];
[self.storeWindow setDelegate:self];
}
[self.storeWindow setBackgroundColor:[NSColor whiteColor]];
self.store = [[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 850, 640)];
[self.store loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:json[#"url"]]]];
[self.storeWindow.contentView addSubview:self.store];
[self.storeWindow makeKeyAndOrderFront:self.window];
Any ideas?
NSWindow’s releasedWhenClosed property can be set to change the default behavior, which is to release a window when it is closed (unless it is owned by a window controller). The property can be set in the Interface Editor’s Attributes Inspector, or programmatically, for example:
[myWindow setReleasedWhenClosed:NO];

OSX custom keyboard field

I am creating an application using Unity3d platform, and I want to show native osx textfields for my osx build.
Is there way to show native text field?
I have tried to add textField to NSWindow, but it is not visible.
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 100)];
[textField setStringValue:#"VALUE"];
NSApplication * shAp = [NSApplication sharedApplication];
NSWindow *window = [shAp windows][1];
if (window != NULL)
{
NSLog(#"window found, add subview");
[[window contentView] addSubview:textField];
}
My solution for this is using child window.
I create Child Window and then add TextField as subview.
All works fine, but I should resize child window when parent window is resizing.
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 50)];
NSApplication * shAp = [NSApplication sharedApplication];
NSWindow *window = [shAp windows][1];
NSWindow *overlayWindow = [[NSWindow alloc]initWithContentRect:newRect
styleMask:NSBorderlessWindowMask
backing:window.backingType
defer:NO];
[window addChildWindow:overlayWindow ordered:NSWindowAbove];
[[overlayWindow contentView] addSubview:textView];

Programmatically created window does not show up as correct size

This is my code in the applicationDidFinishLaunching function,
// Create window
NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 300)
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered defer:NO];
//Create gl view
NSRect frame = [window contentRectForFrameRect:[window frame]];
MyOpenGLView *glView = [[MyOpenGLView alloc] initWithFrame:frame];
[window setContentView:glView];
[window makeFirstResponder:glView];
// Show up
[window makeKeyAndOrderFront:self];
The application builds and runs. But when it runs, the window seems to be full screen. In other words, I get the name of the application on the top left and nothing else on screen changes. Its like an empty window the size of my screen. Why does this happen and how can I fix it?
Additional information: initWithFrame function in MyOpenGLView class,
self = [super initWithFrame:frameRect];
[self myInit];
return self;
I'm going to guess you're using Automatic Reference Counting (ARC) and not manual reference counting. To review, here's your code:
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
NSWindow *window = [[NSWindow alloc] initWithContentRect:
NSMakeRect(0, 0, 400, 300) styleMask:(NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered defer:NO];
//Create gl view
NSRect frame = [window contentRectForFrameRect:[window frame]];
MyOpenGLView *glView = [[MyOpenGLView alloc] initWithFrame:frame];
[window setContentView:glView];
[window makeFirstResponder:glView];
// Show up
[window makeKeyAndOrderFront:self];
}
Under ARC, the NSWindow you create here in this method only lasts as long as the method. In other words, it will be created, shown for a split second (if even at all) and then will immediately be deallocated and removed from the screen. In order to make it persist, you should define it as an instance variable. For example:
MDAppController.h:
#interface MDAppController : NSObject
#property (nonatomic, strong) NSWindow *window;
#end
MDAppController.m:
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
self.window = [[NSWindow alloc] initWithContentRect:
NSMakeRect(0, 0, 400, 300)
styleMask:(NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered defer:NO];
// or
// _window = ....
// ....
// Show up
[self.window makeKeyAndOrderFront:self];
// or
// [_window makeKeyAndOrderFront:self];
}
Here, you're setting the instance variable window to the NSWindow you create and since that ivar is defined as strong, it will persist after that method returns.

NSWindow like Quicksilver

I am creating an app, where I want to show a "pop-up" or "notification" to the user when he press a hotkey.
I want that to be displayed as a floating message, like the one that appears when you change the volume, or the brightness, or like the Quicksilver App input window.
I want it to has alpha, to fade in, to stay there for 5-8 secs, and to fade out.
And ... the problem is that I don't know how to get started on that. I've tried:
NSRect frame = NSMakeRect(0, 0, 600, 65);
_myWindow = [[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[_myWindow setBackgroundColor:[NSColor blueColor]];
[_myWindow center];
[_myWindow makeKeyAndOrderFront:NSApp];
But, of course that's not what I'm trying to do.
Any help is welcome ;-)
I believe the proper term for this is a bezel window. Quicksilver is open source (https://github.com/quicksilver/Quicksilver) so you can see how they do it, but I've accomplished something similar with a custom NSWindow subclass:
- (id) initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
if((self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag])) {
[self setOpaque:NO];
[self setIgnoresMouseEvents:YES];
[self setLevel:NSFloatingWindowLevel];
[self setBackgroundColor:[NSColor clearColor]];
}
return self;
}
and the animation controlled by the window controller:
- (void) windowDidLoad
{
CAAnimation *animation = [CABasicAnimation animation];
[animation setDelegate:self];
[[self window] setAnimations:[NSDictionary dictionaryWithObject:animation forKey:#"alphaValue"]];
}
to make the window fade in, code similar to the following should work:
[[self window] setAlphaValue:0.0];
[[[self window] animator] setAlphaValue:1.0];
[[self window] orderFront:self];
I realize this isn't a plug and play solution but it should get you started.

Cocoa App Enter Full Screen

I am developing a simple application which make use of full screen window.
Window contains view that contains button, image etc etc... , but when I enter in full screen with the follow lines:
NSWindow* tmp = [self window];
[tmp setStyleMask:NSBorderlessWindowMask];
[tmp setFrame:[tmp frameRectForContentRect:[[tmp screen] frame]]display:YES animate:NO];
[tmp setBackingType:NSBackingStoreBuffered];
screenRect = [[NSScreen mainScreen] frame];
int windowLevel = CGShieldingWindowLevel();
[self.window setLevel:windowLevel];
The view I put in the window doesn't resized automatically, I could make some operation for resize correctly that work, but there are a way to do that automatically?
I post all my AppController here:
-(id)init {
self = [super initWithWindowNibName:#"MainWindow"];
NSWindow* tmp = [self window];
[tmp setStyleMask:NSBorderlessWindowMask];
[tmp setFrame:[tmp frameRectForContentRect:[[tmp screen] frame]]display:YES animate:NO];
[tmp setBackingType:NSBackingStoreBuffered];
screenRect = [[NSScreen mainScreen] frame];
/**
// [[tmp standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
// [[tmp standardWindowButton:NSWindowZoomButton] setHidden:YES];
self.window = [[NSWindow alloc] initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO screen:[NSScreen mainScreen]];
**/
int windowLevel = CGShieldingWindowLevel();
[self.window setLevel:windowLevel];
return self;
}
// We need to be layer-backed to have subview transitions.
-(void)awakeFromNib {
[[self window] setContentSize:[topMenu frame].size];
[[[self window] contentView] addSubview:topMenu];
[topMenu enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
[[[self window] contentView] setWantsLayer:YES];
}
- (void)dealloc
{
[super dealloc];
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
[topMenu_controller performAnimation];
return;
}
You can use the springs and struts of Interface Builder to set a view's autosizing behavior:
http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/IB_UserGuide/Layout/Layout.html