2012-06-04 2 views
0


У меня есть Прозрачный NSWindow с простым значком в нем, который можно перетаскивать по экрану.
Мой код:
.h:Как отличить событие mouseDown от mouseDragged в Transparent NSWindow

@interface CustomView : NSWindow{ 
} 

@property (assign) NSPoint initialLocation; 

.m

@synthesize initialLocation; 

- (id) initWithContentRect: (NSRect) contentRect 
       styleMask: (NSUInteger) aStyle 
        backing: (NSBackingStoreType) bufferingType 
        defer: (BOOL) flag{ 
    if (![super initWithContentRect: contentRect 
          styleMask: NSBorderlessWindowMask 
          backing: bufferingType 
           defer: flag]) return nil; 
    [self setBackgroundColor: [NSColor clearColor]]; 
    [self setOpaque:NO]; 
    [NSApp activateIgnoringOtherApps:YES]; 
    return self; 
} 

- (void)mouseDragged:(NSEvent *)theEvent { 
    NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame]; 
    NSRect windowFrame = [self frame]; 
    NSPoint newOrigin = windowFrame.origin; 

    // Get the mouse location in window coordinates. 
    NSPoint currentLocation = [theEvent locationInWindow]; 
    // Update the origin with the difference between the new mouse location and the old mouse location. 
    newOrigin.x += (currentLocation.x - initialLocation.x); 
    newOrigin.y += (currentLocation.y - initialLocation.y); 

    // Don't let window get dragged up under the menu bar 
    if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height)) { 
     newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height); 
    } 

    // Move the window to the new location 
    [self setFrameOrigin:newOrigin]; 
} 

- (void)mouseDown:(NSEvent *)theEvent {  
    // Get the mouse location in window coordinates. 
    self.initialLocation = [theEvent locationInWindow]; 
} 

Я хочу, чтобы отобразить NSPopover когда пользователи нажимает на изображение прозрачного окна. Но, как вы видите в коде, событие mouseDown используется для получения местоположения мыши (приведенный выше код был взят из примера).
Что я могу узнать, когда пользователь нажимает значок, чтобы перетащить его или просто щелкнул по нему, чтобы отобразить NSPopover?
Спасибо

ответ

2

Это классическая ситуация получения определяющего события после того, как оно вам понадобится, чтобы начать действие. В частности, вы не можете знать, является ли mouseDown началом перетаскивания до тех пор, пока не начнется перетаскивание. Тем не менее, вы хотите воздействовать на этот mouseDown, если перетаскивание не запускается.

В iOS (я понимаю, что здесь нет прямого отношения к коду, но он является учебным), существует целый API, основанный на том, чтобы позволить iOS делать такие решения для вас. Вся система Gesture основана на идее, что пользователь начинает делать что-то, что может быть одним из многих различных действий, и, следовательно, необходимо разрешить с течением времени, что может привести к отмене действий в течение периода отслеживания.

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

В mouseDown запустите NSTimer набор для соответствующего времени охраны (не так много, чтобы люди случайно переместили указатель и не настолько коротки, чтобы вы триггер до того, как пользователь перетащит), чтобы перезвонить вам позже, чтобы вызвать popover.

В зоне mouseDragged используйте защитную зону, чтобы убедиться, что если пользователь немного подергивается, это не считается перетаскиванием. Это может быть раздражающим, так как иногда возникает необходимость перетаскивать что-то дальше, чем кажется необходимым, чтобы начать перетаскивание, поэтому вы захотите либо найти волшебную константу где-нибудь, либо сделать некоторые эксперименты. Когда защитная зона превышена, начните свою законную операцию перетаскивания, отменив NSTimer с помощью [timer invalidate] и сделайте перетаскивание.

В обратном вызове для таймера отобразите свой popover. Если пользователь перетащил, NSTimer будет признан недействительным, что приведет к его не срабатыванию, и поэтому popover не будет отображаться.

+0

Очень жаль, что это так больно реализовать. Но спасибо за эту идею. – rocky

Смежные вопросы