效果

实现思路

实现过程

创建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)
		}
}