开发者

How to implement a custom Focus Ring in drawRect for NSTextField or NSTextVew

I want to draw a custom focus ring for my NSTextView subclass (which doesn't have a focus ring by default). I managed to implement it by overriding the parent NSScrollView drawRect and adding this code:

- (void)drawRect:(NSRect)dirt开发者_开发知识库yRect {
    if (focused) {
        NSSetFocusRingStyle(NSFocusRingOnly);
        NSRectFill(dirtyRect);
    }

    [super drawRect:dirtyRect];
}

However, I want to draw my own, custom focus ring. I have searched and searched for examples of this, and tried messing around and writing it myself, to no avail. The biggest issue I have is the fact that it will get cropped to the NSScrollView/NSTextView frame, no matter how I do it.

Thanks.


Updating this answer for 10.7+:

Now you should override drawFocusRingMask to render (simply drawing a shape; the system will take care of color/style), and override focusRingMaskBounds to hint at its boundaries. Also, call noteFocusRingMaskChanged if you change the shape in some way that the system could not figure out on its own.


(Below is the previous answer, requiring older APIs:)

In the Carbon framework there are HIThemeBeginFocus() and HIThemeEndFocus(), which allow you to cause any series of drawings (such as a rectangle or shape) to have an automatic "focused" appearance. Requires Mac OS X 10.5 or later.

This uses Core Graphics directly. To find the CG context from a drawRect: method in Cocoa, you'd do something like:

NSGraphicsContext* contextMgr = [NSGraphicsContext currentContext];
CGContextRef drawingContext = (CGContextRef)[contextMgr graphicsPort];

As far as avoiding clipping, one option is to use a parent view (such as an NSBox that has no border) to give extra padding. Perform the custom drawing at an inset location in the parent view that won't be clipped; in other words, give the illusion that the view is a bit smaller than its actual rectangle.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