In my app I change the position of the standardWindowButtons close / miniturize / expand like so:
//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];
Now when the window appears with the buttons there is two problems: 1. They are grey and not their correct color 2. when the mouse is over them they do not show the + - or x sign
can anyone tell me what I am doing wrong. Thanks.
Here is the mechanics of this hover magic: Before drawing itself standard circled button (such as NSWindowMiniaturizeButton
) calls their superview
undocumented method _mouseInGroup:
. If this method returns YES
circled button draws itself with icon inside. That's all.
If you place these buttons inside your own view, you can simply implement this method and control this mouse-hover-appearance as you want. If you just move or relayout these buttons and they still be subview
s of NSThemeFrame
(or something similar), you have to swizzle method _mouseInGroup:
for this class, and probably it doesn't worth it because we have perfectly simple previous method.
In my case I have custom NSView
that contains my standard buttons as subview
s and this code makes all described above 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];
}
I'm fully aware that this question is old and Valentin Shergin's answer is correct. It prevents the utilize of any Private API, unlike Google did in Chrome. Just wanted to share a method for those who don't feel like subclass NSView
just to put those buttons in an existed view (such as self.window.contentView
).
As I just wanted to reposition the NSWindowButton
s via setFrame:
, I found out that once the window was resized, the tracking areas seems to "fix" themselves automagically, without any Private API usage (at least in 10.11).
Thus, you can do things like the following to apply "fake resize" to the window that you repositioned your buttons:
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];
(I did it within my main window's NSWindowDelegate
windowDidBecomeMain:
. Should work as long as the window is loaded and visible.)
You're not adding them again. You're moving them to contentView. The buttons are originally in window.contentView.superview.
[window.contentView.superview addSubview:closeButton];
[window.contentView.superview addSubview:fullScreenButton];
[window.contentView.superview addSubview:minitButton];
Should get you the correct behaviour without requiring a trackingArea.
Call [button highlight:yes]
for each button.
来源:https://stackoverflow.com/questions/7634788/cocoa-osx-nswindow-standardwindowbutton-behaving-strangely-once-copied-and-add