Разрешить щелчок и перетащить представление, чтобы перетащить само окно?

Я использую текстурированное окно, в котором есть панель вкладок вверху, чуть ниже строки заголовка.

Я использовал -setContentBorderThickness:forEdge: в окне, чтобы градиент выглядел правильно, и чтобы листы выходили из правильной позиции.

Однако, что не работает, перетаскивание окна. Он работает, если я нажимаю и перетаскиваю область, которая на самом деле является строкой заголовка, но поскольку градиент полосы заголовка разливается в панель вкладок (потенциально/часто пустой), очень легко щелкнуть слишком низко, и это кажется очень расстраивающим, когда вы пытаетесь перетащить и убедитесь, что окно не двигается.

Я замечаю NSToolbar, занимая примерно такое же пространство ниже строки заголовка, что позволяет перетаскивать окно, когда курсор над ним. Как это реализовать?

Спасибо.

Tab Bar

Ответы

Ответ 1

Я нашел здесь здесь:

-(void)mouseDown:(NSEvent *)theEvent {    
    NSRect  windowFrame = [[self window] frame];

    initialLocation = [NSEvent mouseLocation];

    initialLocation.x -= windowFrame.origin.x;
    initialLocation.y -= windowFrame.origin.y;
}

- (void)mouseDragged:(NSEvent *)theEvent {
    NSPoint currentLocation;
    NSPoint newOrigin;

    NSRect  screenFrame = [[NSScreen mainScreen] frame];
    NSRect  windowFrame = [self frame];

    currentLocation = [NSEvent mouseLocation];
    newOrigin.x = currentLocation.x - initialLocation.x;
    newOrigin.y = currentLocation.y - initialLocation.y;

    // Don't let window get dragged up under the menu bar
    if( (newOrigin.y+windowFrame.size.height) > (screenFrame.origin.y+screenFrame.size.height) ){
        newOrigin.y=screenFrame.origin.y + (screenFrame.size.height-windowFrame.size.height);
    }

    //go ahead and move the window to the new location
    [[self window] setFrameOrigin:newOrigin];
}

Это прекрасно работает, хотя я не уверен на 100%, что я делаю это правильно. Там есть одна ошибка, которую я нашел до сих пор, и что если перетаскивание начинается внутри подвью (сама вкладка), а затем вводится супервизор (панель вкладок). Окно прыгает. Некоторые -hitTest: магия или, возможно, даже просто недействительность initialLocation на mouseUp, вероятно, исправить это.

Ответ 2

Я попробовал решение mouseDownCanMoveWindow (fooobar.com/questions/341618/...), но это не сработало для меня. Я избавился от этого метода и вместо этого добавил его в мой подкласс окна:

- (BOOL)isMovableByWindowBackground {
    return YES;
}

который работал как шарм.

Ответ 3

Вы пытались переопределить метод NSView mouseDownCanMoveWindow, чтобы вернуть YES?

Ответ 4

Он работает для меня после двух шагов:

  • Подкласс NSView, переопределите mouseDownCanMoveWindow, чтобы вернуть YES.
  • Подкласс NSWindow, переопределите isMovableByWindowBackground, чтобы вернуть YES.

Ответ 5

Как и в macOS 10.11, самый простой способ сделать это - использовать новый метод -[NSWindow performWindowDragWithEvent:]:

@interface MyView () {
    BOOL movingWindow;
}
@end

@implementation MyView

...

- (BOOL)mouseDownCanMoveWindow
{
    return NO;
}

- (void)mouseDown:(NSEvent *)event
{
    movingWindow = NO;

    CGPoint point = [self convertPoint:event.locationInWindow
                              fromView:nil];

    // The area in your view where you want the window to move:
    CGRect movableRect = CGRectMake(0, 0, 100, 100);

    if (self.window.movableByWindowBackground &&
        CGRectContainsPoint(movableRect, point)) {

        [self.window performWindowDragWithEvent:event];
        movingWindow = YES;
        return;
    }

    // Handle the -mouseDown: as usual
}

- (void)mouseDragged:(NSEvent *)event
{
    if (movingWindow) return;

    // Handle the -mouseDragged: as usual
}

@end

Здесь -performWindowDragWithEvent: будет обрабатывать правильное поведение, не перекрывая строку меню, а также будет привязываться к краям на macOS 10.12 и новее. Обязательно включите переменную экземпляра BOOL movingWindow с вашим личным интерфейсом просмотра, чтобы избежать событий -mouseDragged: после того, как вы определили, что не хотите их обрабатывать.

Здесь мы также проверяем, что для параметра -[NSWindow movableByWindowBackground] установлено значение YES, чтобы это представление можно было использовать в окнах без перемещения по окну, но это необязательно.

Ответ 6

Это довольно просто:

переопределить свойство mouseDownCanMoveWindow

override var mouseDownCanMoveWindow:Bool {
    return false
}