14

ドックからアイテムをドラッグすると、クラウド ドラッグ カーソルが表示され、放すとピッと消えます。同様に、Xcode でブレークポイントを行番号ガターの外にドラッグすると、同じことが起こります。

アプリケーションに同じ効果を実装したいのですが、正しい方法が見つかりません。

NSDraggingSource および NSDraggingDestination プロトコルを実装する NSImageView の子孫があります。このビューには、コンテンツを他のビューにドラッグできるインスタンスがいくつかあります (このシナリオではコピー操作が行われますが、これは、ドラッグ アンド ドロップが実装され、標準タスクで完全に機能していることを示す場合にのみ関係します)。

ここで、画像をそのビューからどこにでも (別のビュー インスタンスを除いて) ドラッグするときに、ドロップ時に削除操作を実行したいと考えています。ただし、ドラッグ操作はターゲット ビューによって完全に制御されます。思い通りに応答させることはできましたが (これは大変な作業ですが)、アプリケーションの外にドラッグすると完全に失敗します。

ドラッグ操作を削除できれば、次の方法で簡単に処理できます。

- (void)draggedImage: (NSImage *)image
             endedAt: (NSPoint)screenPoint
           operation: (NSDragOperation)operation
{
    if (operation == NSDragOperationDelete) {
        NSRect rect = [self.window convertRectToScreen: [self convertRect: self.frame fromView: nil]];
        NSShowAnimationEffect(NSAnimationEffectPoof, rect.origin, self.bounds.size, nil, nil, NULL);
    }
}

私はすでに次のように削除カーソルを設定しようとしました:

- (void)draggingSession: (NSDraggingSession *)session
           movedToPoint: (NSPoint)screenPoint
{
    if (!NSPointInRect(screenPoint, self.window.frame)) {
        [[NSCursor disappearingItemCursor] set];
    }
}

(簡単にするために、これは現時点ではウィンドウ全体を対象としています)。これは、デスクトップまたはファインダー ウィンドウにヒットしない限り機能します。おそらく、Finder が独自のドラッグ カーソルを同時に設定するため、ちらつき始めます。ドックを叩いてもまったく効果なし。これは、独自のペーストボード データ型を定義したときにも発生します。

さらに、アプリケーションの他のドロップ対応ビューは、ドラッグ データ (NSTextView など) を受け入れますが、これは望ましくありません (カスタム スキームでドラッグ ペーストボードに NSURL を書き込んでいます)。

アップデート:

私はさらに数歩進んだ。draggingSession:sourceOperationmaskForDraggingContext:ピーターがすでに示したように、私のコードではどのように見えるかを処理することが不可欠です。

- (NSDragOperation)       draggingSession: (NSDraggingSession *)session
    sourceOperationMaskForDraggingContext: (NSDraggingContext)context;
{
    switch(context) {
        case NSDraggingContextOutsideApplication:
            return NSDragOperationDelete;
            break;

        case NSDraggingContextWithinApplication:
        default:
            return NSDragOperationDelete | NSDragOperationMove;
            break;
    }
}

これにより、2 つの問題が解決されます。1) アプリケーションの外部では、ドラッグ操作はまったく受け入れられません。2) すべての標準ビューもこの操作を受け入れないようにします (NSOutlineView、NSTextView などは指定されたドラッグ操作を処理しないため)。さらに、独自のペーストボード データ型を作成しましたが、これは必要ないようです。それでも、独自のものを持っている方が明確です。

残念ながら、NSImageView の子孫の外側 (アプリケーションの内外の両方) にドロップしても、NSDragOperationDelete はdraggedImage:endedAt:operation:(上で指定したもの) ではなく、NSDragOperationNone になります。さらに、マウスをアプリケーションの外に移動するときのドラッグ カーソルは、消えるアイテムではなく、許可されていません。したがって、誰かがこれら2つのことを解決できれば、それを私の質問への回答として受け入れます.

4

5 に答える 5

2

これを行うためのハックではない方法があるかもしれませんが、1 つの可能性を考えることができます: ドラッグが開始されたら、デスクトップのサイズの透明な境界線のないウィンドウを作成して、ダミーのドラッグ先にします。透過的であっても、ドロップを受信できるようにするために-setIgnoresMouseEvents:withを呼び出す必要がある場合があります。NOまた、メニュー バーまたは Dock へのドラッグが引き続きウィンドウによってインターセプトされるように、ウィンドウ レベルをメニュー バー (NSMainMenuWindowLevel + 1) の上に設定する必要があります。

ドラッグ先として、このウィンドウは、画像ビューの 1 つがカーソルの下にあるかどうかを確認する必要があります。を使用+[NSWindow windowNumberAtPoint:belowWindowWithWindowNumber:]して、カーソルの下にある透明なオーバーレイ ウィンドウの下のウィンドウを見つけることができます。次に、 を使用-[NSApplication windowWithWindowNumber:]してアプリのウィンドウの 1 つであるかどうかを判断し、そうである場合は、そのコンテンツ ビューを呼び出し-[NSView hitTest:]て (カーソル座標を適切に変換して) ビューを見つけます。NSDraggingDestinationその後、必要に応じてメソッドをそのビューに転送できます。

于 2013-07-04T14:04:38.320 に答える
2

私の推測では、 NSDragOperationDelete は、ドックの Trashをターゲットとするドラッグ/ドロップのみに関係し、それ以外には関係ないと思います。

NSDragOperationGenericの方が適しているはずです。メソッドを混在させないでください。10.7 ルートを使用する場合は、以下をお勧めします。

-(void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
于 2013-07-10T00:27:03.530 に答える