質問

右マウスのボタンクリックで作業したいNSButtonサブクラスがあります。ただ過負荷 -rightMouseDown: 定期的なクリックと同じ種類の動作が必要なので、それをカットしません(たとえば、ボタンが押し下げられ、ユーザーはボタンを離れることでキャンセルできます。マウスがリリースされたときにアクションが送信されます)。

私がこれまでに試したことは過負荷です -rightMouse{Down,Up,Dragged}, イベントを変更して、左マウスボタンのクリックを示すために、次に送信します -mouse{Down,Up,Dragged}. 。今ではこれは明らかにせいぜいハッキングになります。結局のところ、Mac OS Xはそれをすべて好きではありませんでした。ボタンをクリックできますが、リリースされると、ボタンが押し込まれたままになります。

私は自分で動作を模倣することができましたが、それはあまり複雑ではありません。ただし、ボタンを押し込んだ方法がわかりません。


「しないでください!それは型破りなMac OS Xの動作であり、避けるべきです」と言う前に:私はこれを考慮し、右クリックがワークフローを大幅に改善する可能性があります。基本的にボタンは4つの状態を循環します。右クリックして、逆にサイクリングすることをお勧めします。それは重要な機能ではありませんが、いいでしょう。それでも「しないで!」と言っていると感じたら、あなたの考えを教えてください。それは有り難いです!

ありがとう!

編集:これは私のイベントを変更する試みでした(タイプを変更することはできないので、新しい情報を作成し、すべての情報をコピーしました。あなたと同じように、私はそれを試しました):

// I've contracted all three for brevity
- (void)rightMouse{Down,Up,Dragging}:(NSEvent *)theEvent {
    NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouse{Down,Up,Dragging} location:[theEvent locationInWindow] modifierFlags:[theEvent modifierFlags] timestamp:[theEvent timestamp] windowNumber:[theEvent windowNumber] context:[theEvent context] eventNumber:[theEvent eventNumber] clickCount:[theEvent clickCount] pressure:[theEvent pressure]];
    [self mouse{Down,Up,Dragging}:event]; 
}

更新:私はそれに気づきました -mouseUp: NSButtonに送られたことはなく、Nscontrolに変更した場合はそうでした。フランシス・マクグルーが独自のイベント処理ループが含まれていると指摘するまで、なぜこれがなぜだったのかわかりませんでした。今、これは私が再ルーティングする前になぜ理にかなっています -rightMouseDown:, 、しかし、ボタンはリリース時に上がりません。これは、新しいイベントを単独でフェッチしていたため、右から左マウスのボタンイベントから遮断されて変換できませんでした。

役に立ちましたか?

解決

NSButtonはマウストラッキングループに入ります。これを変更するには、nsbuttonをサブクラス化し、独自のカスタムトラッキングループを作成する必要があります。このコードを試してください:

- (void) rightMouseDown:(NSEvent *)theEvent 
{
    NSEvent *newEvent = theEvent;
    BOOL mouseInBounds = NO;

    while (YES) 
        {
            mouseInBounds = NSPointInRect([newEvent locationInWindow], [self convertRect:[self frame] fromView:nil]);
            [self highlight:mouseInBounds];

            newEvent = [[self window] nextEventMatchingMask:NSRightMouseDraggedMask | NSRightMouseUpMask];

            if (NSRightMouseUp == [newEvent type])
            {
                break;
            }
        }
    if (mouseInBounds) [self performClick:nil];
}

これが私がそれをする方法です。うまくいけば、それはあなたのために働くでしょう。

他のヒント

左マウスをクリックして保持し、パスコントロールで偽の右マウスになりました。これがあなたのすべての問題を解決するかどうかはわかりませんが、私がこれをしたときの重要な違いはタイムスタンプを変更することであることがわかりました。

NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown 
                                    location:[theEvent locationInWindow] 
                               modifierFlags:[theEvent modifierFlags] 
                                   timestamp:CFAbsoluteGetTimeCurrent()
                                windowNumber:[theEvent windowNumber] 
                                     context:[theEvent context]
 // I was surprised to find eventNumber didn't seem to need to be faked 
                                 eventNumber:[theEvent eventNumber]   
                                  clickCount:[theEvent clickCount] 
                                    pressure:[theEvent pressure]];

もう1つは、ボタンの種類に応じて、 state プッシュされているかどうかにかかわらず価値があるかもしれないので、あなたはそれを突ってみようとするかもしれません。

更新:私はその理由を理解したと思います rightMouseUp: 呼ばれることはありません。あたり -[NSControl mouseDown:] ドキュメント、ボタンがマウスが取得されるとマウスの追跡を開始します mouseDown イベント、そうではありません 止まる それが得られるまで追跡します mouseUp. 。追跡している間、他に何もできません。たとえば、カスタムの最後に試してみました mouseDown::

[self performSelector:@selector(mouseUp:) withObject:myFakeMouseUpEvent afterDelay:1.0];

しかし、これは通常まで延期されます mouseUp: 他の方法でトリガーされます。したがって、右のマウスボタンをクリックした場合、(マウスで)送信できません leftMouseUp, 、したがって、ボタンはまだ追跡されており、 rightMouseUp イベント。私はまだ解決策が何であるかわかりませんが、それは有用な情報になると考えました。

上記の回答に追加することはあまりありませんが、Swiftで働いている人にとっては、イベントマスクの定数を見つけるのに苦労するかもしれません。コンパイラが受け入れることなので、これにより時間を節約できます。より厄介な方法はありますか?これはあなたのサブクラスに入ります -

var rightAction: Selector = nil 
  // add a new property, by analogy with action property

override func rightMouseDown(var theEvent: NSEvent!) {
  var newEvent: NSEvent!

  let maskUp = NSEventMask.RightMouseUpMask.rawValue
  let maskDragged = NSEventMask.RightMouseDraggedMask.rawValue
  let mask = Int( maskUp | maskDragged ) // cast from UInt

  do {
    newEvent = window!.nextEventMatchingMask(mask)
  }
  while newEvent.type == .RightMouseDragged

私のループはやりました。 while true, 、そして、私はドラッグイベントで何もする必要はありません。

おそらく私のコントロールがテーブルビューに埋め込まれていたため、Convertrect()から意味のある結果を得るのに無限の問題がありました。最後の部分のためにこれで終わりました。

let whereUp = newEvent.locationInWindow
let p = convertPoint(whereUp, fromView: nil)
let mouseInBounds = NSMouseInRect(p, bounds, flipped) // bounds, not frame
if mouseInBounds {
  sendAction(rightAction, to: target)
  // assuming rightAction and target have been allocated
  }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top