如果您想使用比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实例,但它们是您无法直接访问的私有子类。您可以通过在窗口上调用display
来强制它们重新绘制,但这可能会覆盖您对窗口所做的任何操作,因为它将使用这些类的现有绘图例程。
因此,您可能还想考虑交换这些视图的drawRect:方法(在drawRect:中调用[[NSGraphicsContext currentContext] graphicsPort]将为您提供一个CGContextRef,您可以使用Quartz API与之一起使用)。您可以通过在窗口的内容视图上调用superview
来获取框架视图。
请注意,窗口框架视图的排列未经记录,可能会随着系统更新而更改。
无论如何,听起来是一个有趣的项目!