窗口NSWindow
一.keyWindow和mainWindow
可以接收输入事件(键盘,鼠标,触控板等外设)的窗口对象称为keyWindow;当前的活动窗口也称为mainWindow。一个时刻只能有一个keyWindow和一个mainWindow。keyWindow和mainWindow可以是同一个窗口,也可以是不同的窗口。当mainWindow可以接收输入事件时,它同时也是keyWindow。
NSPanel类型的window不能做为mainWindow,只能做为keyWindow。一些常用的子类有NSColorPanel(颜色选择),NSFontPanel(字体选择),NSSavePanel(保存打开文件)
二.模态窗口
当有多个window在屏幕上时,用户可以点击切换到任何一个窗口上。有些特殊场景需要限制用户只能处理完当前的窗口的任务,只有关闭或处理完这个窗口才能继续操作其它的window。因此引入了模态窗口的概念。
有2种创建模态窗口的方法:
1.Modal windows
这种window比较霸道,当它启动后,此时只有这个window可以接收响应用户操作,无法切换到其他窗口操作,其他窗口也不能接收处理系统内部的各种事件。
使用NSApplication的runModalForWindow方法来创建Modal window
- (IBAction)showModelWindowAction:(id)sender {
[[NSApplication sharedApplication]runModalForWindow:self.myWindow];
}
使用stopModal方法来结束模态。
[NSApplication sharedApplication]stopModal];
2.Modal sessions
比起Modal windows,Modal sessions方式创建的window稍微温和一些,允许响应快捷键和系统菜单,比如字体颜色选择这些panel面板.
启动Modal sessions 窗口
NSModalSession sessionCode = [[NSApplication sharedApplication]beginModalSessionForWindow:window];
结束Modal sessions 窗口
使用sessionCode做为参数来关闭Modal sessions 窗口
[[NSApplication sharedApplication]endModalSession:sessionCode];
注意任何一种模态窗口,都必须调用结束模态的方法去结束模态。如果点击了window左上角的关闭按钮,而没有执行结束模态的方法。整个系统仍然处于模态,其他窗口无法正常工作。
三.创建窗口对象
使用NSWindow类创建窗口对象,除了frame参数,还需要制定styleMask来确定窗口样式风格。
NSRect frame = CGRectMake(0, 0, 200, 200);
NSUInteger style = NSTitledWindowMask | NSClosableWindowMask |NSMiniaturizableWindowMask | NSResizableWindowMask;
NSWindow *window = [NSWindow alloc]initWithContentRect:frame styleMask:style backing:NSBackingStoreBuffered defer:YES];
window.title = @"New Create Window";
[window makeKeyAndOrderFront:self];
1.styleMask: 按位表示的窗口风格参数
enum {
NSBorderlessWindowMask = 0, //没有顶部titilebar边框
NSTitledWindowMask = 1 << 0, //有顶部titilebar边框
NSClosableWindowMask = 1 << 1,//带有关闭按钮
NSMiniaturizableWindowMask = 1 << 2,//带有最小化按钮
NSResizableWindowMask = 1 << 3,//恢复按钮
NSTexturedBackgroundWindowMask = 1 << 8 //带纹理背景的window
};
2.backing:窗口绘制的缓存模式
enum {
NSBackingStoreRetained = 0,// 兼容老系统参数,基本很少用到
NSBackingStoreNonretained = 1,//不缓存直接绘制
NSBackingStoreBuffered = 2//缓存绘制
};
3.defer:表示延迟创建还是立即创建
四.窗口显示控制
1.窗口居屏幕中心显示
-(void)center;
2.前置显示窗口并且是其成为keyWindow
-(void)makeKeyAndOrderFront:(id)sender;
3.前置显示窗口
-(void)orderFront:(id)sender;
4.后置窗口,改变其在屏幕上的顺序
-(void)orderBack:(id)sender;
5.从屏幕上移除,隐藏窗口
-(void)orderOut:(id)sender;
五.窗口通知
当窗口状态变化时候,系统会发出相关通知消息。
NSWindowDidBecomeKeyNotification:窗口成为keyWindow
NSWindowDidBecomeMainNotification:窗口成为mainWindow
NSWindowDidMoveNotification:窗口移动
NSWindowDidResignKeyNotification:窗口不再是keyWindow
NSWindowDidResignMainNotification:窗口不再是mainWindow
NSWindowDidResizeNotification:窗口大小改变
NSWindowWillCloseNotification:关闭窗口
比如说有多个窗口来回切换操作,2个窗口之间会有业务影响,一个窗口的界面数据修改会影响另外一个窗口的界面数据。可以注册NSWindowDidBecomeMainNotification,NSWindowDidBecomeKeyNotification消息,当窗口每次接收到这个消息可以重新获取数据刷新界面。
注册关闭窗口的消息通知,可以在窗口关闭前完成一些资源释放,提醒用户有变化的数据是否需要保存等。
六.contentView
查看NSWindow.h头文件,有2个重要的属性说明一下
@property (strong) id /* NSView * */ contentView;
@property (strong) NSViewController *contentViewController NS_AVAILABLE_MAC(10_10);
通过xib设计window元素布局的话,直接从控件库拖上去就行了。在运行过程中要动态增加view元素到NSWindow的话,使用window的contentView,它代表了window的根视图。
有2种方法改变NSWindow的contentView
1.可以使用自定义的NSView或NSViewController的view,增加到contentView
[self.window.contentView addSubview:view]
2.OSX 10.10系统及以后,创建一个NSViewController子类,实例化后赋值给NSWindow的contentViewController。
NSViewController *myVC = [NSViewController alloc]init];
self.window.contentViewController = myVC;
七.设置window的属性
//设置Window的image和title
[self.window setRepresentedURL:[NSURL URLWithString:@"WindowTitle"]];
[self.window setTitle:@"SQLiteApp"];
NSImage *image = [NSImage imageNamed:@"windowIcon"];
[[self.window standardWindowButton:NSWindowDocumentIconButton] setImage:image];
//设置窗口的背景颜色
[self.window setOpaque:NO];
[self.window setBackgroundColor:[NSColor greenColor]];
//阴影
self.window.hasShadow = YES;
NSShadow *outShadow = [[NSShadow alloc] init];
outShadow.shadowOffset = NSMakeSize(0, 1);
outShadow.shadowBlurRadius = 1;
outShadow.shadowColor = [NSColor colorWithRed:0 green:0 blue:0 alpha:0.1];
[self.window.contentView setShadow:outShadow];
//圆角
self.window.contentView.wantsLayer = YES;
self.window.contentView.layer.cornerRadius = 8;
self.window.contentView.layer.masksToBounds = YES;
//点击他处自动隐藏
self.window.hidesOnDeactivate = YES;
//居中 window有记忆功能,会记住上次退出前的位置,所以要把isRestorable设为NO
[self.window setRestorable:NO];
[self.window center];
//控制显示的位置
[self.window setRestorable:NO];
NSRect frame = NSMakeRect(0, 0, 100, 100);
[self.window setFrame:frame display:YES];
参考自《MacOS应用开发基础教程》