2009-10-08 16 views
0

我有多個疊加的控件可以在特定條件下處理鼠標點擊。我希望能夠做的是:發送一個事件給另一個NSControl下面的NSControl,如果它沒有處理它

  1. 頂部控制接收 mouseDown:事件。
  2. 最高控制權決定是否處理mouseDown:事件。
  3. 如果有,請採取措施並阻止其他控件接收mouseDown:事件。
  4. 如果沒有,請將事件發送到下面的控件。
  5. 此控件決定它是否處理事件。

從本質上說,我試圖將事件發送到其「Z順序」只是頂部控制面板下方的控制,沒有頂部的控制需要了解的其他控件或者在實例化時需要一些特殊的設置。

我想到的第一件事是將事件發送到[topControl nextResponder],但窗口上的所有控件似乎都是窗口本身,而不是像我以前認爲的那樣基於它們的Z-順序的控件鏈的nextResponder

有沒有辦法做到這一點,而不訴諸手動設置下一個響應者?我們的目標是獲得一個獨立於其他控件的控件,並且可以放在窗口上並按預期工作。

在此先感謝!

回答

1

很難確切知道最好的方法,因爲我不知道你的應用程序做了什麼,但這是一個想法。聽起來你想通過視圖層次傳遞消息......不知何故。

無論如何,一個視圖會做兩件事情之一:

  • 處理消息
  • 把它傳遞給「下一個視圖」(你如何定義「下一個視圖」取決於你的應用程序)

所以。你會如何做到這一點?視圖的默認行爲應該是將消息傳遞給下一個視圖。實施這種事情的一個好方法是通過一個非正式協議。

@interface NSView (MessagePassing) 

- (void)handleMouseDown:(NSEvent *)event; 
- (NSView *)nextViewForEvent:(NSEvent *)event; 

@end 

@implementation NSView (MessagePassing) 

- (void)handleMouseDown:(NSEvent *)event { 
    [[self nextView] handleMouseDown:event]; 
} 

- (NSView *)nextViewForEvent:(NSEvent *)event { 
    // Implementation dependent, but here's a simple one: 
    return [self superview]; 
} 

@end 

現在,應該有這種行爲的看法,你可以這樣做:

- (void)mouseDown:(NSEvent *)event { 
    [self handleMouseDown:event]; 
} 

- (void)handleMouseDown:(NSEvent *)event { 
    if (/* Do I not want to handle this event? */) { 
     // Let superclass decide what to do. 
     // If no superclass handles the event, it will be punted to the next view 
     [super handleMouseDown:event]; 
     return; 
    } 

    // Handle the event 
} 

你可能會想創建一個子類NSView覆蓋mouseDown:,你會那麼您基地等自定義視圖類。

如果您想根據實際z順序確定「下一個視圖」,請記住,z順序由subviews集合內的順序決定,後面的視圖首先出現。所以,你可以做這樣的事情:

- (void)nextViewForEvent:(NSEvent *)event { 
    NSPoint pointInSuperview = [[self superview] convertPoint:[event locationInWindow] fromView:nil]; 
    NSInteger locationInSubviews = [[[self superview] subviews] indexOfObject:self]; 
    for (NSInteger index = locationInSubviews - 1; index >= 0; index--) { 
     NSView *subview = [[[self superview] subviews] objectAtIndex:index]; 
     if (NSPointInRect(pointInSuperview, [subview frame])) 
      return subview; 
    } 
    return [self superview]; 
} 

這可能比你想要的方式更多,但我希望它能幫助。

+0

這是一個非常有趣的答案,我很可能會使用你的答案的第二部分,它似乎是一個很好的方式來獲得基於他們的Z順序的意見。謝謝! – Form

2

您只需致電[super mouseDown:event]即可。由於Mac OS X 10.5(此前而不是的工作方式相同)NSView知道如何處理重疊的視圖,並會爲您處理事件處理。


如果需要10.5之前版本的目標:這是一個非常糟糕的主意。事件處理機制不僅不知道如何處理重疊子視圖,繪圖系統也不會看到一些非常奇怪的文物。也就是說,如果你確定:

在你的自定義控件/視圖中覆蓋-[NSView hitTest:]。 AppKit使用此方法來確定層次結構中將鼠標事件傳遞給哪個視圖。如果您返回nil,那麼您的自定義視圖中的點將被忽略,並且該事件應傳遞到覆蓋該點的下一個視圖。

雖然如此,由於上述原因,這仍然是一個壞主意。它當時並不是AppKit正式支持的東西。 10.4和更早版本中更普遍接受的解決方法是使用子窗口。

+0

很高興知道,謝謝!但是,我必須至少支持10.4,所以我必須以另一種方式來做到這一點。目前我正在手動設置下一個響應者並且它可以工作,但這不是最佳的。當然,在10.4和更高版本上有更清晰的方法來執行此操作... – Form

+0

請您詳細說明子窗口嗎? – Form

+0

創建一個無邊界窗口,它是您的自定義控件的大小,並將其作爲子窗口附加到主窗口。因此,您可以獲得重疊視圖的效果,而無需真正這樣做。做這件事有點痛苦,但正如我所說的那樣,重疊視圖在10.4上不被支持 - 並且試圖強迫他們工作是危險的。 –

相關問題