NSButton Subclass, который реагирует на щелчок правой

StackOverflow https://stackoverflow.com/questions/5812367

  •  25-10-2019
  •  | 
  •  

Вопрос

У меня есть подкласс NSButton, который я хотел бы сделать с нажатием на кнопку правой мыши. Просто перегрузка -rightMouseDown: Не вырезал его, так как я хотел бы такого же поведения, как и для обычных щелчков (например, кнопка нажата, пользователь может отменить, оставив кнопку, действие отправляется при выпуске мыши и т. Д.).

То, что я пробовал до сих пор, это перегрузка -rightMouse{Down,Up,Dragged}, изменение событий, чтобы указать на нажатие кнопки левой мыши, а затем отправить их на -mouse{Down,Up,Dragged}. Анкет Теперь это было бы в лучшем случае взломом, и, как оказалось, Mac OS X не понравилось все это. Я могу нажать кнопку, но после выпуска кнопка остается нажатой.

Я мог бы имитировать поведение сам, что не должно быть слишком сложным. Тем не менее, я не знаю, как заставить кнопку выглядеть нажатой.


Прежде чем вы скажете: «Не так! Это нетрадиционное поведение Mac OS X, и его следует избегать»: я рассмотрел это, и щелчок правой кнопку может значительно улучшить рабочий процесс. По сути, кнопка цикла в 4 состояниях, и я хотел бы, чтобы правой щелкнули, чтобы сделать его цикла в обратном направлении. Это не важная особенность, но это было бы неплохо. Если вам все еще хочется сказать: «Не так!», Дайте мне знать ваши мысли. Я ценю это!

Спасибо!

РЕДАКТИРОВАТЬ: Это была моя попытка изменить событие (вы не можете изменить этот тип, поэтому я сделал новую, копировав всю информацию. Я имею в виду, я знаю, что это структура, явно говорит мне, что не делайте этого, но Я попробовал, как и вы):

// I've contracted all three for brevity
- (void)rightMouse{Down,Up,Dragging}:(NSEvent *)theEvent {
    NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouse{Down,Up,Dragging} location:[theEvent locationInWindow] modifierFlags:[theEvent modifierFlags] timestamp:[theEvent timestamp] windowNumber:[theEvent windowNumber] context:[theEvent context] eventNumber:[theEvent eventNumber] clickCount:[theEvent clickCount] pressure:[theEvent pressure]];
    [self mouse{Down,Up,Dragging}:event]; 
}

Обновление: я заметил, что -mouseUp: Никогда не отправляли в NSButton, и если я изменил его на NSControl, это было. Я не мог понять, почему это было, пока Фрэнсис МакГрю не указал, что он содержит свой собственный цикл обработки событий. Теперь это также имело смысл, почему, прежде чем я смог перенаправить -rightMouseDown:, но кнопка не будет выпущена. Это связано с тем, что он сам забрал новые события, которые я не мог перехватывать и преобразовать из -за правой к левой кнопке мыши.

Это было полезно?

Решение

NSButton входит в петлю отслеживания мыши. Чтобы изменить это, вам придется подключить NSButton и создать свой собственный цикл отслеживания. Попробуйте этот код:

- (void) rightMouseDown:(NSEvent *)theEvent 
{
    NSEvent *newEvent = theEvent;
    BOOL mouseInBounds = NO;

    while (YES) 
        {
            mouseInBounds = NSPointInRect([newEvent locationInWindow], [self convertRect:[self frame] fromView:nil]);
            [self highlight:mouseInBounds];

            newEvent = [[self window] nextEventMatchingMask:NSRightMouseDraggedMask | NSRightMouseUpMask];

            if (NSRightMouseUp == [newEvent type])
            {
                break;
            }
        }
    if (mouseInBounds) [self performClick:nil];
}

Вот как я это делаю; Надеюсь, это сработает для вас.

Другие советы

Я перевернул левую мышь, которая нажимает на щелчок в фальшивую правую мышь на контроле пути. Я не уверен, что это решит все ваши проблемы, но я обнаружил, что ключевым отличием, когда я это сделал, было изменение временной метки:

NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown 
                                    location:[theEvent locationInWindow] 
                               modifierFlags:[theEvent modifierFlags] 
                                   timestamp:CFAbsoluteGetTimeCurrent()
                                windowNumber:[theEvent windowNumber] 
                                     context:[theEvent context]
 // I was surprised to find eventNumber didn't seem to need to be faked 
                                 eventNumber:[theEvent eventNumber]   
                                  clickCount:[theEvent clickCount] 
                                    pressure:[theEvent pressure]];

Другое дело, что в зависимости от типа кнопки, его state Может быть, значение, которое делает его появлением или нет, так что вы могли бы попытаться ковыпать это.

Обновление: я думаю, что выяснил, почему rightMouseUp: никогда не вызывается. В соответствии с -[NSControl mouseDown:] Документы, кнопка начинает отслеживать мышь, когда получает mouseDown событие, а это не так остановка отслеживание, пока не получится mouseUp. Анкет Пока он отслеживает, он не может сделать ничего другого. Я только что попробовал, например, в конце обычая mouseDown::

[self performSelector:@selector(mouseUp:) withObject:myFakeMouseUpEvent afterDelay:1.0];

Но это откладывается до нормального mouseUp: Получил какой -то другой путь. Итак, если вы нажали правильную кнопку мыши, вы не можете (с мышью) отправить leftMouseUp, таким образом, кнопка все еще отслеживается и не примет rightMouseUp мероприятие. Я до сих пор не знаю, каково это решение, но я подумал, что это будет полезной информации.

Не так много, чтобы добавить к ответам выше, но для тех, кто работает в Swift, у вас могут возникнуть проблемы с поиском констант для маски событий, похороненных глубоко в документации, и еще больше проблем с поиском способа объединения (или) их в некотором роде что компилятор принимает, так что это может сэкономить вам некоторое время. Есть более аккуратный путь? Это идет в вашем подкласс -

var rightAction: Selector = nil 
  // add a new property, by analogy with action property

override func rightMouseDown(var theEvent: NSEvent!) {
  var newEvent: NSEvent!

  let maskUp = NSEventMask.RightMouseUpMask.rawValue
  let maskDragged = NSEventMask.RightMouseDraggedMask.rawValue
  let mask = Int( maskUp | maskDragged ) // cast from UInt

  do {
    newEvent = window!.nextEventMatchingMask(mask)
  }
  while newEvent.type == .RightMouseDragged

Моя петля стала доходом ... хотя, поскольку он всегда должен выполнять хотя бы один раз, и мне никогда не нравилось писать while true, и мне не нужно ничего делать с событиями перетаскивания.

У меня были бесконечные проблемы с получением значимых результатов из Convertrect (), возможно, потому, что мои элементы управления были встроены в представление таблицы. Благодаря Густаву Ларссону выше за то, что я закончил с этим для последней части -

let whereUp = newEvent.locationInWindow
let p = convertPoint(whereUp, fromView: nil)
let mouseInBounds = NSMouseInRect(p, bounds, flipped) // bounds, not frame
if mouseInBounds {
  sendAction(rightAction, to: target)
  // assuming rightAction and target have been allocated
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top