2010-01-03 3 views
5

Mac 용 Objective-C에서 Windows 용으로 작성한 응용 프로그램을 다시 작성하려고합니다. Mac 용으로 멋지게 할 수 있기를 바랍니다. 모서리. 화면의 왼쪽으로 마우스를 움직이면 윈도우가 보입니다. 창 위치 밖으로 이동하면 윈도우가 다시 숨겨집니다. (창은 화면의 왼쪽으로 밀어 넣습니다).화면 가장자리에 윈도우가 튀어 나오고 튀어 오름

누구든지이 작업을 수행하는 방법에 대한 데모 코드 (또는 참조)를 찾을 수 있는지, 아니면 현재 응용 프로그램이 맨 위에 있지 않더라도 마우스가있는 위치를 알려주는 방법을 알 수 있습니까? (이 말을 쓰는 방법을 모르거나 Windows 환경에 익숙하지 않은 경우).

-Brad

+0

이것은 Quicksilver의 Shelf 및 Clipboard History, (선택 사항) Adium의 연락처 목록과 같은 창처럼 들리며, 마우스가 가장자리에 닿으면 화면 밖으로 튀어 나오게됩니다. 그게 네 생각이야? –

+0

네, 그게 내가 생각하는 것입니다. – Brad

답변

1

가 여기에 내가 무엇을 최대 온입니다. 위의 조언을 해주신 Peter에게 감사드립니다.

@interface SlidingWindow : NSWindow 
    { 
     CGRectEdge _slidingEdge; 
     NSView *_wrapperView; 
    } 


    @property (nonatomic, assign) CGRectEdge slidingEdge; 
    @property (nonatomic, retain) NSView *wrapperView; 

    -(id)initWithContentRect:(NSRect) contentRect 
        styleMask:(unsigned int) styleMask 
        backing:(NSBackingStoreType) backingType 
         defer:(BOOL) flag; 

    - (NSView*)wrapperViewWithFrame:(NSRect)bounds; 

    - (BOOL)mayOrderOut; 

    @end 

    @interface SlidingWindow() 

    - (void)adjustWrapperView; 

    - (void)setWindowWidth:(NSNumber*)width; 
    - (void)setWindowHeight:(NSNumber*)height; 

    @end 


    @implementation SlidingWindow 


@synthesize slidingEdge = _slidingEdge; 
@synthesize wrapperView = _wrapperView; 


