Кнопки перехода и не поднимая окно

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

Как это сделать?

Я просмотрел документацию Apple, и мне нужно немного продолжить в Руководство по обработке событий какао, отправка событий, в котором говорится:

Некоторые события, многие из которых определяются Application Kit (тип NSAppKitDefined), связаны с действиями, управляемыми окном или самим объектом приложения. Примерами этих событий являются события, связанные с активацией, деактивацией, скрытием и отображением приложения. NSApp отфильтровывает эти события на ранних этапах своей процедуры отправки и обрабатывает их самостоятельно.

Итак, из моего ограниченного понимания (Как событие входит в какао, приложение) подкласс NSApplication и переопределение - (void)sendEvent:(NSEvent *)theEvent должны перехватывать каждое событие мыши и клавиатуры, но все же окно открывается при нажатии. Таким образом, либо окно открывается до того, как событие будет обнаружено NSApplication, либо мне не хватает чего-то еще.

К сожалению, я просмотрел рассказ Мэтта Галлахера, который проясняет NSApplication путем его воссоздания Мэтт не покрыл очередь событий, так что в остальном я в тупике.

Любая помощь будет оценена, спасибо.

Отредактировано для добавления: Нашел сообщение в Lloyd's Lounge, в котором он говорит об той же проблеме и ссылается на сообщение по адресу CocoaBuilder, сделайте первый снимок правой кнопкой мыши. В настоящее время я пробую код, предоставленный там, после некоторой возни и повторной активации NSLog для [theEvent type] обнаруживается активность левой кнопки мыши.

Теперь, щелкнув левой кнопкой мыши по окну, чтобы открыть его, вы получите последовательность типов событий 13, 1, 13, это снова NSAppKitDefined, NSLeftMouseDown и NSAppKitDefined. Могу ли я отфильтровать их или узнать, куда они идут?


person Community    schedule 30.09.2009    source источник


Ответы (4)


Этого можно добиться с помощью NSPanel, который настроен так, чтобы не скрывать при деактивации и становиться ключевым только при необходимости. Это также предполагает, что элементы управления, которые вы будете использовать, возвращают YES в -acceptsFirstMouse:; NSButtons делают это по умолчанию.

Вы можете отключить скрытие при деактивации флага через IB для панели, но вам нужно будет отправить сообщение -setBecomesKeyOnlyIfNeeded:YES на панель, чтобы она и приложение не двигались вперед при нажатии кнопки.

person Ashley Clark    schedule 30.09.2009
comment
Я хочу верить, что это ответ, но чтение ссылки на класс NSView (где определен метод acceptsFirstMouse:) говорит, что он установлен на NO. И, наконец, создание подклассов NSView в любом случае не имеет значения. - person ; 01.10.2009
comment
Только что нашел краткое обсуждение CocoaDev, cocoadev.com/index.pl?PreventWindowOrdering, это делает то, что я хочу, хотя это кажется плохим способом сделать это. - person ; 01.10.2009
comment
В документации для acceptsFirstMouse: конкретно вызывается NSButton как возвращающий YES: Однако многие объекты управления, такие как экземпляры NSButton и NSSlider, принимают их, поэтому пользователь может немедленно манипулировать элементом управления, не отпуская кнопку мыши. - person Ashley Clark; 02.10.2009
comment
Если вы не можете использовать NSPanel для окна, в котором вы хотите такое поведение, мне кажется, что метод, описанный в CocoaDev, подходит. - person Ashley Clark; 02.10.2009

Это не совсем тот ответ, который я искал, но пока он работает достаточно хорошо. Создав подкласс NSView и реализовав следующие методы, это представление может затем действовать как кнопка.

- (void)mouseDown:(NSEvent *)theEvent {
    [NSApp preventWindowOrdering];
//  [self setNeedsDisplay:YES];
}

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
    return YES;
}

- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent {
    return YES;
}

Больше ничего не требуется, вот и все. Конечно, это обходит все достоинства NSButton, которые я хотел сохранить, я должен спроектировать, а затем позаботиться о рисовании и обновлении состояний кнопок, но я просто рад получить ответ.

person Community    schedule 23.10.2009

Можно заставить NSButton реагировать на события перехода без изменения его поведения, когда приложение активно:

Интерфейс (ClickThroughButton.h):

#import <AppKit/AppKit.h>

@interface ClickThroughButton : NSButton

@end

Реализация (ClickThroughButton.m):

#import "ClickThroughButton.h"

@implementation ClickThroughButton

- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent {
    return ![NSApp isActive];    
}

- (void)mouseDown:(NSEvent *)theEvent {    
    if (![NSApp isActive]) {
        [NSApp preventWindowOrdering];        

        [self highlight:YES];

        NSEvent *mouseUpEvent = [[self window] nextEventMatchingMask:NSLeftMouseUpMask
                                                  untilDate:[NSDate distantFuture]
                                                     inMode:NSEventTrackingRunLoopMode
                                                    dequeue:YES];
        NSPoint mouseLocation = [self convertPoint:[mouseUpEvent locationInWindow] fromView:nil];
        BOOL mouseUpInside = [self mouse:mouseLocation inRect:[self bounds]];

        if (mouseUpInside) {
            if ([self target])
                [[self target] performSelector:[self action] withObject:self]; 
        }

        [self highlight:NO];            

    } else {
        [super mouseDown:theEvent];        
    }
}

@end
person mrwalker    schedule 16.11.2011
comment
Работает, но как держать диалог наверху? Я разрабатываю такое приложение, как Keyboard Viewer. - person mh taqia; 17.05.2012

Вы проверили acceptsFirstMouse:? Любой NSView может вернуть YES этому событию, чтобы сказать, что представление должно обрабатывать событие, а не выводить окно на передний план. Предположительно, перехватывая событие, он не будет использоваться для вывода окна на передний план, но я не могу за это поручиться.

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

person Alex    schedule 30.09.2009
comment
acceptFirstMouse: и acceptFirstResponder: не имеют никакого эффекта, это была (и я должен был отметить) моя первая попытка решить эту проблему. Спасибо хоть. - person ; 30.09.2009