2011-03-09 68 views
3

如何通過拖動標題欄來更改NSWindow的位置? 我知道我可以使用windowWillMove:windowDidMove:通知,但這些通知只會在拖動開始或結束時纔會發出通知。NSWindow移動中的通知

+0

你有進一步的瞭解嗎?我還想知道窗口框架在拖動... – Georg 2014-04-10 11:41:21

+0

@Georg,請參閱下面的答案。 :) – VinceFior 2015-07-12 05:33:15

回答

0

我絕對沒有可可專家,但AFAIK windowDidMove即使在你拖動並稍微休息時也會發出通知(鼠標左鍵仍然按下,鼠標不會移動半秒左右)。

怎麼樣看兩件事:你知道窗口拖動開始,你知道它什麼時候結束。觀察鼠標移動之間的時間,然後獲得移動的窗口位置。

2

我有一個解決方案,可以讓您確定拖動窗口的位置。

這兩個問題是,拖動窗口時沒有內置的方式獲得通知,並且窗口的框架在其停止移動之前不會更新。我的方法是通過設置重複計時器並跟蹤光標位移來解決這些問題。

首先,訂閱NSWindowWillMoveNotificationNSWindowDidMoveNotification以確定窗口何時開始和停止移動。

[[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); 
} 

myMethodactualFrameOrigin點會報告,其中框架實際上是,即使self.view.window.frame.origin點只有當你停止拖動窗口的更新。

這種方法可以讓你在窗口被拖動時得到通知,並告訴你它的實際位置,所以你都準備好了!


我發現的唯一的問題是,快速按下標題欄不移動光標將火NSWindowWillMoveNotification但不NSWindowDidMoveNotification,這將導致計時器錯誤地不斷重複。爲了處理這種情況,我們可以通過檢查(pressedButtons & (1 << 0)) == (1 << 0)來檢查在myMethod中是否按住鼠標左鍵。如果按鈕沒有按下,我們只需取消定時器。