// // KMScreenShotHandler.swift // PDF Reader Pro // // Created by liujiajie on 2024/1/24. // import Foundation let KMCancelCurrentCapturingActionNotification = "KMCancelCurrentCapturingActionNotification" class KMScreenShotHandler: NSObject{ var isCapturing = false static let defaultManager = KMScreenShotHandler() class func fullScreenShot() -> NSImage { var screenShot = CGWindowListCreateImage(.infinite, .optionOnScreenOnly, kCGNullWindowID, []) let img2 = NSImage(cgImage: screenShot!, size: NSZeroSize) screenShot = nil return img2 } class func appointWindowScreenShot(withWindowID windowID: CGWindowID) -> NSImage? { let windowImage = CGWindowListCreateImage(.null, .optionIncludingWindow, windowID, []) let newImage = imageFromCGImageRef(windowImage) return newImage } class func imageFromCGImageRef(_ image: CGImage?) -> NSImage? { var imageRect = NSRect(x: 0.0, y: 0.0, width: 0.0, height: 0.0) var imageContext: CGContext? var newImage: NSImage? // Get the image dimensions. imageRect.size.height = CGFloat(image?.height ?? 0) imageRect.size.width = CGFloat(image?.width ?? 0) // Create a new image to receive the Quartz image data. if imageRect.size == CGSize.zero { return newImage } newImage = NSImage(size: imageRect.size) newImage?.lockFocus() // Get the Quartz context and draw. imageContext = NSGraphicsContext.current?.cgContext imageContext?.draw(image!, in: NSRectToCGRect(imageRect)) newImage?.unlockFocus() return newImage } class func screenPosition(for event: NSEvent) -> CGPoint { var point = event.locationInWindow point.x += event.window?.frame.origin.x ?? 0 point.y += event.window?.frame.origin.y ?? 0 return point } class func calculateString(_ aString: String, font aFont: NSFont) -> CGSize { let attributeString = NSMutableAttributedString(string: aString) let style = NSMutableParagraphStyle() style.lineSpacing = 10 attributeString.addAttribute(.paragraphStyle, value: style, range: NSRange(location: 0, length: aString.count)) attributeString.addAttribute(.font, value: aFont, range: NSRange(location: 0, length: aString.count)) let options: NSString.DrawingOptions = [.usesLineFragmentOrigin, .usesFontLeading] let rect = attributeString.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: options, context: nil) return CGSize(width: rect.size.width + 10, height: rect.size.height) } class func imageToPDFViaSavePanel(_ image: NSImage) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { let savePanel = NSSavePanel() let originalPDFName = "untitled" savePanel.nameFieldStringValue = originalPDFName + "_ScreenShot" savePanel.allowedFileTypes = ["pdf"] savePanel.begin { (result) in if result == .OK { let newDocument = CPDFDocument() _ = newDocument?.km_insert(imageData: image.jpgData() ?? Data(), pageSize: image.size, at: 0) let isSuccess = newDocument?.write(to: savePanel.url!) if isSuccess ?? false { NSDocumentController.shared.openDocument(withContentsOf: savePanel.url!, display: true) { (document, documentWasAlreadyOpen, error) in // Handle completion } } } } } } class func imageToPDF(_ image: NSImage) -> CPDFDocument? { let newDocument = CPDFDocument() _ = newDocument?.km_insert(imageData: image.jpgData() ?? Data(), pageSize: image.size, at: 0) let savePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last!.appending("/\(Bundle.main.bundleIdentifier!)/ScreenShot.pdf") let isSuccess = newDocument?.write(to: URL(fileURLWithPath: savePath)) if isSuccess ?? false { return newDocument } return nil } class func beginScreenShot_SelectWindowCompleteHandler(_ handler: @escaping captureScreenCallBack) { if KMScreenShotHandler.defaultManager.isCapturing == true { NotificationCenter.default.post(name: Notification.Name(KMCancelCurrentCapturingActionNotification), object: nil) } let screenShotWindow = KMScreenShotMaskWindowController { (ima) in if let image = ima { handler(image) } } screenShotWindow.beginImageCapture(true) } class func beginScreenShot_FullSreenWithDelayTime(_ delayTime: NSInteger, completeHandler handler: @escaping captureScreenCallBack) { if KMScreenShotHandler.defaultManager.isCapturing { NotificationCenter.default.post(name: Notification.Name(KMCancelCurrentCapturingActionNotification), object: nil) } KMScreenShotHandler.defaultManager.isCapturing = true let screenShotWindow = KMScreenShotMaskWindowController(fullScreenShot: delayTime, completeHandler: { (ima) in KMScreenShotHandler.defaultManager.isCapturing = false if let image = ima { handler(image) } }) } class func beginScreenshot_SelectRectWithCompleteHandler(_ handler: @escaping captureScreenCallBack) { if KMScreenShotHandler.defaultManager.isCapturing { NotificationCenter.default.post(name: Notification.Name(KMCancelCurrentCapturingActionNotification), object: nil) } let screenShotWindow = KMScreenShotMaskWindowController( handler: { (ima) in if let image = ima { handler(image) } }) screenShotWindow.beginImageCapture(false) } // func setIsCapturing(iscapturing: Bool) { // self.isCapturing = iscapturing // } }