Cocoa/OSX - NSWindow standardWindowButton ведет себя странно, как только копируется и добавляется снова
В моем приложении я меняю положение стандартных кнопокWindowButtons 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];
Теперь, когда появляется окно с кнопками, есть две проблемы:
1. Они серые, а не их правильный цвет
2. Когда мышь над ними, они не показывают знак + или x
может кто-нибудь сказать мне, что я делаю неправильно. Спасибо.
Ответы
Ответ 1
Вот механика этой магии наведения: перед тем, как рисовать стандартную кнопку с круговым движением (например, NSWindowMiniaturizeButton
), вызывается их superview
недокументированный метод _mouseInGroup:
. Если этот метод возвращает YES
, круглая кнопка рисует себя со значком внутри. Это все.
Если вы разместите эти кнопки внутри своего собственного вида, вы можете просто реализовать этот метод и управлять этим поясом мыши, как хотите. Если вы просто перемещаете или ретранслируете эти кнопки, и они по-прежнему остаются subview
NSThemeFrame
(или что-то подобное), вы должны использовать метод swizzle _mouseInGroup:
для этого класса, и, вероятно, это не стоит, потому что у нас есть совершенно простые предыдущий метод.
В моем случае у меня есть пользовательский NSView
, который содержит стандартные кнопки в качестве subview
, и этот код делает все описанное выше magic:
- (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];
}
Ответ 2
Я полностью понимаю, что этот вопрос старый, и ответ Валентина Шергина правильный. Это предотвращает использование любого Private API, в отличие от Google в 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:
. Должен работать, пока окно загружено и видимо.)
Ответ 3
Вы не добавляете их снова. Вы перемещаете их в contentView. Кнопки изначально находятся в окне window.contentView.superview.
[window.contentView.superview addSubview:closeButton];
[window.contentView.superview addSubview:fullScreenButton];
[window.contentView.superview addSubview:minitButton];
Должно получиться правильное поведение, не требуя отслеживания.
Ответ 4
Вызовите [button highlight:yes]
для каждой кнопки.