以编程方式截取 NSView 或 NSWindow 屏幕截图?

Kib*_*tik 6 macos screenshot objective-c

我需要将 NSView 捕获到图像中。捕获 NSWindow 也很好 - 我可以稍后裁剪出必要的视图。

我有两个要求:(1)我在视图上有半透明的按钮;(2) 即使视图部分超出屏幕,我也需要捕获图像。

这是我想要捕捉的视图:

在此输入图像描述

这四种方法我都试过了,没有一个能达到我想要的效果。

方法一。

NSImage *image = [[NSImage alloc] initWithData:[view dataWithPDFInsideRect:viewRect]];
NSData *imageData = [image TIFFRepresentation];
[imageData writeToFile:fName atomically:NO];
Run Code Online (Sandbox Code Playgroud)

此方法保留按钮透明度,但忽略其图层添加,如花哨的边框:

在此输入图像描述

方法2.

这是捕获 NSView 内容的推荐方法:

NSBitmapImageRep *imageRep = [view bitmapImageRepForCachingDisplayInRect:viewRect];
[view cacheDisplayInRect:viewRect toBitmapImageRep:imageRep];
NSImage *image = [[NSImage alloc] initWithSize:viewRect.size];
[image addRepresentation:imageRep];
NSData *imageData = [image TIFFRepresentation];
[imageData writeToFile:fName atomically:NO];
Run Code Online (Sandbox Code Playgroud)

此方法保留图层特征但忽略按钮透明度:

在此输入图像描述

方法3.

这个方法只是将视图层渲染成图像:

NSImage *image = [[NSImage alloc] initWithSize:viewRect.size];
[image lockFocus];
CGContextRef ctx = [NSGraphicsContext currentContext].graphicsPort;
[view.layer renderInContext:ctx];
[image unlockFocus];
NSData *imageData = [image TIFFRepresentation];
[imageData writeToFile:fName atomically:NO];
Run Code Online (Sandbox Code Playgroud)

此方法还保留图层特征但忽略按钮透明度:

在此输入图像描述

方法4.

CGImageRef cgimg = CGWindowListCreateImage(CGRectZero, kCGWindowListOptionIncludingWindow, (int)self.window.windowNumber, kCGWindowImageBoundsIgnoreFraming);
NSImage *image = [[NSImage alloc] initWithCGImage:cgimg size:viewRect.size];
NSData *imageData = [image TIFFRepresentation];
[imageData writeToFile:fName atomically:NO];
Run Code Online (Sandbox Code Playgroud)

此方法保留图层功能和按钮透明度,但如果视图部分超出屏幕,则它不会渲染超出屏幕的部分:

在此输入图像描述

那么,我做错了什么?如何像系统屏幕截图实用程序一样获取屏幕截图?