Click through NSView

后端 未结 5 868
后悔当初
后悔当初 2021-01-02 04:30

I have an NSView containing multiple subviews. One of those subviews is transparent and layered on top.

I need to be able to click through this view dow

相关标签:
5条回答
  • 2021-01-02 05:00

    I circumvented the issue with this code snippet.

    - (NSView *)findNextSiblingBelowEventLocation:(NSEvent *)theEvent {
      // Translate the event location to view coordinates
      NSPoint location = [theEvent locationInWindow];
      NSPoint convertedLocation = [self convertPointFromBase:location];
    
      // Find next view below self
      NSArray *siblings = [[self superview] subviews];
      NSView *viewBelow = nil;
      for (NSView *view in siblings) {
        if (view != self) {
          NSView *hitView = [view hitTest:convertedLocation];
          if (hitView != nil) {
            viewBelow = hitView;
          }
        }
      }
      return viewBelow;
    }
    
    - (void)mouseDown:(NSEvent *)theEvent {
      NSView *viewBelow = [self findNextSiblingBelowEventLocation:theEvent];
      if (viewBelow) {
        [[self window] makeFirstResponder:viewBelow];
      }
      [super mouseDown:theEvent];
    }
    
    0 讨论(0)
  • 2021-01-02 05:01

    Put your transparent view in a child window of its own.

    0 讨论(0)
  • 2021-01-02 05:03

    Here's a Swift 5 version of figelwump's answer:

    public override func hitTest(_ point: NSPoint) -> NSView? {
        // pass-through events that don't hit one of the visible subviews
        return subviews.first { subview in
            !subview.isHidden && nil != subview.hitTest(point)
        }
    }
    
    0 讨论(0)
  • 2021-01-02 05:03

    Here's a Swift 5 version of Erik Aigner's answer:

    public override func mouseDown(with event: NSEvent) {
        // Translate the event location to view coordinates
        let convertedLocation = self.convertFromBacking(event.locationInWindow)
    
        if let viewBelow = self
            .superview?
            .subviews // Find next view below self
            .lazy
            .compactMap({ $0.hitTest(convertedLocation) })
            .first
        {
            self.window?.makeFirstResponder(viewBelow)
        }
    
        super.mouseDown(with: event)
    }
    
    0 讨论(0)
  • 2021-01-02 05:05

    Here's another approach. It doesn't require creating a new window object and is simpler (and probably a bit more efficient) than the findNextSiblingBelowEventLocation: method above.

    - (NSView *)hitTest:(NSPoint)aPoint
    {
        // pass-through events that don't hit one of the visible subviews
        for (NSView *subView in [self subviews]) {
            if (![subView isHidden] && [subView hitTest:aPoint])
                return subView;
        }
    
        return nil;
    }
    
    0 讨论(0)
提交回复
热议问题