views:

4259

answers:

4

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];
A: 

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.

Steve McLeod
+1  A: 

Try

[window makeKeyAndOrderFront:self];

instead of

[window display];

Is that what you're aiming for?

Rich Catalano
+18  A: 

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:winRect
     styleMask:NSBorderlessWindowMask
     backing:NSBackingStoreBuffered
     defer:NO];
[window setBackgroundColor:[NSColor blueColor]];
[window makeKeyAndOrderFront:NSApp];

You can make the sender for makeKeyAndOrderFront or orderFront whatever is appropriate for your situation.

Jason Coco
Just curious to the person who found my answer /so/ unhelpful as to vote it down... why was it unhelpful?
Jason Coco
Don't worry about the down-voter Jason. I found your answer helpful.
Steve McLeod
+5  A: 

I think the simplest way is to create a new NIB for your window and load that whenever you need to display a window:

if (![NSBundle loadNibNamed:@"NibName" owner:self])

You can enjoy the benefits of Interface Builder when editing your window's attributes.

diciu
Amen to that! Why is it that new immigrants to Cocoaland are always so fearful of doing things the right way? The old adage applies, people - when in Rome, do as the Romans do.
Sherm Pendley
@Sherm, The person didn't ask about "the right way", he asked how to do something a specific way. I've had a need to create windows programatically in Cocoa before and it had nothing to do with not wanting to use NIBs or doing it "right". It had to do with the nature of the problem I was solving.
Jason Coco
@diciu, The OP clearly needs a borderless window for some reason, so in his case he's going to have to create the window programatically anyway. I don't think this is a helpful answer to this actual question. The question is not "How do I create a Window?" to which this /would/ be helpful.
Jason Coco
@Jason Coco what I've done in the past is to subclass NSWindow's initializer method to create a borderless window, so I can still use use IB. Using IB may or may not be suitable for this specific problem, but it still deserves to be mentioned here as one possible solution.
Marc Charbonneau
In some cases I've done that too, but 1) it still doesn't sound like a solution to the problem; and 2) the information on subclassing and all the caveats that go with it were not even mentioned in the answer.
Jason Coco
@Jason - When someone asks how to shoot themselves in the foot, the right answer is to tell them not to. Explaining how to load the gun and aim it is not helpful.
Sherm Pendley
@Jason - Also, in my experience here and elsewhere, those asking how to avoid IB are usually doing so because they are accustomed to GUI builders that generate brittle, hard-to-maintain code. IB may not always be the right answer, but it should always be the first thing to consider.
Sherm Pendley
@Sherm, granted that, but I didn't see this question that way. He clearly stated that he needed a number of dynamically generated windows. Based on his example code, he needed windows that had no border. Both of these requirements make IB iffy at best, but the dynamically generated requirement...
Jason Coco
@Sherm, Like I've said, I've had the same issues. I know how to use IB very well but I was designing an app that required full-screen and needed small windows to be built up and torn down dynamically (borderless ones as well). IB would have been worse than useless for my requirements.
Jason Coco
Wow I've created a debate :-)@Jason: this is the solution I use in my projects. Since making 1000 windows _is_ possible by loading a NIB 1000 times, I find it fits the requirement of code level creation. YMMV
diciu