NSWindow.contentView
中的draw方法,渲染高亮区域的图像覆盖背景创建NSWindowController,NSWindow,NSView对应的子类:
在ClipManager.shared.start()
中创建控制器、窗口和页面的对象并建立关系:
func start() {
guard let screen = NSScreen.main else { return } // 单显示器环境
NSApplication.shared.activate(ignoringOtherApps: true) // 在触发快捷键后激活App,使开启的窗口能够变为key window
let view = ClipView(frame: screen.frame)
let clipWindow = ClipWindow(contentRect: screen.frame, contentView: view)
let clipWindowController = ClipWindowController(window: clipWindow)
self.controllers.append(clipWindowController) // 将其加入当前保存的控制器中
self.status = .ready
clipWindowController.capture(screen)
}
ClipWindow的条件在初始化时既可以满足:
class ClipWindow: NSWindow {
init(contentRect: NSRect, contentView: ClipView) {
super.init(contentRect: contentRect, styleMask: .borderless, backing: .buffered, defer: false)
self.contentView = contentView // ClipView as its contentView
self.level = .statusBar
}
}
我们暂时不使用鼠标监听事件来获取高亮区域,而是使用一个临时的NSRect来表示我们所选取的范围:
let tmpRect = NSRect(x: 300, y: 300, width: 200, height: 400)
调用ClipWindowController.capture(screen)
进入准备Clip的状态。在capture中实现获取当前屏幕图像,并设置Window的透明背景功能,最后显示ClipWindow:
class ClipWindowController: NSWindowController {
var clipView: ClipView? // 为了方便使用self.window.view
var screenImage: NSImage? // 背景图片
let tmpRect = NSRect(x: 300, y: 300, width: 200, height: 400)
func capture(screen: NSScreen) {
guard let window = self.window else { return }
guard let cgScreenImage = CGDisplayCreateImage(CGMainDisplayID()) else { return } // 获取主显示器的CGImage
self.screenImage = NSImage(cgImage: cgScreenImage, size: screen.frame.size) // 转化为NSImage
window.backgroundColor = NSColor(white: 0, alpha: 0.5) // 设置背景为透明,透明度为0.5
self.clipView = window.contentView as? ClipView
self.showWindow(nil)
}
}