Получение [NSEvent mouseLocation] в системе координат представления
У меня есть NSView, который ловит событие mouseDown.
Я получаю координацию щелчка мышью, используя:
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint touchPoint = [NSEvent mouseLocation];
//Rest of code
}
Тем не менее, это устанавливает clickPoint в качестве расположения мыши в глобальной координации экрана.
Я хочу получить позицию щелчка в относительной координации вида. Если пользователь щелкает в левом нижнем углу окна, я хочу, чтобы точка была (0, 0), независимо от того, где находится окно на экране.
3 ответа
Вы должны использовать 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)
}
Просто используйте
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.x, dy: eventWindow.frame.y)
let viewFrameInScreen = view.frameInWindow.translate(dx: viewWindow.frame.x, dy: viewWindow.frame.y)
return eventLocationInScreen.translate(dx: -viewFrameInScreen.x, dy: -viewFrameInScreen.y)
} else {
// different screen, try to convert to unified coordinate
let eventLocationInScreen = locationInWindow.translate(dx: eventWindow.frame.x, dy: eventWindow.frame.y)
let eventLocationInBase = eventLocationInScreen.translate(dx: eventScreen.frame.x, dy: eventScreen.frame.y)
let viewFrameInScreen = view.frameInWindow.translate(dx: viewWindow.frame.x, dy: viewWindow.frame.y)
let viewFrameInBase = viewFrameInScreen.translate(dx: viewScreen.frame.x, dy: viewScreen.frame.y)
return eventLocationInBase.translate(dx: -viewFrameInBase.x, dy: -viewFrameInBase.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)
}
}
Как видите, он проверяет, совпадает ли и событие, и окно просмотра, если нет, логика пытается сравнить экран и попытаться выполнить преобразование вручную.