问题 Cocoa / OSX - NSWindow standardWindowButton表现奇怪,一旦复制并再次添加


在我的应用程序中,我更改standardWindowButtons close / miniturize / expand的位置,如下所示:

 //Create the buttons
    NSButton *minitButton = [NSWindow standardWindowButton:NSWindowMiniaturizeButton forStyleMask:window.styleMask];
NSButton *closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:window.styleMask];
NSButton *fullScreenButton = [NSWindow standardWindowButton:NSWindowZoomButton forStyleMask:window.styleMask];


//set their location
[closeButton setFrame:CGRectMake(7+70, window.frame.size.height - 22 - 52, closeButton.frame.size.width, closeButton.frame.size.height)];
[fullScreenButton setFrame:CGRectMake(47+70, window.frame.size.height - 22 -52, fullScreenButton.frame.size.width, fullScreenButton.frame.size.height)];
[minitButton setFrame:CGRectMake(27+70, window.frame.size.height - 22 - 52, minitButton.frame.size.width, minitButton.frame.size.height)];

//add them to the window
[window.contentView addSubview:closeButton];
[window.contentView addSubview:fullScreenButton];
[window.contentView addSubview:minitButton];

现在,当窗口出现按钮时,存在两个问题: 它们是灰色的而不是正确的颜色 2.当鼠标悬停在它们上面时,它们不显示+ - 或x符号

任何人都可以告诉我我做错了什么。谢谢。


2685
2017-10-03 12:09


起源



答案:


这是这种悬停魔法的机制:在绘制自己标准的圆圈按钮之前(例如 NSWindowMiniaturizeButton打电话给他们 superview 无证方法 _mouseInGroup:。如果此方法返回 YES 带圆圈的按钮用里面的图标绘制自己。就这样。

如果将这些按钮放在自己的视图中,则只需实现此方法并根据需要控制鼠标悬停外观。如果您只是移动或重新布局这些按钮,它们仍然存在 subviewNSThemeFrame (或类似的东西),你必须调酒方法 _mouseInGroup: 对于这个类,可能它不值得,因为我们有完全简单的先前方法。

在我的情况下,我有自定义 NSView 包含我的标准按钮 subviews和这段代码使上述所有内容变得神奇:

- (void)updateTrackingAreas
{
    NSTrackingArea *const trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect) owner:self userInfo:nil];
    [self addTrackingArea:trackingArea];
}

- (void)mouseEntered:(NSEvent *)event
{
    [super mouseEntered:event];
    self.mouseInside = YES;
    [self setNeedsDisplayForStandardWindowButtons];
}

- (void)mouseExited:(NSEvent *)event
{
    [super mouseExited:event];
    self.mouseInside = NO;
    [self setNeedsDisplayForStandardWindowButtons];
}

- (BOOL)_mouseInGroup:(NSButton *)button
{
    return self.mouseInside;
}

- (void)setNeedsDisplayForStandardWindowButtons
{
    [self.closeButtonView setNeedsDisplay];
    [self.miniaturizeButtonView setNeedsDisplay];
    [self.zoomButtonView setNeedsDisplay];
}

10
2018-05-23 20:40



在swift中不起作用。 - Li Fumin
@LiFumin你可能需要将_mouseInGroup方法标记为'@objc'。 - Valentin Shergin
刚尝试过,仍然无法正常工作。 @ValentinShergin - Li Fumin


答案:


这是这种悬停魔法的机制:在绘制自己标准的圆圈按钮之前(例如 NSWindowMiniaturizeButton打电话给他们 superview 无证方法 _mouseInGroup:。如果此方法返回 YES 带圆圈的按钮用里面的图标绘制自己。就这样。

如果将这些按钮放在自己的视图中,则只需实现此方法并根据需要控制鼠标悬停外观。如果您只是移动或重新布局这些按钮,它们仍然存在 subviewNSThemeFrame (或类似的东西),你必须调酒方法 _mouseInGroup: 对于这个类,可能它不值得,因为我们有完全简单的先前方法。

在我的情况下,我有自定义 NSView 包含我的标准按钮 subviews和这段代码使上述所有内容变得神奇:

- (void)updateTrackingAreas
{
    NSTrackingArea *const trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect) owner:self userInfo:nil];
    [self addTrackingArea:trackingArea];
}

- (void)mouseEntered:(NSEvent *)event
{
    [super mouseEntered:event];
    self.mouseInside = YES;
    [self setNeedsDisplayForStandardWindowButtons];
}

- (void)mouseExited:(NSEvent *)event
{
    [super mouseExited:event];
    self.mouseInside = NO;
    [self setNeedsDisplayForStandardWindowButtons];
}

- (BOOL)_mouseInGroup:(NSButton *)button
{
    return self.mouseInside;
}

- (void)setNeedsDisplayForStandardWindowButtons
{
    [self.closeButtonView setNeedsDisplay];
    [self.miniaturizeButtonView setNeedsDisplay];
    [self.zoomButtonView setNeedsDisplay];
}

10
2018-05-23 20:40



在swift中不起作用。 - Li Fumin
@LiFumin你可能需要将_mouseInGroup方法标记为'@objc'。 - Valentin Shergin
刚尝试过,仍然无法正常工作。 @ValentinShergin - Li Fumin


我完全清楚这个问题是  和 瓦伦丁谢尔金的答案 是 正确。它阻止任何利用 私有API不像 谷歌在Chrome中做过。只是想为那些不喜欢子类的人分享一个方法 NSView 只是将这些按钮放在现有视图中(例如 self.window.contentView)。

因为我只是想重新定位 NSWindowButton通过 setFrame:,我发现一旦窗户出现了 调整,跟踪区域似乎“固定“ 他们自己 自动地没有任何私有API使用 (至少在10.11)。

因此,您可以执行以下操作以应用“假大小“到你重新定位按钮的窗口:

NSRect frame = [self.window frame];
frame.size = NSMakeSize(frame.size.width, frame.size.height+1.f);
[self.window setFrame:frame display:NO animate:NO];
frame.size = NSMakeSize(frame.size.width, frame.size.height-1.f);
[self.window setFrame:frame display:NO animate:YES];

(我是在主窗口内完成的 NSWindowDelegate  windowDidBecomeMain:。只要窗口加载就应该工作 可见。)


1
2018-03-29 18:49





你不是要再添加它们。您正在将它们移动到contentView。这些按钮最初位于window.contentView.superview中。

[window.contentView.superview addSubview:closeButton];
[window.contentView.superview addSubview:fullScreenButton];
[window.contentView.superview addSubview:minitButton];

无需trackingArea即可获得正确的行为。


0
2017-07-02 18:20





呼叫 [button highlight:yes] 对于每个按钮。


-1
2017-12-24 10:21



可悲的是 [button highlight:YES] 仅绘制窗口按钮的“按下”状态(参考)。我不知道有什么方法可以画出“悬停”状态。 - rentzsch