Sizing and Placing Windows
This article describes how to control a window’s size and position, including how to set a window’s minimum and maximum size, how to constrain a window to the screen, how to cascade windows so their title bars remain visible, how to zoom a window as though the user pressed the zoom button, and how to center a window on the screen.
Setting a Window’s Size and Location
center method places a window in the most prominent location on the screen, one suitable for important messages and alert dialogs.
You can resize or reposition a window using
setFrame:display:animate:—the former is equivalent to the latter with the animate flag
NO. You might use these methods in particular to expand or contract a window to show or hide a subview (such as a control that may be exposed by clicking a disclosure triangle). If the animate argument in
YES, the method performs a smooth resize of the window, where the total time for the resize can be obtained by calling
The user can resize windows by clicking and dragging on the bottom right corner of the window. While the user is resizing the window,
inLiveResize will return
YES. Otherwise, it returns
NO. The user can generally reposition windows by dragging only the title bar. If you want users to be able to drag your window by clicking elsewhere, you should override
mouseDownCanMoveWindow so that it returns
YES in any views that you want to be draggable window regions. The methods
setMovable: determine whether the user can move the window by clicking in its title bar or background.
To keep the window’s top-left hand corner fixed when resizing, you must typically also reposition the origin, as illustrated in the following example.
NSRect frame = [myWindow frame];
if (frame.size.width <= MIN_WIDTH_WITH_ADDITIONS)
frame.size.width = MIN_WIDTH_WITH_ADDITIONS;
frame.size.height += ADDITIONS_HEIGHT;
frame.origin.y -= ADDITIONS_HEIGHT;
[myWindow setFrame:frame display:YES animate:YES];
// implementation continues...
Note that the window’s delegate does not receive
windowWillResize:toSize: messages when the window is resized in this way. It is your responsibility to ensure that the window’s new size is acceptable.
The window’s delegate does receive
windowDidResize: messages. You can implement
windowDidResize: to add or remove subviews at suitable junctures. There are no additional flags to denote that the window is performing an animated resize operation (as distinct from a user-initiated resize). It is therefore up to you to capture relevant state information so that you can update the window contents appropriately in
If you use the Cocoa document architecture, you can use the
setShouldCascadeWindows: method of
NSWindowController to set whether the window, when it is displayed, should cascade in relation to other document windows (that is, have a slightly offset location so that the title bars of previously displayed windows are still visible). The default is true, so typically you have no additional work to perform.
If you are not using the document architecture, you can use the
cascadeTopLeftFromPoint: method of
NSWindow to cascade windows yourself. The method returns a point shifted from the top-left corner of the window that can be passed to a subsequent invocation of
cascadeTopLeftFromPoint: to position the next window so the title bars of both windows are fully visible.
You use the
zoom: method to toggle the size and location of a window between its standard state, as determined by the application, and its user state: a new size and location the user may have set by moving or resizing the window.
Constraining a Window’s Size and Location
You can use
setContentMaxSize: to limit the user’s ability to resize the window—note that you can still set it to any size programmatically. Similarly, you can use
setContentAspectRatio: to keep a window’s width and height at the same proportions as the user resizes it, and
setContentResizeIncrements: to make the window resize in discrete amounts larger than a single pixel. (Aspect ratio and resize increments are mutually exclusive attributes.) In general, you should use the
setContent... methods instead of those that affect the window’s frame (
setMaxSize:, and so on). These are preferred because they avoid confusion for windows with toolbars, and also are typically a better model since you control the content of the window but not the frame.
You can use the
constrainFrameRect:toScreen: method to adjust a proposed frame rectangle so that it lies on the screen in such a way that the user can move and resize a window. However, you should make sure your window fits onscreen before display. Note that any NSWindow with a title bar automatically constrains itself to the screen. The
cascadeTopLeftFromPoint: method shifts the top left point by an amount that allows one window to be placed relative to another so that both their title bars are visible.
Additionally, when a window is about to be resized, the window’s delegate will be sent a
windowWillResize:toSize: message. You can implement that method in your delegate to easily control your window’s size.