2017-06-13 3 views
8

私はメニューバーアプリケーションで作業していますが、NSMenuItemviewプロパティを使用してカスタムビューを設定しています。カスタムビューのNSMenuItemはマウスイベントを受け取りません

ビューは表示されますが、開いているサブメニューがあるメニュー項目のマウスクリックイベントは発生しません。

このスクリーンショットでは、各アイテムにボタンを追加しました。 3つ右端のボタンは正しく機能しますが、親メニューのボタンはクリックイベントをまったく受け取りません。

Screenshot

私には、原料の束を試してみた:カスタムビューキーのNSWindowたときに作成mouseUpmouseDown方法

  • を使用してマウスイベントをキャプチャしようとすると

    • マウスがそのビューに入る
    • グローバルモニタとローカルモニタを追加するNSEvents

    ...しかしNSMenuItemためtarget-actionコールバックがあれば呼び出されませんので無駄に

    はしても、ボタンを追加するアプローチせずに、私は、標準NSMenuItemのデフォルトの動作を複製することはできませんそれはカスタムビューを持っています。

    デフォルトのNSMenuItem(カスタム表示なし)を使用して開いているサブメニューを持つメニューを選択できるので、これは理論上可能であるはずです。

    誰も助けることができますか?

    おかげ

  • +2

    メニュー項目を追加するときにコードを投稿できますか?あなたの写真から、メニュー項目をカスタム表示にするのではなく、メニュー項目に(上に)表示を追加するように見えます。これは面白い質問のようです。 – Farini

    答えて

    4

    私はメニュー項目のviewとしてNSButton秒で、あなたのようなテストプロジェクトを設定し、あなたが見たのと同じ動作を見ました。それは本当に面白いです。 NSApplicationをサブクラス化し、その-sendEvent:メソッドをオーバーライドして、どのイベントがメカニズムを通過するかを見るためにログを追加すると、を実行してもが実際には呼び出されないことがわかります。それは奇妙じゃない?したがって、次に試すべきことはNSButtonをサブクラス化し、-mouseDown:のオーバーライドを追加してそこにブレークポイントを配置することです。もちろん、開いているサブメニューではブレークポイントにヒットすることはありませんが、他のボタンではヒットします。我々はそれを行うときには、バックトレースは次のとおりです。

    (lldb) bt 
    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 
        * frame #0: 0x0000000100002fa0 menutest`MyButton.mouseDown(event=0x0000608000121900, self=0x0000600000140a50) at AppDelegate.swift:33 
        frame #1: 0x000000010000303c menutest`@objc MyButton.mouseDown(with:) at AppDelegate.swift:0 
        frame #2: 0x00007fffa9f6724f AppKit`-[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 6341 
        frame #3: 0x00007fffa9f63a6c AppKit`-[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 1942 
        frame #4: 0x00007fffa9f62f0a AppKit`-[NSWindow(NSEventRouting) sendEvent:] + 541 
        frame #5: 0x00007fffa9a2328d AppKit`-[NSCarbonWindow sendEvent:] + 118 
        frame #6: 0x00007fffa9a20261 AppKit`NSMenuItemCarbonEventHandler + 10597 
        frame #7: 0x00007fffab0acd85 HIToolbox`DispatchEventToHandlers(EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 1708 
        frame #8: 0x00007fffab0abff6 HIToolbox`SendEventToEventTargetInternal(OpaqueEventRef*, OpaqueEventTargetRef*, HandlerCallRec*) + 428 
        frame #9: 0x00007fffab0c1d14 HIToolbox`SendEventToEventTarget + 40 
        frame #10: 0x00007fffab0ea7df HIToolbox`ToolboxEventDispatcherHandler(OpaqueEventHandlerCallRef*, OpaqueEventRef*, void*) + 2503 
        frame #11: 0x00007fffab0ad17a HIToolbox`DispatchEventToHandlers(EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 2721 
        frame #12: 0x00007fffab0abff6 HIToolbox`SendEventToEventTargetInternal(OpaqueEventRef*, OpaqueEventTargetRef*, HandlerCallRec*) + 428 
        frame #13: 0x00007fffab0c1d14 HIToolbox`SendEventToEventTarget + 40 
        frame #14: 0x00007fffab12e928 HIToolbox`IsUserStillTracking(MenuSelectData*, unsigned char*) + 1658 
        frame #15: 0x00007fffab255dc4 HIToolbox`TrackMenuCommon(MenuSelectData&, unsigned char*, SelectionData*, MenuResult*, MenuResult*) + 1664 
        frame #16: 0x00007fffab13a223 HIToolbox`MenuSelectCore(MenuData*, Point, double, unsigned int, OpaqueMenuRef**, unsigned short*) + 554 
        frame #17: 0x00007fffab139f66 HIToolbox`_HandleMenuSelection2 + 460 
        frame #18: 0x00007fffa97ee368 AppKit`_NSHandleCarbonMenuEvent + 239 
        frame #19: 0x00007fffa9a68702 AppKit`_DPSEventHandledByCarbon + 54 
        frame #20: 0x00007fffa9de90c5 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 963 
        frame #21: 0x00007fffa96623db AppKit`-[NSApplication run] + 926 
        frame #22: 0x00007fffa962ce0e AppKit`NSApplicationMain + 1237 
        frame #23: 0x00000001000035fd menutest`main at AppDelegate.swift:13 
        frame #24: 0x00007fffc12fc235 libdyld.dylib`start + 1 
    

    あなたが見ることができるようにメニューが実際に炭素であるため、イベントはココアイベントディスパッチ機構を介して派遣されていません。そうですが、64ビットへの移行で削除されたと思われるCarbon APIやサブシステムの多くは、実際にはまだ生き残っています。彼らはただのプライベートAPIです。 は、これらを64ビットモードで使用することはできませんが、Appleが可能で、メニューシステム全体がまだCarbonイベントモデルの上に実装されています。サードパーティの開発者はPhotoshopを一から書き直す必要はありますが、誰かが1997年に書いたそのメニュー処理コードは、あきらめるだけの価値があります。私は確信しています。

    とにかく、このバックトレース(最上位レベルのもの以外)でもっとも初期のObjective-Cメソッドである-[NSCarbonWindow sendEvent:]を振りかざすことによって少しテストを行い、サブメニューアイテムがクリックされたときにそれはそうではありません。だから私が推測しなければならないのは、Carbonイベントハンドラに問題があると言えます。さて、これは後端の痛みのビットかもしれないが、ちょっと、問題はない!これを回避するには、Carbonレベルに落として、独自のCarbonイベントハンドラをインストールします。いいえ、あなたの袖を巻いてみましょう。th-

    ああ、右。

    これらのAPIを64ビットモードで使用することはできません。

    Picard Facepalm

    とにかく、私は悲しいことに、これは将来の破損をthis guy didようになりました民間のAPIが何であるかを使用するように厄介なハックを使用して危険にさらすの短い仕事に取得する方法があるように起こっているとは思わない(言うまでもありませんApp StoreからInstabannedされている)。または何かをやって実際にバックトレースでそれらのCの機能のうちの1つをモンスキッペンドしているように狂っている可能性がさらに悪化する可能性があります。しかし、この全体の問題は、レーダーの報告に値すると思われる。 file one with Appleをお知らせして、この問題について知らせてください。将来のリリースで修正されるかもしれません。

    編集:実際には解決策があります。サブメニューを持たないメニュー項目に添付されたビューは、期待するマウスイベントを受け取るので、submenuの設定を無視して、自分のビューにmouseEntered:イベントとmouseExited:イベントをキャッチして自分でメニューを表示するだけで、サブメニュー。世界で最も理想的なソリューションではありませんが、それは少なくとも何かです。

    関連する問題