ADA笔记:Window Programming Guide(三)

Sat 18 May 2019 / In categories Programming

AppKit, Cocoa

本文是Apple Documentation Archive Window Programming Guide的学习笔记。

设置窗口集合的行为

Setting Window Collection Behavior

窗口服务器支持若干个窗口集合,比如Spaces, Exposé和“Cycle Through Windows” 。通过setCollectionBehavior:,一个窗口可以在某种程度上决定自己在窗口集合中的行为。

对于Spaces集合(虚拟桌面),默认的行为是NSWindowCollectionBehaviorDefault,也就是窗口只在某个Space中显示。如果把行为修改成NSWindowCollectionBehaviorCanJoinAllSpaces,则窗口会在所有的Spaces显示。第三个选项是NSWindowCollectionBehaviorMoveToActiveSpace,这会把窗口永远显示在激活的Space上。

isOnActiveSpace告知窗口所在的Space是否是激活的。通过windowNumbersWithOptions:可以获取一组Space中和窗口相关的属性,具体的选项在NSWindowNumberListOptions中列举。

对于Exposé集合,对于正常等级(NSNormalWindowLevel)的窗口,其默认行为是NSWindowCollectionBehaviorManaged,窗口会同时在Spaces和Exposé中。如果不是正常等级的窗口,默认行为是NSWindowCollectionBehaviorTransient,不会在Exposé中显示。最后一个选项是 NSWindowCollectionBehaviorStationary,具有这个选项的窗口不受Exposé影响。

对于“Cycle Through Windows”集合(Cmd+~),有两个选项可以控制其行为:NSWindowCollectionBehaviorParticipatesInCycleNSWindowCollectionBehaviorIgnoresCycle。前一个选项使窗口参与“Cycle Through Windows”,具有后一个选项的窗口则不参与。

设置窗口大小的位置

Sizing and Placing Windows

如果窗口时一片纸,而屏幕是一个矩形平面,窗口需要决定自己在这平面上的位置。使用center方法可以把窗口放置在屏幕的中央。可以通过setFrame:display:或者setFrame:display:animate:来调整窗口自身的大小和位置。前面的第二个方法会在窗口变化的过程中采用一定的动画效果,动画的持续时间可以用animationResizeTime:获取。

用户可以通过拖曳等方式主动改变窗口大小。在用户做次操作的过程中,inLiveResize会返回YES。如果用户想移动窗口,他可以拖动窗口的标题栏。也可以通过自定义mouseDownCanMoveWindow来允许用户拖动标题栏以外的视图区域。如果想禁止用户拖动窗口,可以setMovable:isMovable返回setMovable:的结果。

如果使用setFrame:去更新窗口大小,窗口的委任不会收到windowWillResize:toSize:通知,但是可以收到windowDidResize:通知。注意,windowDidResize:本身不区分是用户在调整窗口大小还是程序自身在调整窗口大小。

对于文档窗口,可以通过NSWindowControllersetShouldCascadeWindows:方法来设置文档窗口之间是否级联显示。默认是采用级联显示的,也就是说老的窗口的标题栏不会被新窗口遮蔽。对于非文档窗口,可以使用NSWindowcascadeTopLeftFromPoint:来手动进行级联显示,这个方法会告知下一个窗口如何摆放才不会遮蔽当前窗口的标题栏。

zoom:可以在程序默认的窗口大小和用户调整后的窗口大小之间切换。

setContentMinSize:可以设置窗口内容区域的最小值,setContentMaxSize:可以设置窗口内容区域的最大值, setContentAspectRatio: 可以限制窗口内容区域的长宽比。 setContentResizeIncrements: 可以限定窗口调整大小时候的步长(默认是1像素)。如果想直接设置窗口大小,可以使用setAspectRatio:, setMaxSize:等。

constrainFrameRect:toScreen:可以给窗口设置一个屏幕区域,窗口只能在这个屏幕区域内调整大小。对于有标题栏的窗口,默认的可调整大小的区域在整个屏幕之内,不会超出屏幕范围。

保存窗口的位置信息

Saving a Window’s Position into the User’s Defaults

一个窗口的位置信息是可以存储到硬盘上用户相关的配置中的。saveFrameUsingName:会把当前窗口的位置信息保存,setFrameUsingName:从保存的信息中恢复窗口位置。setFrameAutosaveName:可以自动保存当前窗口的位置信息。值得注意的是,上述操作和窗口级联有冲突,需要使用setShouldCascadeWindows:NO来关闭窗口控制器相关的功能。removeFrameUsingName:可以从硬盘上删除已经保存的窗口位置信息。

