Domanda

Il mini-player iTunes (per fare un solo esempio) supporta click-through in cui l'applicazione non viene portata in primo piano quando si utilizzano i comandi play / pausa e volume.

Come è questo fatto?

Ho cercato attraverso la documentazione di Apple e ho un po 'di andare avanti, in cacao di gestione degli eventi Guida, evento spedizione afferma:

  

Alcuni eventi, molti dei quali sono definiti dal Kit applicazione (tipo NSAppKitDefined), hanno a che fare con le azioni controllate da una finestra o l'oggetto applicazione stessa. Esempi di questi eventi sono quelli relativi alla attivazione, disattivazione, nascondendo e mostrando l'applicazione. NSApp filtra questi eventi all'inizio della sua routine di spedizione e gestisce essa stessa.

Quindi, dal mio comprensione limitata ( Come un evento Inserisce un cacao, Application ) sottoclassi NSApplication e prioritario - (void)sendEvent:(NSEvent *)theEvent dovrebbe trappola ogni mouse e tastiera evento, ma ancora, la finestra è sollevata al clic. Quindi, o la finestra viene sollevato prima che l'evento è visto da NSApplication o mi manca qualcosa d'altro.

Ho guardato di Matt Gallagher Demystifying NSApplication ricreando esso , purtroppo Matt non ha coperto la coda di eventi, in modo diverso da quello, io sono perplesso.

Qualsiasi aiuto sarebbe apprezzato, grazie.

A cura di aggiungere: Trovato un posto presso Lounge di Lloyd in cui parla lo stesso problema e link ad un post all'indirizzo CocoaBuilder, cattura primo destro del mouse . Attualmente sto provando il codice fornito lì, dopo un po 'armeggiare intorno e riattivando la NSLog per [theevent tipo], l'attività pulsante sinistro del mouse viene catturato.

Ora, a sinistra cliccando sulla finestra per portarla avanti produce una sequenza di tipi di eventi, 13, 1, 13, questi sono NSAppKitDefined, NSLeftMouseDown e NSAppKitDefined di nuovo. Posso filtrare questi fuori o trovare dove stanno andando?

È stato utile?

Soluzione 2

Questa non è esattamente la risposta che cercavo, ma per ora funziona sufficientemente bene. Sottoclasse NSView ed attuare i seguenti metodi, che guarda può quindi agire come un pulsante.

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

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

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

è richiesto Nient'altro, il gioco è fatto. Naturalmente questo bypassa tutta la bontà NSButton che ho voluto mantenere, devo progettare e quindi si prenderà cura del disegno e aggiornare gli stati del pulsante, ma io sono solo contento di avere una risposta.

Altri suggerimenti

Questo può essere realizzato con una NSPanel che è stato impostato per non nascondere il disattivare e di diventare unica chiave in base alle esigenze. Ciò presuppone anche che i controlli che userete YES ritorno alla -acceptsFirstMouse:; NSButtons fanno per impostazione predefinita.

È possibile disattivare la pelle sulla bandiera Disattiva attraverso IB per il pannello, ma avrete bisogno di emettere il messaggio -setBecomesKeyOnlyIfNeeded:YES al pannello per mantenerlo e l'applicazione di venire in avanti su clic del pulsante.

E 'possibile fare un NSButton risponde ai click-through di eventi senza cambiare il suo comportamento quando l'applicazione è attiva:

Interfaccia (ClickThroughButton.h):

#import <AppKit/AppKit.h>

@interface ClickThroughButton : NSButton

@end

attuazione (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

Avete verificato acceptsFirstMouse:? Qualsiasi NSView può tornare YES a questo evento per dire che la vista deve gestire l'evento piuttosto che portare la finestra in primo piano. Presumibilmente, intercettando l'evento, non sarà utilizzato per portare la finestra in primo piano, ma non posso garantire per questo.

Avrete ovviamente bisogno di sottoclasse qualsiasi controllo che si desidera avere questo comportamento per ignorare acceptsFirstMouse:.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top