在我的应用程序中,我更改了标准窗口按钮关闭/缩小/展开的位置,如下所示:
//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 符号
谁能告诉我我做错了什么。谢谢。
这是这种悬停魔法的机制:在绘制自身之前,标准圆形按钮(例如
NSWindowMiniaturizeButton
)调用其superview
未记录的方法_mouseInGroup:
。如果此方法返回 YES
,则圆形按钮会在内部绘制图标。仅此而已。
如果您将这些按钮放在您自己的视图中,您可以简单地实现此方法并根据需要控制此鼠标悬停外观。如果你只是移动或重新布局这些按钮,而它们仍然是
subview
的 NSThemeFrame
(或类似的东西),那么你必须为这个类调整方法 _mouseInGroup:
,而且可能不值得,因为我们有完美的简单的以前的方法。
就我而言,我有自定义的
NSView
,其中包含我的标准按钮 subview
,并且此代码使上述所有内容变得神奇:
- (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];
}
我完全意识到这个问题是旧并且Valentin Shergin的答案是正确。它阻止使用任何“私人 API”,与“Google 在 Chrome 中所做的”不同。只是想为那些不喜欢子类 NSView
的人分享一种方法,只是将这些按钮放在现有视图中(例如 self.window.contentView
)。
因为我只是想通过
NSWindowButton
重新定位 setFrame:
,我发现一旦窗口
调整大小,跟踪区域似乎会自动“
修复”,无需使用任何私有 API (至少在 10.11 中)。 因此,您可以执行以下操作,将“fake resize”应用到您重新定位按钮的窗口:
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:
中完成的。只要窗口已加载且可见
,就应该可以工作。)
您不会再次添加它们。您正在将它们移动到 contentView。按钮最初位于 window.contentView.superview 中。
[window.contentView.superview addSubview:closeButton];
[window.contentView.superview addSubview:fullScreenButton];
[window.contentView.superview addSubview:minitButton];
过了这么久,Valentin Shergin 的回答
仍然有效!
// Need to first add your traffic light buttons to this stack view
class FauxTitleBarView: NSStackView {
var isMouseInside: Bool = false
@objc func _mouseInGroup(_ button: NSButton) -> Bool {
return isMouseInside
}
private func markButtonsDirty() {
for btn in views {
btn.needsDisplay = true
}
}
override func mouseEntered(with event: NSEvent) {
isMouseInside = true
markButtonsDirty()
}
override func mouseExited(with event: NSEvent) {
isMouseInside = false
markButtonsDirty()
}
}
class MyWindowController: NSWindowController, NSWindowDelegate {
var fauxTitleBar: FauxTitleBarView
// ...
func windowDidBecomeMain(_ notification: Notification) {
// The traffic light buttons should change to active color
for button in fauxTitleBar.views {
button.needsDisplay = true
}
}
func windowDidResignMain(_ notification: Notification) {
// The traffic light buttons should change to inactive color
for button in fauxTitleBar.views {
button.needsDisplay = true
}
}
}
为每个按钮调用
[button highlight:yes]
。