Domanda

Ho una sottoclasse NSButton che mi piacerebbe fare il lavoro con clic del pulsante destro del mouse. Basta sovraccarico -rightMouseDown: non è tagliato, come vorrei lo stesso tipo di comportamento per i clic regolari (ad esempio, il pulsante viene spinto verso il basso, l'utente può annullare lasciando il pulsante, viene inviato l'azione quando il mouse viene rilasciato, ecc .).

Quello che ho provato finora sta sovraccaricando -rightMouse{Down,Up,Dragged}, modificando gli eventi per indicare i clic tasto sinistro del mouse e poi inviarlo a -mouse{Down,Up,Dragged}. Ora, questo sarebbe chiaramente un hack al meglio, e come si scopre di Mac OS X non mi è piaciuto tutto. Posso fare clic sul pulsante, ma al momento del rilascio, i resti del pulsante premuto.

ho potuto imitare il comportamento stesso, che non dovrebbe essere troppo complicato. Tuttavia, non so come fare l'aspetto tasto premuto.


Prima di dire "! Do Non è un comportamento non convenzionale di Mac OS X e deve essere evitato": ho considerato questo e un click destro potuto migliorare notevolmente il flusso di lavoro. Fondamentalmente il pulsante passa tra 4 stati, e mi piacerebbe un click destro per renderlo ciclo in senso inverso. Non è una caratteristica essenziale, ma sarebbe bello. Se ancora voglia di dire "No!", Poi fatemi sapere i vostri pensieri. Lo apprezzo!

Grazie!

EDIT: Questo è stato il mio tentativo di cambiare l'evento (non è possibile modificare il tipo, così ho fatto uno nuovo, la copia di tutte le informazioni attraverso Voglio dire, so che questo è il quadro dice chiaramente a me non lo faccio. Questo, ma mi ha dato un andare, come si fa):

// 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]; 
}

UPDATE: Ho notato che -mouseUp: non è mai stato inviato a NSButton, e se ho cambiato in un NSControl, è stato. Non riuscivo a capire il motivo per cui questo è stato, fino a quando Francesco McGrew ha sottolineato che contiene il proprio ciclo di gestione degli eventi. Ora, anche questo aveva un senso per il motivo per cui prima di riuscire a reindirizzare il -rightMouseDown:, ma il pulsante non sarebbe salito sul rilascio. Questo è perché è stato il recupero di nuovi eventi sul proprio, che non ho potuto intercettare e convertire da destra a eventi tasto sinistro del mouse.

È stato utile?

Soluzione

NSButton sta entrando in un ciclo di monitoraggio del mouse. Per cambiare questo dovrete sottoclasse NSButton e creare il proprio ciclo di monitoraggio personalizzato. Prova questo codice:

- (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];
}

Questo è come lo faccio; Speriamo che lavorerà per voi.

Altri suggerimenti

Ho girato un sinistro del mouse-and-hold in un topo finto destra verso il basso su un controllo percorso. Non sono sicuro che questo risolverà tutti i vostri problemi, ma ho trovato che la differenza fondamentale quando ho fatto questo stava cambiando il timestamp:

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]];

L'altra cosa è che a seconda del tipo di pulsante, la sua state può essere il valore che viene spinto facendolo apparire o no, così si potrebbe provare frugando in quel.

UPDATE: Penso di aver capito perché rightMouseUp: non viene mai chiamato. Per il -[NSControl mouseDown:] documenti, il pulsante avvia il tracciamento della mouse quando si ottiene un evento mouseDown, e non lo fa di arresto di monitoraggio fino a quando non ottiene mouseUp. Mentre è il monitoraggio, non può fare altro. Ho appena provato, ad esempio, alla fine di un mouseDown: personalizzato:

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

, ma questo viene messo fuori fino a un mouseUp: normale viene attivato un altro modo. Quindi, se hai fatto clic sul pulsante destro del mouse, non è possibile (con il mouse) inviare un leftMouseUp, quindi il tasto è ancora tracking, e non accetterà un evento rightMouseUp. Io ancora non so quale sia la soluzione, ma ho pensato che sarebbe informazioni utili.

Non c'è molto da aggiungere alle risposte di cui sopra, ma per coloro che lavorano a Swift, si possono avere problemi a trovare le costanti per la maschera degli eventi, sepolto in profondità nella documentazione, e ancor più difficoltà a trovare un modo per combinare (OR) li in un modo che il compilatore accetta, quindi questo è possibile risparmiare un po 'di tempo. C'è un modo più ordinato? Questo va nella sottoclasse -

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

Il mio ciclo è diventato un do..while, come ha sempre fatto da eseguire almeno una volta, e non ho mai voluto scrivere while true, e non ho bisogno di fare qualcosa con gli eventi di trascinamento.

Ho avuto problemi senza fine di ottenere risultati significativi da convertRect (), forse perché i miei controlli sono stati inseriti in una vista tabella. Grazie a Gustav Larsson sopra per il mio finire con questo per l'ultima parte -

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
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top