最小化窗口

Minimizing Windows

通过miniaturize:可以把窗口最小化到Dock,deminiaturize:会恢复窗口。performMiniaturize:会模拟用户最小化窗口的行为(视觉上?)。最小化后的窗口的图标可以通过setMiniwindowImage:设置,标题可以通过setMiniwindowTitle:设置。这些都是NSWindow的方法。

使用Window菜单

Using the Window Menu

标准的Cocoa应用(macOS的GUI应用)都有带有一个Window菜单,可以用来对应用的窗口们做一些操作。通常情况下你不需要去修改此菜单的行为。

需要的话,有一些方法可以干预Window菜单的行为。setExcludedFromWindowsMenu:YES可以避免一个窗口被列在Window菜单之下。面板类型的窗口不会出现在Window菜单下,因为它们不能成为应用的主窗口。但是NSPanel的派生类可以对面板的默认行为做一些修改,比如在isExcludedFromWindowsMenu中返回NO,可以让此派生类在Window菜单中显示;canBecomeMainWindow返回YES可以让此派生类成为主窗口。

此外,如果原先一个窗口不能被添加到Window菜单,随后又被修改成可以的,这个窗口可能不会自动出现在Window菜单中。可以使用addWindowsItem:title:filename:主动添加此窗口到Window菜单,使用removeWindowsItem:可以主动从Window菜单中移除那些已经不能被列举在Window菜单的窗口。

设置窗口的显示效果

Setting a Window’s Appearance

窗口的风格是由窗口的周遭元素决定的,比如标题栏、状态栏等。这些,你的应用是无法直接访问和修改的。但是可以在窗口初始化的时候指定所需要添加的周遭元素,比如:

  • NSTitledWindowMask,添加标题栏
  • NSClosableWindowMask,添加关闭按键
  • NSMiniaturizableWindowMask,添加最小化按键
  • NSResizableWindowMask,添加窗口大小调整相关的元素

如果指定的是NSBorderlessWindowMask,那么上面的元素都不会有,你将得到一个完全空白的窗口。

如果在窗口初始化的时候禁用了某个按键,比如关闭按键,但是后来又想启用它,可以通过standardWindowButton:来获取这个按键,然后改变它的显示状态。

NSButton *closeButton = [window standardWindowButton:NSWindowCloseButton];

[closeButton setEnabled:YES];

setOpaque可以用来设置窗口的透光性。窗口的背景可以通过setBackgroundColor:修改。注意,上述操作可以使窗口透明,但是窗口的标题栏不受影响,并且窗口中的那些不透光的视图也不收影响。如果想影响整个窗口,可以通过setAlphaValue:修改。

通过setColorSpace:可以设置窗口的颜色区域。具体参考:NSColorSpace Class Reference.

setContentBorderThickness:forEdge:可以设置内容边框的厚度。setAutorecalculatesContentBorderThickness:forEdge:可以设置是否在重回窗口梯度背景的时候对边框产生影响。(OS X 10.5引进的功能)。

设置窗口的标题栏和其所代表的文件

Setting a Window’s Title and Represented File

窗口的标题可以通过setTitle:设置成任何值。但是对于文档型的窗口,让标题栏显示当前文档对应的文件是一个不错的主意。setTitleWithRepresentedFilename:把一个文件路径作为窗口的标题。setRepresentedFilename:可以修改标题栏关联的文件路径。通过setDocumentEdited:可以在标题栏上示意文件有改动(提示用户需要保存)。

从OS X 10.5开始,可以把标题栏和一个URL关联,setRepresentedURL:representedURL可以获取关联的URL。

标题栏可以显示一个文档图标,可以通过下面的方式修改图标的内容:

[[NSWindow standardWindowButton:NSWindowDocumentIconButton] setImage:customImage].

默认情况下按住Cmd或者Control然后点击文档图标会弹出显示文件的路径。此行为受窗口代理的window:shouldPopUpDocumentPathMenu:控制,返回NO表示禁止这个行为。此外,在窗口代理的window:shouldDragDocumentWithEvent:from:withPasteboard:返回NO,会禁止文档图标的拖动。

(本篇完)

Load Disqus Comments