在视图协调系统中获取[NSEvent mouseLocation]



我有一个NSView正在捕捉一个mouseDown事件。

我得到鼠标点击的协调使用:

- (void)mouseDown:(NSEvent *)theEvent {
    NSPoint touchPoint = [NSEvent mouseLocation];
    //Rest of code
}

但是,这会将clickPoint设置为鼠标在全局屏幕协调中的位置。

我想获得点击在相对视图协调中的位置——如果用户在窗口的左下角点击,我想让点为(0,0),无论包含窗口在屏幕上的哪个位置

您应该使用locationInWindow,而不是mouseLocation。关于locationInWindow的文档显示了如何从那里开始:

NSPoint event_location = [theEvent locationInWindow];
NSPoint local_point = [self convertPoint:event_location fromView:nil];

Swift

override func mouseMoved(with event: NSEvent) {
    let mouseLocation = event.locationInWindow
    print(mouseLocation)
}

简单地使用[self convertPoint:event_location fromView:nil];可能是不准确的,这可能发生在事件的窗口和视图的窗口不相同的时候。下面是在不同窗口/屏幕中获取事件位置的更健壮的方法:

public extension NSEvent {
  /// Get the event mouse location in `view`.
  func location(in view: NSView) -> CGPoint {
    if let eventWindow = window, let viewWindow = view.window {
      if eventWindow.windowNumber == viewWindow.windowNumber {
        // same window, just convert
        return view.convert(locationInWindow, from: nil)
      } else {
        // window not equal, check screen
        if let eventScreen = eventWindow.screen, let viewScreen = viewWindow.screen {
          if eventScreen.isEqual(to: viewScreen) {
            // same screen, try to convert between windows
            // screen coordinate zero point is at bottom left corner
            let eventLocationInScreen = locationInWindow.translate(dx: eventWindow.frame.origin.x, dy: eventWindow.frame.origin.y)
            let viewFrameInScreen = view.frameInWindow.translate(dx: viewWindow.frame.origin.x, dy: viewWindow.frame.origin.y)
            return eventLocationInScreen.translate(dx: -viewFrameInScreen.origin.x, dy: -viewFrameInScreen.origin.y)
          } else {
            // different screen, try to convert to unified coordinate
            let eventLocationInScreen = locationInWindow.translate(dx: eventWindow.frame.origin.x, dy: eventWindow.frame.origin.y)
            let eventLocationInBase = eventLocationInScreen.translate(dx: eventScreen.frame.origin.x, dy: eventScreen.frame.origin.y)
            let viewFrameInScreen = view.frameInWindow.translate(dx: viewWindow.frame.origin.x, dy: viewWindow.frame.origin.y)
            let viewFrameInBase = viewFrameInScreen.translate(dx: viewScreen.frame.origin.x, dy: viewScreen.frame.origin.y)
            return eventLocationInBase.translate(dx: -viewFrameInBase.origin.x, dy: -viewFrameInBase.origin.y)
          }
        }
      }
    }
    // other unexpected cases, fall back to use `convert(_:from:)`
    return view.convert(locationInWindow, from: nil)
  }
}
public extension NSView {
  /// The view's frame in its window.
  var frameInWindow: CGRect {
    convert(bounds, to: nil)
  }
}
public extension CGRect {
  /// Move/translate a `CGRect` by its origin..
  /// - Parameters:
  ///   - dx: The delta x.
  ///   - dy: The delta y.
  /// - Returns: A new `CGRect` with moved origin.
  func translate(dx: CGFloat = 0, dy: CGFloat = 0) -> CGRect {
    CGRect(origin: origin.translate(dx: dx, dy: dy), size: size)
  }
}
public extension CGPoint {
  /// Translate the point.
  /// - Parameters:
  ///   - dx: The delta x.
  ///   - dy: The delta y.
  /// - Returns: The translated point.
  @inlinable
  @inline(__always)
  func translate(dx: CGFloat = 0, dy: CGFloat = 0) -> CGPoint {
    CGPoint(x: x + dx, y: y + dy)
  }
}

正如您所看到的,它检查事件和视图的窗口是否相同,如果不是,逻辑尝试比较屏幕并尝试手动转换

相关内容

  • 没有找到相关文章

最新更新