You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:57:51