How NOT to change the background when NSButton clicked - macos

I have a NSButton on a view I subclass the NSView and draw something in the drawRect:, and the view is belong to a NSWindow which
Then when I click the button, I find the view become transparent, which I guess is because the button click changes the button's background. So I subclass the NSButton,
- (void)mouseDown:(NSEvent *)theEvent {
[self.window.contentView setNeedsDisplay:YES];
[super mouseDown:theEvent];
[self.window.contentView setNeedsDisplay:YES];
}
Right now when I mouseDown and mouseUp, the view seems right, except there is a flash transparent when I click, even more, when I mouseDown and move out of the button, the background becomes transparent again.
Can anyone tell me what should I do to make the background of a clicked button do not change?or where to put the redraw code.
THANKS!

Related

addSubview not displayed until windows focus has been lost and recovered

I have the following code attached to an NSButton
- (IBAction) onTest: (id) sender
{
NSLog(#"OnTest");
[overlayView setFrame: scrollView.frame];
[scrollView.superview addSubview: overlayView];
}
My nib is setup as the following picture:
The scrollView outlet is attached to the NSScrollView that encloses a NSTableView and the overlayView is attached to a NSView that has a green background.
On the click of a button, I receive the OnTest log message in xcode, but the green view is not visible, however if I switch focus from the applications window to say XCode, then back to the window, the green overlay is now visible.
I've tried using [scrollView.superView setNeedsDisplay: YES], but that still does not cause the green view to be displayed.
Any suggestions as to that I'm doing wrong?

cocoa: NSView touch event

I created a simple cocoa project, and added an NSButton in the window.
Then I added an NSScrollView to the window and hided the NSButton.
However, when I click the scroll view , it is strange that the NSButton action responds!
I guess there is something with the touch event chains, but I failed to find it.
For example, I try to use:
- [NSView becomeFirstResponder];
- [NSView setAcceptsTouchEvents:];
SO what I want is the only the front-most view to become the first responder, and the touch event will not be sent to its superview or so.
Thanks.
This is the view hierarchy:
the scroll view and button are both added to the window view, and the scrollview's frame includes the button's frame. In other words, the button is hidden by the scroll view but still receives click events.
You need to add mouseDown: event in NSScrollView or NSCrollView's View. like this:
-(void)mouseDown:(NSEvent *)theEvent {
NSLog(#"MouseDown in NSView");
}

Handling mouse over on NSCell (NSTextAttachmentCell)

Can't figure out how to handle mouse move over NSCell (or NSTextAttachmentCell). Is it possible ?
You can add a tracking area in the view that contains the cell and implement mouseEntered: and mouseExited: (and mouseMoved if you need that also) in that view. Here is an example where I added a tracking area one a button (button is the IBOutlet for the button). I added this code in the view's awakeFromNib method:
NSTrackingArea *buttonArea = [[NSTrackingArea alloc] initWithRect:self.button.frame options:NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInActiveApp owner:self userInfo:nil];
[self addTrackingArea:buttonArea];
This will cause the view to receive mouseEntered, mouseMoved, and mouseExited messages when the cursor enters the frame of the button.

When clicked NSImageView, Application can't move

I create NSToolbar and added NSView on the NSToolbar.
NSView Included NSImageView.
When clicked NSImageView or NSView in NSToolbar, I can't moved application.
How can I move application when I clicked NSView (or NSImageView) on the NSToolbar.
The question isn't very clear to me, but if you want to move the window with the mouse you could subclass the NSView (or NSImageView) and add
- (BOOL)mouseDownCanMoveWindow {
return YES;
}

How to make a transparent NSView subclass handle mouse events?

The problem
I have a transparent NSView on a transparent NSWindow. The view's drawRect: method draws some content (NSImages, NSBezierPaths and NSStrings) on the view but leaves parts of it transparent.
Clicking on the regions of the view that have been drawn on invokes the usual mouse event handling methods (mouseDown: and mouseUp:).
Clicking on the transparent areas gives focus to whatever window is behind my transparent window.
I would like to make parts of the transparent region clickable so that accidentally clicking between the elements drawn on my view does not cause the window to lose focus.
Solutions already attempted
Overriding the NSView's hitTest: method. Found that hitTest: was only called when clicking on a non-transparent area of the view.
Overriding the NSView's opaqueAncestor method. Found that this was not called when clicking on any part of the view.
Filling portions of the transparent area with [NSColor clearColor] in the drawRect: method, and with an almost-but-not-quite-transparent colour. This had no effect.
Experimented with the NSTrackingArea class. This appears to only add support for mouseEntered:, mouseExited:, mouseMoved:, and cursorUpdate: methods, not mouseUp: and mouseDown:.
I had the same problem. It looks like [window setIgnoresMouseEvents:NO] will do it.
(On Lion, at least. See http://www.cocoabuilder.com/archive/cocoa/306910-lion-breaks-the-ability-to-click-through-transparent-window-areas-when-the-window-is-resizable.html)
As far as I know, click events to transparent portions of windows aren't delivered to your application at all, so none of the normal event-chain overrides (i.e -hitTest:, -sendEvent:, etc) will work. The only way I can think of off the top of my head is to use Quartz Event Taps to capture all mouse clicks and then figure out if they're over a transparent area of your window manually. That, frankly, sounds like a huge PITA for not much gain.
George : you mentioned that you tried filling portions with an almost but not quite transparent color. In my testing, it only seems to work if the alpha value is above 0.05, so you might have some luck with something like this:
[[NSColor colorWithCalibratedRed:0.01 green:0.01 blue:0.01 alpha:0.05] set];
It's an ugly kludge, but it might work well enough to avoid using an event tap.
Did you try overriding
- (NSView *)hitTest:(NSPoint)aPoint
in your NSView sublcass?
You can use an event monitor to catch events outside a window/view.
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/MonitoringEvents/MonitoringEvents.html
You can override the hitTest method in your NSView so that it always returns itself.
According to the NSView documentation, the hitTest method will either return the NSView that the user has clicked on, or nil if the point is not inside the NSView. In this case, I would invoke [super hitTest:], and then return the current view only if the result would otherwise be nil (just in case your custom view contains subviews).
- (NSView *)hitTest:(NSPoint)aPoint
{
NSView * clickedView = [super hitTest:aPoint];
if (clickedView == nil)
{
clickedView = self;
}
return clickedView;
}
You can do:
NSView* windowContent = [window contentView];
[windowContent setWantsLayer:YES]
Making sure that the background is transparent:
[[windowContent layer] setBackgroundColor:[[NSColor clearColor] CGColor]];
Another option would be to add a transparent background image that fills the contentView.

Resources