Mac OS - Swift:获取包含程序坞(Dock)与菜单栏的屏幕
嘿,这个问题我之前做屏幕截图工具的时候也踩过坑!其实NSScreen本身是能拿到包含Dock和菜单栏的整个屏幕区域的,不过如果是要捕获这个区域的图像,就得靠CoreGraphics的API了,我给你详细说下:
1. 先搞清楚NSScreen的两个关键属性
首先别搞混frame和visibleFrame:
NSScreen.main?.frame:这就是整个屏幕的完整边界,包含Dock、菜单栏所有区域,坐标原点在屏幕左下角(macOS的坐标系统)。NSScreen.main?.visibleFrame:这是应用程序可以安全使用的区域,自动排除了Dock和菜单栏的占用空间。
如果你只是需要获取这个完整屏幕的尺寸/位置信息,直接用frame就够了。
2. 捕获包含Dock和菜单栏的屏幕截图
如果你的需求是生成整个屏幕的截图(包含Dock和菜单),NSScreen帮不上忙,得用CoreGraphics的CGDisplayCreateImage方法,它会直接捕获指定显示器的全部内容:
Swift 代码示例
import Cocoa import CoreGraphics func captureFullScreen() -> NSImage? { // 获取主屏幕的Display ID let mainDisplayID = CGMainDisplayID() // 捕获整个屏幕图像(包含Dock和菜单栏) guard let cgImage = CGDisplayCreateImage(mainDisplayID) else { print("屏幕捕获失败") return nil } // 转换成NSImage方便后续处理 let nsImage = NSImage(cgImage: cgImage, size: NSSize(width: cgImage.width, height: cgImage.height)) return nsImage } // 调用示例 if let fullScreenImage = captureFullScreen() { // 这里可以把图像保存到本地或者显示在界面上 let savePanel = NSSavePanel() savePanel.allowedContentTypes = [.png] if savePanel.runModal() == .OK, let url = savePanel.url { try? fullScreenImage.pngData?.write(to: url) } }
Objective-C 代码示例
#import <Cocoa/Cocoa.h> #import <CoreGraphics/CoreGraphics.h> NSImage *captureFullScreen() { CGDirectDisplayID mainDisplayID = CGMainDisplayID(); CGImageRef cgImage = CGDisplayCreateImage(mainDisplayID); if (!cgImage) { NSLog(@"屏幕捕获失败"); return nil; } NSImage *nsImage = [[NSImage alloc] initWithCGImage:cgImage size:NSMakeSize(CGImageGetWidth(cgImage), CGImageGetHeight(cgImage))]; CGImageRelease(cgImage); return nsImage; } // 调用示例 NSImage *fullScreenImage = captureFullScreen(); if (fullScreenImage) { NSSavePanel *savePanel = [NSSavePanel savePanel]; savePanel.allowedContentTypes = @[NSBitmapImageFileTypePNG]; if ([savePanel runModal] == NSModalResponseOK) { NSData *pngData = [fullScreenImage TIFFRepresentation]; NSBitmapImageRep *bitmapRep = [NSBitmapImageRep imageRepWithData:pngData]; pngData = [bitmapRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; [pngData writeToURL:savePanel.URL atomically:YES]; } }
3. 重要注意事项
- 权限问题:macOS 10.15(Catalina)及以后的系统,屏幕录制需要用户授权。你必须在项目的
Info.plist中添加NSScreenCaptureUsageDescription键,填写一段说明文字(比如“需要捕获屏幕内容以生成完整截图”),否则程序会崩溃或者被系统拒绝访问屏幕。 - 多屏幕场景:如果要捕获非主屏幕,你可以通过
CGGetActiveDisplayList获取所有显示器的ID,再针对特定ID调用CGDisplayCreateImage。
4. 实时屏幕捕获(比如屏幕共享)
如果需要实时获取屏幕流,推荐用CGDisplayStream,它能高效地获取连续的屏幕帧,适合做屏幕共享、直播这类场景,用法和单次捕获类似,只是需要处理回调中的每一帧数据。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

