NSView上のドラッグによって、ウィンドウをドラッグさせる


概要

  • 指定したカスタムビュー上でドラッグした場合に、ウィンドウの位置を移動させる

GitHub

実装

カスタムビュー(DraggingView)

  • コード全体
#import "DraggingView.h"

@interface DraggingView()
@property NSPoint currentPoint;
@end

@implementation DraggingView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    // Drawing code here.
    // 分かりやすいようにビューに色を付ける
    NSRect bounds = [self bounds];
    [[[NSColor blueColor] colorWithAlphaComponent:0.1] set];
    [NSBezierPath fillRect:bounds];
}

#pragma mark Events
- (void)mouseDown:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}

- (void)mouseDragged:(NSEvent *)event {
    NSPoint previousPoint = _currentPoint;
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換

    // 移動したマウスの距離だけウィンドウの位置を移動させる
    double  distance_x   = _currentPoint.x - previousPoint.x;
    double  distance_y   = _currentPoint.y - previousPoint.y;
    NSRect  windowFrame  = self.window.frame;
    NSPoint windowOrigin = windowFrame.origin; // 現在のウィンドウ位置
    windowOrigin.x  += distance_x;
    windowOrigin.y  += distance_y;
    _currentPoint.x -= distance_x;             // ウィンドウの位置が変わったので、次のマウス移動の計算のために補正を行う
    _currentPoint.y -= distance_y;
    [self.window setFrameOrigin:windowOrigin]; // ウィンドウの位置を移動
    [self setNeedsDisplay:YES];
}

- (void)mouseUp:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}

@end
  • NSViewNSResponderを継承していて、これにはイベントを処理するメソッドが定義されています。
  • 今回はその中のmouseDownmouseDraggedmouseUpを使用します。
- (void)mouseDown:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}
  • マウスを押し込んだ際に呼ばれるメソッド
  • 引数のNSEventオブジェクトから作成できる座標情報はウィンドウのものなので、今回は必要ないが、利便性のためNSViewの座標系に変換することが多い。
  • _currentPointに押された位置を記録しておく
- (void)mouseDragged:(NSEvent *)event {
    NSPoint previousPoint = _currentPoint;
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換

    // 移動したマウスの距離だけウィンドウの位置を移動させる
    double  distance_x   = _currentPoint.x - previousPoint.x;
    double  distance_y   = _currentPoint.y - previousPoint.y;
  • ドラッグ前のマウス位置はpreviousPointへ保存
  • ドラッグ後のマウス位置を_currentPointへ保存
  • この2点からドラッグした距離を計算する
NSRect  windowFrame  = self.window.frame;
NSPoint windowOrigin = windowFrame.origin; // 現在のウィンドウ位置
windowOrigin.x  += distance_x;
windowOrigin.y  += distance_y;
_currentPoint.x -= distance_x;             // ウィンドウの位置が変わったので、次のマウス移動の計算のために補正を行う
_currentPoint.y -= distance_y;
[self.window setFrameOrigin:windowOrigin]; // ウィンドウの位置を移動
[self setNeedsDisplay:YES];
  • 移動した距離だけウィンドウの位置を変更する
  • このとき_currentPointを更新しておくことを忘れないように。
    • ウィンドウ位置が変更したため_currentPointを補完しないと、次回のドラッグ距離計算のときにずれが生じてしまう。
- (void)mouseUp:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}
  • ドラッグが終了したときに呼ばれるメソッド。
  • 今回は必要なし。

参考