2010-04-02 4 views
0

J'ai créé une boucle d'événement local et montré une fenêtre sans bordure (dérivée de NSPanel), J'ai trouvé dans la boucle d'événement aucun événement NSMouseMoved reçu, bien que je puisse recevoir des événements de bouton bas/haut de souris . Que dois-je faire pour obtenir les événements NSMouseMoved?Cocoa nextEventMatchingMask ne recevant pas l'événement NSMouseMoved

J'ai trouvé que faire la fenêtre flottante comme fenêtre clé peut recevoir les événements NSMouseMoved, mais je ne veux pas changer la fenêtre clé. Et il semble que cela soit possible, parce que j'ai trouvé après avoir cliqué sur l'icône de l'application de test dans la barre de Dock système, je peux recevoir les événements mousemoved, et la fenêtre clé/mainwindow sont inchangées.

Voici le code de mon test: (Créez un projet Cocoa App FloatWindowTest, et mettez un bouton à lier avec onClick: IBAction). Merci d'avance!

-Jonny

#import "FloatWindowTestAppDelegate.h" 

@interface FloatWindow : NSPanel 
@end 

@interface FloatWindowContentView : NSView 
@end 

@implementation FloatWindowTestAppDelegate 

@synthesize window; 

- (void)delayedAction:(id)sender 
{ 
    // What does this function do? 
    // 1. create a float window 
    // 2. create a local event loop 
    // 3. print out the events got from nextEventMatchingMask. 
    // 4. send it to float window. 

    // What is the problem? 
    // In local event loop, althrough the event mask has set NSMouseMovedMask 
    // there's no mouse moved messages received. 
    // 

    FloatWindow* floatWindow = [[FloatWindow alloc] init]; 

    NSEvent* event = [NSApp currentEvent]; 
    NSPoint screenOrigin = [[self window] convertBaseToScreen:[event locationInWindow]];  
    [floatWindow setFrameTopLeftPoint:screenOrigin]; 
    [floatWindow orderFront:nil]; 


    //Making the float window as Key window will work, however 
    //change active window is not anticipated. 
    //[floatWindow makeKeyAndOrderFront:nil]; 

    BOOL done = NO; 
    while (!done) 
    { 
     NSAutoreleasePool* pool = [NSAutoreleasePool new]; 
     NSUInteger eventMask = NSLeftMouseDownMask| 
     NSLeftMouseUpMask| 
     NSMouseMovedMask| 
     NSMouseEnteredMask| 
     NSMouseExitedMask| 
     NSLeftMouseDraggedMask; 

     NSEvent* event = [NSApp nextEventMatchingMask:eventMask 
              untilDate:[NSDate distantFuture] 
               inMode:NSDefaultRunLoopMode 
               dequeue:YES]; 

     //why I cannot get NSMouseMoved event?? 
     NSLog(@"new event %@", [event description]); 
     [floatWindow sendEvent:event]; 
     [pool drain]; 
    } 

    [floatWindow release]; 
    return; 
} 

-(IBAction)onClick:(id)sender 
{ 
    //Tried to postpone the local event loop 
    //after return from button's mouse tracking loop. 
    //but not fixes this problem. 
    [[NSRunLoop currentRunLoop] 
      performSelector:@selector(delayedAction:) 
        target:self 
        argument:nil 
        order:0 
        modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]]; 
} 
@end 



@implementation FloatWindow 

- (id)init 
{ 
    NSRect contentRect = NSMakeRect(200,300,200,300); 
    self = [super initWithContentRect:contentRect 
          styleMask:NSTitledWindowMask 
           backing:NSBackingStoreBuffered 
           defer:YES]; 

    if (self) { 
     [self setLevel:NSFloatingWindowLevel]; 

     NSRect frameRect = [self frameRectForContentRect:contentRect]; 
     NSView* view = [[[FloatWindowContentView alloc] 
         initWithFrame:frameRect] autorelease]; 
     [self setContentView:view]; 

     [self setAcceptsMouseMovedEvents:YES]; 
     [self setIgnoresMouseEvents:NO]; 
    }  
    return self;       
} 

- (BOOL)becomesKeyOnlyIfNeeded 
{ 
    return YES; 
} 

- (void)becomeMainWindow 
{ 
    NSLog(@"becomeMainWindow"); 
    [super becomeMainWindow]; 
} 

- (void)becomeKeyWindow 
{ 
    NSLog(@"becomeKeyWindow"); 
    [super becomeKeyWindow]; 
} 

@end 

@implementation FloatWindowContentView 

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

- (BOOL)acceptsFirstResponder 
{ 
    return YES; 
} 

- (id)initWithFrame:(NSRect)frameRect 
{ 
    self = [super initWithFrame:frameRect]; 
    if (self) { 
     NSTrackingArea* area; 
     area = [[NSTrackingArea alloc] initWithRect:frameRect 
              options:NSTrackingActiveAlways| 
                NSTrackingMouseMoved| 
                NSTrackingMouseEnteredAndExited 
               owner:self 
              userInfo:nil]; 
     [self addTrackingArea:area]; 
     [area release]; 
    } 
    return self; 
} 

- (void)drawRect:(NSRect)rect 
{ 
    [[NSColor redColor] set]; 
    NSRectFill([self bounds]); 
} 

- (BOOL)becomeFirstResponder 
{ 
    NSLog(@"becomeFirstResponder"); 
    return [super becomeFirstResponder]; 
} 

@end 

Répondre

1

Je pense que je trouve la bonne réponse. Ceci est en quelque sorte lié à dire à NSWindow d'accepter l'événement MouseMoved. mais à ma grande surprise, la fenêtre devrait accepter les événements mouseMoved n'est pas la fenêtre flottante, mais la fenêtre actuelle. La solution est donc simple, il suffit d'activer la fenêtre de la clé pour accepter les événements déplacés par la souris avant de lancer le suivi, et de rétablir le commutateur après la fin du suivi.

Questions connexes