How to draw a NSImage like images in NSButtons (with a deepness)?

前端 未结 4 1710
遥遥无期
遥遥无期 2020-12-22 18:37

Is there any way to draw an NSImage like images in NSButtons or other cocoa interface elements?

Here are examples:

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-22 18:47

    If you don't mind calling a private API, you can let the operating system (CoreUI) do the shading for you. You need a few declarations:

    typedef CFTypeRef CUIRendererRef;
    extern void CUIDraw(CUIRendererRef renderer, CGRect frame, CGContextRef context, CFDictionaryRef object, CFDictionaryRef *result);
    
    @interface NSWindow(CoreUIRendererPrivate)
    + (CUIRendererRef)coreUIRenderer;
    @end
    

    And for the actual drawing:

    CGRect drawRect = CGRectMake(x, y, width, height);
    CGImageRef cgimage = your_image;
    
    CFDictionaryRef dict = (CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
            @"backgroundTypeRaised", @"backgroundTypeKey",
            [NSNumber numberWithBool:YES], @"imageIsGrayscaleKey",
            cgimage, @"imageReferenceKey",
            @"normal", @"state",
            @"image", @"widget",
            [NSNumber numberWithBool:YES], @"is.flipped",
            nil];
    CUIDraw ([NSWindow coreUIRenderer], drawRect, cg, dict, nil);
    CGImageRelease (cgimage);
    

    This will take the alpha channel of cgimage and apply the embossing effect as seen on toolbar buttons. You may or may not need the "is.flipped" line. Remove it if your result is upside-down.

    There are a bunch of variations:

    kCUIPresentationStateKey = kCUIPresentationStateInactive: The window is not active, the image will be lighter.

    state = rollover: Only makes sense with the previous option. This means you are hovering over the image, the window is inactive, but the button is sensitive (click-through is enabled). It will become darker.

    state = pressed: Occurs when the button is pressed. The icon gets slightly darker.

    Bonus tip: To find out stuff like this, you can use the SIMBL plugin CUITrace. It prints out all the CoreUI invocations of a target app. This is a treasure trove if you have to draw your own native-looking UI.

提交回复
热议问题