- (id)initWithContentRect:(NSRect) contentRect 
       styleMask:(unsigned int) styleMask 
        backing:(NSBackingStoreType) backingType 
        defer:(BOOL) flag 
{ 

    if ((self = [super initWithContentRect:contentRect 
           styleMask:NSBorderlessWindowMask 
            backing:backingType 
            defer:flag])) { 
     /* May want to setup some other options, 
     like transparent background or something */ 

     [self setSlidingEdge:CGRectMaxYEdge]; 
     [self setHidesOnDeactivate:YES]; 
     [self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; 
    } 

    return self; 
} 

- (NSView*)wrapperViewWithFrame:(NSRect)bounds 
{ 
    return [[[NSView alloc] initWithFrame:bounds] autorelease]; 
} 

- (void)adjustWrapperView 
{ 
    if (self.wrapperView == nil) { 
     NSRect frame = [self frame]; 
     NSRect bounds = NSMakeRect(0, 0, frame.size.width, frame.size.height); 
     NSView *wrapperView = [self wrapperViewWithFrame:bounds]; 
     NSArray *subviews = [[[[self contentView] subviews] copy] autorelease]; 

     for (NSView *view in subviews) { 
      [wrapperView addSubview:view]; 
     } 

     [wrapperView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; 
     [[self contentView] addSubview:wrapperView]; 

     self.wrapperView = wrapperView; 
    } 

    switch (self.slidingEdge) { 
     case CGRectMaxXEdge: 
      [self.wrapperView setAutoresizingMask:(NSViewHeightSizable | NSViewMaxXMargin)]; 
      break; 

     case CGRectMaxYEdge: 
      [self.wrapperView setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)]; 
      break; 

     case CGRectMinXEdge: 
      [self.wrapperView setAutoresizingMask:(NSViewHeightSizable | NSViewMinXMargin)]; 
      break; 

     case CGRectMinYEdge: 
     default: 
      [self.wrapperView setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; 
    } 
} 

- (void)makeKeyAndOrderFront:(id)sender 
{ 
    [self adjustWrapperView]; 

    if ([self isVisible]) { 
     [super makeKeyAndOrderFront:sender]; 
    } 
    else { 
     NSRect screenRect = [[NSScreen menubarScreen] visibleFrame]; 
     NSRect windowRect = [self frame]; 

     CGFloat x; 
     CGFloat y; 
     NSRect startWindowRect; 
     NSRect endWindowRect; 

     switch (self.slidingEdge) { 
      case CGRectMinXEdge: 
       x = 0; 
       y = (screenRect.size.height - windowRect.size.height)/2 + screenRect.origin.y; 
       startWindowRect = NSMakeRect(x - windowRect.size.width, y, 0, windowRect.size.height); 
       break; 

      case CGRectMinYEdge: 
       x = (screenRect.size.width - windowRect.size.width)/2 + screenRect.origin.x; 
       y = 0; 
       startWindowRect = NSMakeRect(x, y - windowRect.size.height, windowRect.size.width, 0); 
       break; 

      case CGRectMaxXEdge: 
       x = screenRect.size.width - windowRect.size.width + screenRect.origin.x; 
       y = (screenRect.size.height - windowRect.size.height)/2 + screenRect.origin.y; 
       startWindowRect = NSMakeRect(x + windowRect.size.width, y, 0, windowRect.size.height); 
       break; 

      case CGRectMaxYEdge: 
      default: 
       x = (screenRect.size.width - windowRect.size.width)/2 + screenRect.origin.x; 
       y = screenRect.size.height - windowRect.size.height + screenRect.origin.y; 
       startWindowRect = NSMakeRect(x, y + windowRect.size.height, windowRect.size.width, 0); 
     } 

     endWindowRect = NSMakeRect(x, y, windowRect.size.width, windowRect.size.height); 

     [self setFrame:startWindowRect display:NO animate:NO]; 

     [super makeKeyAndOrderFront:sender]; 

     [self setFrame:endWindowRect display:YES animate:YES]; 

     [self performSelector:@selector(makeResizable) 
        withObject:nil 
        afterDelay:1]; 
    } 
} 

- (void)makeResizable 
{ 
    NSView *wrapperView = self.wrapperView; 
    NSRect frame = [self frame]; 
    NSRect bounds = NSMakeRect(0, 0, frame.size.width, frame.size.height); 

    [wrapperView setFrame:bounds]; 
    [wrapperView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; 
} 

- (void)orderOut:(id)sender 
{ 
    [self adjustWrapperView]; 

    NSRect startWindowRect = [self frame]; 
    NSRect endWindowRect; 

    switch (self.slidingEdge) { 
     case CGRectMinXEdge: 
      endWindowRect = NSMakeRect(startWindowRect.origin.x, 
             startWindowRect.origin.y, 
             0, 
             startWindowRect.size.height); 
      break; 

     case CGRectMinYEdge: 
      endWindowRect = NSMakeRect(startWindowRect.origin.x, 
             startWindowRect.origin.y, 
             startWindowRect.size.width, 
             0); 
      break; 

     case CGRectMaxXEdge: 
      endWindowRect = NSMakeRect(startWindowRect.origin.x + startWindowRect.size.width, 
             startWindowRect.origin.y, 
             0, 
             startWindowRect.size.height); 
      break; 

     case CGRectMaxYEdge: 
     default: 
      endWindowRect = NSMakeRect(startWindowRect.origin.x, 
             startWindowRect.origin.y + startWindowRect.size.height, 
             startWindowRect.size.width, 
             0); 
    } 

    [self setFrame:endWindowRect display:YES animate:YES]; 

    switch (self.slidingEdge) { 
     case CGRectMaxXEdge: 
     case CGRectMinXEdge: 
      if (startWindowRect.size.width > 0) { 
       [self performSelector:@selector(setWindowWidth:) 
          withObject:[NSNumber numberWithDouble:startWindowRect.size.width] 
          afterDelay:0]; 
      } 
      break; 

     case CGRectMaxYEdge: 
     case CGRectMinYEdge: 
     default: 
      if (startWindowRect.size.height > 0) { 
       [self performSelector:@selector(setWindowHeight:) 
          withObject:[NSNumber numberWithDouble:startWindowRect.size.height] 
          afterDelay:0]; 
      } 
    } 

    [super orderOut:sender]; 
} 

- (void)setWindowWidth:(NSNumber*)width 
{ 
    NSRect startWindowRect = [self frame]; 
    NSRect endWindowRect = NSMakeRect(startWindowRect.origin.x, 
             startWindowRect.origin.y, 
             [width doubleValue], 
             startWindowRect.size.height); 

    [self setFrame:endWindowRect display:NO animate:NO];  
} 

- (void)setWindowHeight:(NSNumber*)height 
{ 
    NSRect startWindowRect = [self frame]; 
    NSRect endWindowRect = NSMakeRect(startWindowRect.origin.x, 
             startWindowRect.origin.y, 
             startWindowRect.size.width, 
             [height doubleValue]); 

    [self setFrame:endWindowRect display:NO animate:NO];  
} 

- (void)resignKeyWindow 
{ 
    [self orderOut:self]; 

    [super resignKeyWindow]; 
} 

- (BOOL)canBecomeKeyWindow 
{ 
    return YES; 
} 

- (void)performClose:(id)sender 
{ 
    [self close]; 
} 

- (void)dealloc 
{ 
    [_wrapperView release], _wrapperView = nil; 

    [super dealloc]; 
} 

@end 


@implementation NSScreen (MenubarScreen) 

+ (NSScreen*)menubarScreen 
{ 
    NSArray *screens = [self screens]; 

    if ([screens count] > 0) { 
     return [screens objectAtIndex:0]; 
    } 

    return nil; 
} 
@end 
+0

Sweet, 데모 코드 덕분에 – Brad

+0

모든 장소에서 min & max를 섞어 봤습니다 만, -adjustWrapperView –

+0

@PierreBernard는 응답에서 최소값과 최대 값을 수정 했습니까? 아니면 여전히 역방향입니까? 또한'@interface '이'@ 구현'을 위해, 그리고 그 안에 있어야 할 필요가있는 것이 명확하지는 않습니다 ... 예를 들어, 'slidingEdge'가 정의되어 있지 않은 것 같습니다. –

2

당신은 그래서 상단에 항상 설정 창 순서로 화면의 가장자리에 보이지 않는 창을 구현하려는거야 감사합니다. 그런 다음이 창에서 마우스로 이동 한 이벤트를들을 수 있습니다.

[self setAcceptsMouseMovedEvents:YES]; 

창을 발생합니다

다음

[self setBackgroundColor:[NSColor clearColor]]; 
[self setExcludedFromWindowsMenu:YES]; 
[self setCanHide:NO]; 
[self setLevel:NSScreenSaverWindowLevel]; 
[self setAlphaValue:0.0f]; 
[self setOpaque:NO]; 
[self orderFrontRegardless]; 

, 마우스에 설정하는 이벤트를 이동 :

이 보이지 상단에있을 창을 설정하려면, 같은 창 서브 클래스의 사용이 호출을 전화를 받으려면

- (void)mouseMoved:(NSEvent *)theEvent 
{ 
    NSLog(@"mouse moved into invisible window."); 
} 

이렇게 시작하면 충분합니다.

-Ken

+0

퍼즐의 다른 부분은 창을 실제로 들락날락하게 만들고 있습니다. 윈도우의 콘텐트 뷰의 즉각적인 서브 뷰를 다른 뷰에 넣고 콘텐트 뷰를 만들어야한다. 내용보기 내보기의 자동 크기 조정 마스크를 조정하지 않고 원본보기를 내용보기의 왼쪽 가장자리 (예를 들어)로 스테이플 링하도록 설정하십시오. 창을 숨기려면 창 크기를 1 픽셀 너비로 조정하십시오. 그것을 표시하려면 적절한 크기로 복원하십시오. 창 크기를 조정할 수있게하려면 창 표시/숨기기 후에보기의 자동 크기 조절 마스크를 전환해야합니다. –

+0

단순히 창을 안팎으로 이동하지 않는 이유는 사용자가 창 밖으로 이동할 다른 화면을 사용자가 가질 수 있기 때문입니다. 그런 다음 창을 숨기고 있지 않고 사용자가 원하는 것이 아닌 다른 화면으로 이동합니다. (이 상황에서 사용자가 창을 표시하는 방법에 대해 사용자는 작은 화면의 가장자리를 지나서 창을 위아래로 움직여 충돌 할 수 있습니다.) –

+0

내가 오버레이 창을 잊어 버린 점이 몇 가지 있습니다 : [self setHasShadow : NO]; 및 [self setIgnoresMouseEvents : NO]; 보이지 않는 창은 실제로 클릭을 차단하지 않습니다. 99 %는 여전히 마우스가 움직이는 이벤트를 얻을 것이라고 확신합니다. –

2

당신은 우리가 바이저 프로젝트에서 그것을 어떻게 보일 수 있습니다 : http://github.com/binaryage/visor/blob/master/src/Visor.m#L1025-1063

+0

이것은 완벽하게 작동합니다! 고맙습니다 다윈 .. – Brad

+0

이 프로젝트에 무슨 일이 일어 났습니까? – Wesley

+0

의 이름이 다음으로 변경되었습니다. http://totalterminal.binaryage.com/ –

2

여기 AutoHidingWindow - 마우스가 화면 가장자리에 부딪 힐 때 튀어 나오는 SlidingWindow의 하위 클래스입니다. 피드백 환영.

@interface ActivationWindow : NSWindow 
{ 
    AutoHidingWindow *_activationDelegate; 
    NSTrackingArea *_trackingArea; 
} 

- (ActivationWindow*)initWithDelegate:(AutoHidingWindow*)activationDelegate; 

@property (assign) AutoHidingWindow *activationDelegate; 
@property (retain) NSTrackingArea *trackingArea; 

- (void)adjustWindowFrame; 
- (void)adjustTrackingArea; 

@end 

@interface AutoHidingWindow() 

- (void)autoShow; 
- (void)autoHide; 

@end 


@implementation AutoHidingWindow 

- (id)initWithContentRect:(NSRect) contentRect 
       styleMask:(unsigned int) styleMask 
        backing:(NSBackingStoreType) backingType 
        defer:(BOOL) flag 
{ 

    if ((self = [super initWithContentRect:contentRect 
           styleMask:NSBorderlessWindowMask 
            backing:backingType 
            defer:flag])) { 
     _activationWindow = [[ActivationWindow alloc] initWithDelegate:self]; 
    } 

    return self; 
} 

@synthesize activationWindow = _activationWindow; 

- (void)dealloc 
{ 
    [_activationWindow release], _activationWindow = nil; 

    [super dealloc]; 
} 

- (void)makeKeyAndOrderFront:(id)sender 
{ 
    [super makeKeyAndOrderFront:sender]; 

} 

- (void)autoShow 
{ 
    [self makeKeyAndOrderFront:self]; 

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(autoHide) object:nil]; 
    [self performSelector:@selector(autoHide) withObject:nil afterDelay:2]; 
} 

- (void)autoHide 
{ 
    NSPoint mouseLocation = [NSEvent mouseLocation]; 
    NSRect windowFrame = [self frame]; 

    if (NSPointInRect(mouseLocation, windowFrame)) { 
     [self performSelector:@selector(autoHide) withObject:nil afterDelay:2]; 
    } 
    else { 
     [self orderOut:self]; 
    } 
} 

@end 


@implementation ActivationWindow 

- (ActivationWindow*)initWithDelegate:(AutoHidingWindow*)activationDelegate 
{ 
    if ((self = [super initWithContentRect:[[NSScreen mainScreen] frame] 
           styleMask:NSBorderlessWindowMask 
            backing:NSBackingStoreBuffered 
            defer:NO]) != nil) { 
     _activationDelegate = activationDelegate; 

     [self setBackgroundColor:[NSColor clearColor]]; 
     [self setExcludedFromWindowsMenu:YES]; 
     [self setCanHide:NO]; 
     [self setHasShadow:NO]; 
     [self setLevel:NSScreenSaverWindowLevel]; 
     [self setAlphaValue:0.0]; 
     [self setIgnoresMouseEvents:YES]; 
     [self setOpaque:NO]; 
     [self orderFrontRegardless]; 

     [self adjustWindowFrame]; 
     [self.activationDelegate addObserver:self 
           forKeyPath:@"slidingEdge" 
            options:0 
            context:@"slidingEdge"]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(screenParametersChanged:) 
                name:NSApplicationDidChangeScreenParametersNotification 
                object:nil];  
    } 

    return self; 
} 

@synthesize activationDelegate = _activationDelegate; 
@synthesize trackingArea = _trackingArea; 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([@"slidingEdge" isEqual:context]) { 
     [self adjustTrackingArea]; 
    } 
    else { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 


- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 

    [self.activationDelegate removeObserver:self forKeyPath:@"slidingEdge"]; 
    _activationDelegate = nil; 

    [_trackingArea release], _trackingArea = nil; 

    [super dealloc]; 
} 

- (void)screenParametersChanged:(NSNotification *)notification 
{ 
    [self adjustWindowFrame]; 
} 

- (void)adjustWindowFrame 
{ 
    NSScreen *mainScreen = [NSScreen mainScreen]; 
    CGFloat menuBarHeight = [NSMenuView menuBarHeight]; 
    NSRect windowFrame = [mainScreen frame]; 

    windowFrame.size.height -= menuBarHeight; 

    [self setFrame:windowFrame display:NO]; 
    [self adjustTrackingArea]; 
} 

- (void)adjustTrackingArea 
{ 
    NSView *contentView = [self contentView]; 
    NSRect trackingRect = contentView.bounds; 
    CGRectEdge slidingEdge = self.activationDelegate.slidingEdge; 
    CGFloat trackingRectSize = 2.0; 

    switch (slidingEdge) { 
     case CGRectMaxXEdge: 
      trackingRect.origin.x = trackingRect.origin.x + trackingRect.size.width - trackingRectSize; 
      trackingRect.size.width = trackingRectSize; 
      break; 

     case CGRectMaxYEdge: 
      trackingRect.origin.y = trackingRect.origin.y + trackingRect.size.height - trackingRectSize; 
      trackingRect.size.height = trackingRectSize; 
      break; 

     case CGRectMinXEdge: 
      trackingRect.origin.x = 0; 
      trackingRect.size.width = trackingRectSize; 
      break; 

     case CGRectMinYEdge: 
     default: 
      trackingRect.origin.y = 0; 
      trackingRect.size.height = trackingRectSize; 
    } 


    NSTrackingAreaOptions options = 
    NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | 
    NSTrackingActiveAlways | 
    NSTrackingEnabledDuringMouseDrag; 

    NSTrackingArea *trackingArea = self.trackingArea; 

    if (trackingArea != nil) { 
     [contentView removeTrackingArea:trackingArea]; 
    } 

    trackingArea = [[NSTrackingArea alloc] initWithRect:trackingRect 
               options:options 
                owner:self 
               userInfo:nil]; 

    [contentView addTrackingArea:trackingArea]; 

    self.trackingArea = [trackingArea autorelease]; 
} 

- (void)mouseEntered:(NSEvent *)theEvent 
{ 
    [self.activationDelegate autoShow]; 
} 


- (void)mouseMoved:(NSEvent *)theEvent 
{ 
    [self.activationDelegate autoShow]; 
} 

- (void)mouseExited:(NSEvent *)theEvent 
{ 
} 

@end 
관련 문제