Cocoa get main window - cocoa

I want to create 3 windows like this:
NSWindow *win1 = [[NSWindow alloc] initWithContentRect:rect1
styleMask:uiStyle
backing:backingStoreStyle
defer:NO];
and make one of them the main window, then get the main window, but I always get nil.
[win1 makeKeyAndOrderFront:win1];
[win2 makeKeyAndOrderFront:win2];
[win3 makeKeyAndOrderFront:win3];
[win2 makeMainWindow];
And all of these are nil:
NSLog(#"%#", [app mainWindow]);
NSLog(#"%#", [win1 isMainWindow]);
NSLog(#"%#", [win2 isMainWindow]);
NSLog(#"%#", [win3 isMainWindow]);

I tried your code. It does return an instantiated NSWindow object. I didn't get nil at all. Can you please post more context to code snippet?
Secondly, it is far easier and manageable to create window in IB. Thirdly, check - (BOOL)canBecomeMainWindow before passing it the message makeMainWindow.
If you want to create custom windows programaticaly, I would suggest create a Window in MainMenu.xib. Get it's IBOutlet, for example window. Then create your windows win1, win2 etc and add then as child windows to your window using addChildWindow.

Related

Print is printing entire window, not the View

I have a simple program, for making sure the print works.
-Subclassed NSObject for a Controller, "ViewController.
-Subclassed NSView, View
Added a custom view to the window, set class to View.
Made ViewController delegate for View.
Added Object in IB, set class to ViewController.
Added IBOutlet to Delegate section of ViewController, connected it to the the custom view on the window.
In View, have a simple [myString drawInRect: rect], where myString is defined in the init as #"Hi".
When I run, the program prints "Hi" in the view. When I click the "Print" menu item, the print preview shows the entire window.
More: I hade an earlier test program which had no print code, I ran it and the print preview showed only the view. I've got through both codes and cannot find a difference, so I am lost at why one is working and the other is not.
Do any of you know why the print preview would show the entire window instead of the view?
[EDIT]-----
I also created an extremely simple program to check and have the same issue.
Subclassed NSView, MainView
Added Custom View to Window, set class to MainView
Added [str drawInRect: dirtyRect withAttributes:nil];
(note; NSString *str = #"Hello";).
[More Information]-------
I added a print method as follows to the NSView object:
-(void)printPDF{
NSRect r = [self bounds];
[[NSPrintOperation printOperationWithView:self] runOperation];
[self dataWithPDFInsideRect:r];
}
Added a button to the window, linked it to an IBAction method in the ViewController:
-(IBAction)printToPDF:(id)sender{
[view printPDF];
}
In the ViewController I have:
IBOutlet View *view;
This works! So, why does the default "print" menu item print the entire Window?
By default, you don't have to write any printing code and the printing just works. But, it provides default behavior (aka, print the entire window).
If you want custom printing behavior, you'd have to write your own printing method.(like you did in your extremely simple program). And you can link the default print menu item to your own printing method.

Sheets are not displaying properly on OSX

I am very much new to OSX development. Consider this as my first app. I want to display a sheet when a button is clicked on the main window. I am using Nib
Following is my code for .h file
#import <Foundation/Foundation.h>
#import "WebKit/Webkit.h"
#interface MainViewObject : NSObject
- (IBAction)accountButtonPressed:(id)sender;
- (IBAction)cancelSheetButtonPressed:(id)sender;
.m file as follows
#import "MainViewObject.h"
#implementation MainViewObject
- (IBAction)accountButtonPressed:(id)sender {
[NSApp beginSheet:self.accountSheet
modalForWindow:[mainWindowView window]
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
[NSApp runModalForWindow:self.accountSheet];
[NSApp endSheet:self.accountSheet];
[self.accountSheet orderOut:self];
}
- (IBAction)cancelSheetButtonPressed:(id)sender {
// Return to normal event handling
[NSApp endSheet:self.accountSheet];
// Hide the sheet
[self.accountSheet orderOut:sender];
}
When I run the app I get something like this:
http://i.imgur.com/DzJJ6.png
I am stuck and I have no idea what wrong in this. I am not able to get the sheet and the not able to even close the app. I have referred to some examples on internet.
- (IBAction)accountButtonPressed:(id)sender {
[NSApp beginSheet:self.accountSheet
modalForWindow:[mainWindowView window]
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
[NSApp runModalForWindow:self.accountSheet];
[NSApp endSheet:self.accountSheet];
[self.accountSheet orderOut:self];
}
Wow, looking at that, it's no surprise the screenshot looks as it is.
Let's walk through that one line at a time. When you click the Accounts button, you're doing 4 things immediately in succession:
You're telling the application to begin showing the sheet attached to your main window. This is OK, and is actually the only code you want in that accountButtonPressed: method.
Right after beginning that sheet, you tell the application you want to also show that sheet all by itself (not attached to any windows but right in the middle of the screen), in an application-modal fashion, which blocks all other events from being processed in the application. In other words, this line doesn't really make sense. You either show a window as a sheet in a "document-modal" fashion (which only ties up the window that the sheet is attached to) or in an "application-modal" fashion, but not both at the same time. ;-)
Immediately after having just shown the sheet, you tell NSApp to stop showing the sheet. Now, you do want to do this eventually, but dismissing the sheet 0.0005 seconds after having just shown it will likely leave your users a little frustrated.
You now tell the sheet to hide itself. This needs to be done from your didEndSelector: method, which brings us to the problems in your first method.
-
[NSApp beginSheet:self.accountSheet
modalForWindow:[mainWindowView window]
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
This is good but read the documentation for beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo: and also the Sheet Programming Topics: Using Custom Sheets. (The Companion guides links at the top of Class Reference pages are especially helpful for learning how to use the APIs in the real world. They were extremely helpful when I was learning).
Specifying nil for the modalDelegate: means you don't have anything that's waiting to be notified about when the sheet has stopped being shown (this happens when you call [NSApp endSheet:sheet]). You also haven't specified the #selector you want called when the sheet is ended. A selector is kind of like a function, aka a "method".
Your code should look something like this:
#implementation MDAppDelegate
- (IBAction)showSheet:(id)sender {
[NSApp beginSheet:self.sheet
modalForWindow:self.window
modalDelegate:self
didEndSelector:#selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:NULL];
}
- (IBAction)cancel:(id)sender {
[NSApp endSheet:self.sheet];
}
- (IBAction)ok:(id)sender {
[NSApp endSheet:self.sheet];
}
- (void)sheetDidEnd:(NSWindow *)sheet
returnCode:(NSInteger)returnCode
contextInfo:(void *)contextInfo {
[sheet orderOut:nil];
}
#end
In this example, you click the Show Sheet button, and the sheet starts being shown attached to the main window. In the sheet, there is a Cancel and an OK button, which both call their respective methods. In each of these methods, you call [NSApp endSheet:self.sheet]. This tells NSApp that it should then call the sheetDidEnd:returnCode:contextInfo: method on the object specified to be the modal delegate. In sheetDidEnd:returnCode:contextInfo: you then tell the sheet to hide itself.
EDIT:
Every NSWindow has a "Visible at launch" flag that can be set in Interface Builder. If this flag is set, the window will be visible at the time the nib file is loaded. If it isn't set, the window is hidden until you programmatically show it. Just edit the flag in the nib file like shown:

Prevent save prompt when closing NSWindow

I have a document-based Cocoa app that uses a secondary NSWindow for a preview mode (with shouldCloseDocument set to NO).
If the document is dirty (edited without saving) and I close the secondary NSWindow, a "Do you want to save the changes made to the document" prompt appears.
How can I avoid this prompt on the secondary NSWindow?
I couldn't find a way to do this. I expected to find a NSWindowDelegate or NSWindow method called before the save prompt but none of the obvious candidates (windowWillClose, close, performClose, windowShouldClose) are.
As a workaround, instead of setting NSWindowController.document I'm using a custom property to pass the document. With document set to NIL, the save prompt is not shown anymore.
specifically you can do this inside your viewController subclass:
make sure delegate is set from the window to the owner class:
//-------------------------------------------------------
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
NSLog (#"windowControllerDidLoadNib");
aController.document = nil;
[super windowControllerDidLoadNib:aController];
............. etc.......

How to give focus to NSWindow loaded from NIB?

I'm using NSWindowController to load a window from a NIB. However, when I call showWindow:, the window is visually topmost, but the focus remains where it was (instead of moving it to the new window).
It's easy to see this happening when the first window (with keyboard focus) is moved slightly, before creating the new window (via cmd+n). This is the result:
The bottom, focused window is the original window. The unfocused window on top is the newly created window.
This is the relevant code:
AppDelegate.h:
- (IBAction)newDocument:(id) sender;
AppDelegate.m:
- (IBAction)newDocument:(id) sender {
[[[FooController alloc] init] showWindow:self];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[self newDocument:self];
}
FooController.h:
#interface FooController : NSWindowController { }
#end
FooController.m:
- (id)init {
self = [super initWithWindowNibName:#"FooWindow"];
return self;
}
FooWindow.xib:
A freshly created Window xib, without modifications.
MainMenu.xib:
The default MainMenu.xib, with its window deleted.
Calling makeKeyAndOrderFront: on the window in the controller's windowDidLoad method does not appear to focus the new window. Setting the File's owner of FooWindow.xib to FooController also did not appear to help.
What is the correct way to load and show a window from a NIB so that it does receive keyboard focus?
Edit: It looks like NSWindowController's window method returns nil, which explains why calling methods on window doesn't do anything. But why is it nil?
Okay, I found the cause of this problem.
The xib's File's owner must be set to the controller, and (this is the part I didn't know about) you have to connect the controller's window outlet to the window itself.
Having done that, it just works. No makeKeyWindow, makeMainWindow or makeKeyAndOrderFront: needed.
Perhaps makeMainWindow: or makeKeyWindow: helps

Why the splash window can’t show before the App launch?

I want to show a splash Screen before the App lunch. First I make the SplashWindow subclassing the NSWindow, the code is :
- (id)initWithContentRect(NSRect)contentRect
styleMask(unsigned int)aStyle
backing(NSBackingStoreType)bufferingType
defer(BOOL)flag {
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[self setBackgroundColor:
[NSColor clearColor]];
[self setLevel: NSStatusWindowLevel];
[self setAlphaValue:1.0];
[self setOpaque:NO];
[self setHasShadow: YES];
return self;
}
and then in the awake from nib in the main app controller:
loadWindow = [[NSWindow alloc] initWithContentRect:[loadWindow frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
[loadWindow setContentView:theView];
[loadWindow setHasShadow:YES]; [
loadWindow setLevel:NSStatusWindowLevel];
[loadWindow makeKeyAndOrderFront:self];
and then I let the loadWindow closed after 3 secondes, I used the method [loadWindow orderOut:self], but when the splash window closed , the mainwinow didn't show . what am I missing? My App is a multi_Documents . and in the mainMenu.nib there was one window(loadwindow),in IB I have connected up the loadWindow outlet in the main controller. I have also connected the view and image. and I changed another way : in the delegate method:applicationWillFinishLaunching: I orderFront the loadWindow , in the method:applicationDidFinishLaunching: I orderOut the loadWindow after 3 seconds, but the mainWindow didn't show too.Somebody can give some advice or codes the result the problem? Thank you very much!
Answer to title: Because your app isn't running yet. An application that isn't running can't do anything.
Serious answer to question:
First, you don't need to subclass NSWindow.
Second, you aren't instantiating your subclass, you're instantiating NSWindow. That's why you're not getting your subclass's behavior. (And this is what you should be doing, since you don't need the subclass.)
Third, you're trying to ask a window that doesn't exist yet for the frame you'll use to create it. loadWindow is nil until after you create something and store it there.
Fourth, because you are asking nil for its frame, you are getting a garbage rectangle back. Then you create a window with this garbage rectangle. Unsurprisingly, when you put this window on the screen, it appears in a random position (probably off-screen) with a random size (probably either too large to create or negative).
Fifth, what makes you think that telling a window to order out would cause some other window to order in? How is it supposed to know what window to order in?
Leaving aside the undeniable reality that the very existence of a splash screen punishes the user for using your application, you should be using NSWindowController to load the window and to do your set-up such as setBackgroundColor: and setLevel:. And in your timer method, where you order out the splash window, you must also explicitly order in the main window.
I don't see anything that would make another window show in the code you posted. Why don't you try sending your main window makeKeyAndOrderFront:?

Resources