У меня есть решение, которое позволяет вам определять положение окна во время его перетаскивания.
Две проблемы заключаются в том, что нет встроенного способа получать уведомления во время перетаскивания окна и что рамка окна не обновляется, пока не перестанет двигаться.Мой подход обходит эти проблемы, устанавливая повторяющийся таймер и отслеживая смещение курсора.
Сначала подпишитесь на NSWindowWillMoveNotification
и NSWindowDidMoveNotification
, чтобы определить, когда окно запускается и останавливается.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowWillMove:)
name:@"NSWindowWillMoveNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowDidMove:)
name:@"NSWindowDidMoveNotification"
object:nil];
Когда окно собирается сдвинуться, запишите положение курсора и запустите повторяющийся таймер, который вызывает ваш собственный метод "перетаскивается окно".
- (void)windowWillMove:(NSNotification *)notification {
if (notification.object == self.view.window) { // make sure we have the right window
self.dragCursorStartPos = [NSEvent mouseLocation];
const NSTimeInterval dragDelaySeconds = 0.1; // polling rate delay
self.dragWindowTimer = [NSTimer scheduledTimerWithTimeInterval:dragDelaySeconds
target:self
selector:@selector(myMethod)
userInfo:nil
repeats:YES];
}
}
Когда окно закончит движение, остановите повторяющийся таймер.
- (void)windowDidMove:(NSNotification *)notification {
if (notification.object == self.view.window) { // make sure we have the right window
if (self.dragWindowTimer != NULL) {
[self.dragWindowTimer invalidate];
self.dragWindowTimer = NULL;
}
}
}
Теперь умная / хакерская часть заключается в том, что мы определяем фактическую позицию кадра, вычисляя смещение курсора изего начальная позиция и добавление этого смещения к указанному источнику фрейма, который не изменился с тех пор, как окно начало двигаться.
- (void)myMethod {
NSPoint cursorPos = [NSEvent mouseLocation];
NSPoint cursorDisplacement = NSMakePoint(cursorPos.x - self.dragCursorStartPos.x, cursorPos.y - self.dragCursorStartPos.y);
CGPoint frameOrigin = self.view.window.frame.origin;
CGPoint actualFrameOrigin = CGPointMake(frameOrigin.x + cursorDisplacement.x, frameOrigin.y + cursorDisplacement.y);
NSLog(@"The frame's actual origin is (%f, %f)", actualFrameOrigin.x, actualFrameOrigin.y);
}
Точка actualFrameOrigin
в myMethod
сообщит, где в действительности находится фрейм,хотя точка self.view.window.frame.origin
обновляется только при прекращении перетаскивания окна.
Этот подход позволяет вам получать уведомления во время перетаскивания окна и сообщать вам его фактическую позицию, так что вы все настроены!
Единственная проблема, которую я обнаружил, заключается в том, чтобыстрое нажатие на строку заголовка без перемещения курсора вызовет NSWindowWillMoveNotification
, но не NSWindowDidMoveNotification
, что приведет к неправильному повторению таймера.Чтобы справиться с этим случаем, мы можем проверить, удерживается ли левая кнопка мыши в myMethod
, проверяя, если (pressedButtons & (1 << 0)) == (1 << 0)
.Если кнопка не удерживается, мы просто отменяем таймер.