我有一个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)
}
}
正如您所看到的,它检查事件和视图的窗口是否相同,如果不是,逻辑尝试比较屏幕并尝试手动转换