2009-09-30 7 views
5

iTunesミニプレイヤー(一例に過ぎない)は、再生/一時停止と音量コントロールが使用されているときにアプリケーションを前面に持ってこないクリックスルーをサポートしています。クリックスルーボタンとウィンドウを上げない

これはどのように行われますか?私はAppleのドキュメントを見、それを述べCocoa Event-Handling Guide, Event Dispatchで、上に行くには少し持ってきた

:アプリケーションキット(タイプNSAppKitDefined)によって定義され、その多く

いくつかのイベントを、する必要がありますウィンドウやアプリケーションオブジェクト自体によって制御されるアクションを実行します。これらのイベントの例は、アプリケーションのアクティブ化、非アクティブ化、隠蔽、および表示に関連するイベントです。 NSAppはディスパッチルーチンの早い段階でこれらのイベントをフィルタリングし、それを処理します。

だから、まだ私の限られた理解(How an Event Enters a Cocoa, Application)サブクラスNSApplicationのとオーバーライド - (void)sendEvent:(NSEvent *)theEventべきトラップすべてのマウスとキーボードイベントが、から、窓をクリックの上に上げています。したがって、NSApplicationによってイベントが表示される前にウィンドウが生成されるか、他に何かがありません。

私はマットギャラガーのDemystifying NSApplication by recreating itを見ましたが、残念ながらマットはイベントキューをカバーしていませんでした。それ以外は、私は困惑しています。

ありがとうございます、ありがとうございます。

追加する編集:は、彼は同じ問題とCocoaBuilder, capture first right mouse downのポストへのリンクについて語っているLloyd's Loungeのポストを見つけました。私は現在、そこに提供されているコードを試しています。[theEvent type]のNSLogを回して再起動すると、マウスの左ボタンのアクティビティが捕捉されています。

ウィンドウを左クリックすると、イベントタイプのシーケンス13, 1, 13が生成されます。これは、NSAppKitDefined、NSLeftMouseDown、およびNSAppKitDefinedです。これらをフィルタリングしたり、どこに行くのかを見つけることはできますか?

答えて

2

これは私が探していた答えではありませんが、今のところ十分にうまくいきます。 NSViewをサブクラス化し、次のメソッドを実装することにより、そのビューはボタンとして機能します。

- (void)mouseDown:(NSEvent *)theEvent { 
    [NSApp preventWindowOrdering]; 
// [self setNeedsDisplay:YES]; 
} 

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

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

これ以外は何も必要ありません。もちろん、これはNSButtonの優れた点を迂回しているので、ボタンの状態を描画して更新する必要があります。しかし、私は答えがうれしいです。

1

acceptsFirstMouse:をチェックしましたか?すべてNSViewは、このイベントにYESを返して、ウィンドウをフォアグラウンドにするのではなく、ビューがイベントを処理する必要があると言うことができます。おそらく、イベントを傍受することによって、ウィンドウを前面に持っていくのには使用されませんが、私はそれを保証することはできません。

明らかに、この動作を実行するコントロールをサブクラス化して、acceptsFirstMouse:をオーバーライドする必要があります。

+0

acceptsFirstMouse:and acceptsFirstResponder:この問題で私の最初の試みは何の効果もありませんでした。しかし、ありがとう。 –

3

NSPanelは、非アクティブ化時に非表示にしないように設定されており、必要に応じてキーになるように設定できます。これは、使用するコントロールがYESから-acceptsFirstMouse:に戻ることを前提としています。デフォルトではNSButtonです。

パネルのIBから非アクティブ化非表示フラグをオフにすることはできますが、パネルには-setBecomesKeyOnlyIfNeeded:YESメッセージを発行してボタンをクリックするとアプリが表示されないようにする必要があります。

+0

これは答えだと思っていますが、(acceptsFirstMouse: 'メソッドが定義されている)NSViewクラスリファレンスを読むと、それは' NO'に設定されています。最後に 'NSView'をサブクラス化すると、何の違いもありません。 –

+0

ちょうどCocoaDevに関する簡単なディスカッションがありました。http://www.cocoadev.com/index.pl?PreventWindowOrdering、これは私が欲しいことをしていますが、それについては悪い方法のように思えます。 –

+0

'acceptsFirstMouse:'のドキュメントは 'YES 'を返すように' NSButton'を呼び出します: "NSButtonとNSSliderのインスタンスのような多くのコントロールオブジェクトはそれらを受け入れます。マウスボタンを離さずにコントロールを操作することができます。 –

2

それはNSButtonがクリックスルーしたイベントのアプリがアクティブである場合、その動作を変更せずに対応することが可能です:

インタフェース(ClickThroughButton.h):

#import <AppKit/AppKit.h> 

@interface ClickThroughButton : NSButton 

@end 

実施(ClickThroughButton.m) :

#import "ClickThroughButton.h" 

@implementation ClickThroughButton 

- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent { 
    return ![NSApp isActive];  
} 

- (void)mouseDown:(NSEvent *)theEvent {  
    if (![NSApp isActive]) { 
     [NSApp preventWindowOrdering];   

     [self highlight:YES]; 

     NSEvent *mouseUpEvent = [[self window] nextEventMatchingMask:NSLeftMouseUpMask 
                untilDate:[NSDate distantFuture] 
                inMode:NSEventTrackingRunLoopMode 
                dequeue:YES]; 
     NSPoint mouseLocation = [self convertPoint:[mouseUpEvent locationInWindow] fromView:nil]; 
     BOOL mouseUpInside = [self mouse:mouseLocation inRect:[self bounds]]; 

     if (mouseUpInside) { 
      if ([self target]) 
       [[self target] performSelector:[self action] withObject:self]; 
     } 

     [self highlight:NO];    

    } else { 
     [super mouseDown:theEvent];   
    } 
} 

@end 
+0

それは動作しますが、ダイアログを一番上に置く方法はありますか?私はキーボードビューアのようなアプリケーションを開発中です。 –

関連する問題