如果您要求使用比 Cocoa 更低级别的 API 强制窗口重绘自身的方法,那么据我所知,这是不可能的。一个窗口在其内容视图的 drawRect: 方法被调用时重绘自己。它将 CGContextRef 传递给窗口,然后该方法使用它来重绘窗口。 CoreGraphics 不负责重绘窗口。 Cocoa 使用 CoreGraphics 重绘窗口。
可以在 drawRect: 之外获取窗口的图形上下文,然后在需要时绘制到该窗口(参见,例如,here),
但听起来你真正想要做的是截取窗口的普通绘图例程的结果并在上面做一些你自己的事情。您可以通过切换窗口内容视图的类并覆盖 drawRect 来做到这一点。处理注入的辅助函数如下所示:
typedef void (^InjectedBlock)(CGContextRef, CGRect);
void InjectIntoView(NSView* view, InjectedBlock aBlock)
{
Class viewClass = [view class];
InjectedBlock injectedBlock = [aBlock copy];
void(^drawRect)(id, SEL, NSRect) = ^(id self, SEL _cmd, NSRect rect)
{
struct objc_super superId = { self, viewClass };
objc_msgSendSuper(superId, @selector(drawRect:), rect);
injectedBlock([[NSGraphicsContext currentContext] graphicsPort], CGRectFromNSRect(rect));
};
NSString* subclassName = [NSString stringWithFormat:"%s_injected", class_getName(viewClass)]
Class subclass objc_allocateClassPair(viewClass, [subclassName UTF8String], 0);
objc_registerClassPair(subclass);
Method overriddenMethod = class_getInstanceMethod([NSView class], @selector(drawRect:));
IMP imp = imp_implementationWithBlock(drawRect);
class_addMethod(subclass, @selector(drawRect:), imp, method_getTypeEncoding(overriddenMethod))
}
编辑:
啊,你对整个窗口感兴趣。框架等也是 NSView 实例,但它们是您无法直接访问的 NSView 的私有子类。您可以通过在窗口上调用 display 来强制它们重绘,但这可能会覆盖您对窗口所做的任何事情,因为它将使用这些类的现有绘图例程。
因此,您可能还需要考虑调整这些视图的 drawRect: 方法(drawRect: 中对 [[NSGraphicsContext currentContext] graphicsPort] 的调用将为您提供可与 Quartz API 一起使用的 CGContextRef)。您可以通过在窗口的内容视图上调用 superview 来获取框架视图。
请注意,窗口的框架视图的排列没有记录,可能会随着系统更新而改变。
无论如何,这听起来像是一个有趣的项目!