简体   繁体   中英

NSWindow Shadow Outline

I am drawing a custom window by setting a custom content view for the window. When I draw the custom view I give it rounded corners and a nice outline to mimic a proper window.

However, I see another 1 px outline around the window which strays from the edge at the corners. I have found that if I turn off the shadow it goes away, but obviously as this wants to act like a window I need the shadow. Here's what I mean about the 1px outline:

在此处输入图像描述

How can I prevent this?


EDIT

Code for drawing the custom window's content view:

    NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] cornerRadius:5];

    NSGradient* aGradient = [[[NSGradient alloc] initWithColorsAndLocations:
                              [NSColor colorWithDeviceRed:0.5569 green:0.5137 blue:0.4588 alpha:1.0000], 0.0,
                              [NSColor colorWithDeviceRed:0.5569 green:0.5137 blue:0.4588 alpha:1.0000], 1.0,
                              nil] autorelease];

    [aGradient drawInBezierPath:path angle:90];

    [path setLineWidth:4];
    [[NSColor colorWithDeviceRed:0.4235 green:0.3922 blue:0.3451 alpha:0.9000] setStroke];
    [path strokeInside];

    [path setLineWidth:3];
    [[NSColor colorWithDeviceRed:0.8431 green:0.8314 blue:0.8078 alpha:1.0000] setStroke];
    [path strokeInside];

    [path setLineWidth:1];
    [[NSColor colorWithDeviceRed:0.4235 green:0.3922 blue:0.3451 alpha:0.9000] setStroke];
    [path strokeInside];

Don't ask me how I got this, but this will solve your problem.

Define a category for NSWindow with the following content:

@implementation NSWindow(NoShadowRim)

- (id)_shadowRimInfo {
  return @{
    @"kCUIMeasureWindowFrameRimDensity": [NSNumber numberWithInt:0]
  };
}

@end

DISCLAIMER: This overrides the internal method of NSWindow , so use it at your own risk. It may break with any OS X update.

You need to tell the window to recompute its shadow by sending it -invalidateShadow .

Try:

[[self window] display];
[[self window] setHasShadow:NO];
[[self window] setHasShadow:YES];

As I understand correctly, shadows are drawn by windows server. When you draw custom NSWindow with rounded corners or other not rectangular shapes, window server don't count those transparent pixels and dont drop shadow under them.

I developed some hack to avoid such behavior. Just drop additional shadow under your path, something like this:

NSShadow *headShadow = [[NSShadow alloc] init];
[headShadow setShadowColor:[NSColor colorWithSRGBRed:0.0 
                                               green:0.0 
                                                blue:0.0 
                                               alpha:0.16]];
[headShadow setShadowBlurRadius:0.0f];
[headShadow setShadowOffset:NSMakeSize(0.0f, 0.0f)];
[headShadow set];

Ideally for perfect result i fink shadow must be equal to window servers.

This line contouring the window area is drawn automatically. I have a window which has this line running accurately around bottom rounded corners. You have to setup the window as non-opaque and the background color to transparent:

  [self setOpaque:NO];
  [self setBackgroundColor:[NSColor clearColor]];

The somewhere in the contentView -drawRect: you do

  [NSGraphicsContext saveGraphicsState];
  [pathWithBottomRoundedCorner addClip];
  // your drawing here...
  [NSGraphicsContext restoreGraphicsState];

That should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM