vs extensionキーボード入力の傍受

4606 ワード

背景
コードの作成時にユーザーがキーボードイベントを傍受するビジネス要件があります.
きほんぶんせき
part1
vsをデスクトップアプリケーションと見なすと、このフォームアプリケーションに介入したいキーボードイベント処理プロセスです.もちろん、vsはキーボードイベント処理インタフェースを直接暴露しないと直感的に思います.
この観点はjaredparの大物の経験を検証して1を分かち合う時一定の検証を得て、私はまだフォームのキーボードが事件を処理する拡張点を見つけていません
part2
次に、キーボードイベントを直接または間接的に取得する他の方法を探してみました.このとき、コードファイルに対応するドキュメントオブジェクトのコンテンツ変化イベントを傍受することで、キーボードイベントを確認しました.私たちの符号化プロセスでは、キーボードノックの主な目的はコードテキストを修正することです.
この部分の内容はEnDTE.DTE2.events.DocumentEventsが露出したインタフェースで実現
しかし、上記のシナリオには一定の問題があり、我々の1回のキーボードイベントが1段の入力(tabキー、copy paste、中国語入力法で中国語を入力)に対応しているか、または複数回のキーボードイベントが1回の入力(中国語入力法で中国語と組み合わせキーを入力)に対応している可能性があるため、上記のシナリオには欠陥がある.
part3
それから私はjaredparの大物の経験を見つけて1を分かち合って、私はvsがキーボードの事件を処理することに対して少量の理解があって、以下は大物の分かち合いの原話を抜粋します.
Let’s start off with a high level view of the events and systems and the order in which they
fire
  1. PreTranslateMessage – Native windows messages.  May handle and swallow a message
  2. WPF and TextCompositionManager
     a. KeyDown
     b. TranslateAccelator
     b. TextInput
 
Now how the components in Visual Studio play together to route key input
 
  1. PreTranslateMessage – This is handled in msenv.  It has the first go and will attempt 
     to map keyboard input into a key boarding binding for a Visual Studio command.  It 
     will only attempt to map non-alphanumeric input or alphanumeric input which has a 
     modifier such as Shift, Control, Alt.  If it can find a match then it uses the key 
     stroke otherwise it gets passed on goes to #2
  2. WPF
    a. VisualElement raises the KeyDown.  KeyProcessor’s now come into play as they 
       indirectly subscribe to this event which they can interpret and handle. 
    b. Translate Acessorator goes through the IVsChain.  This causes problems because certain
       components (IVsFilterKeysAdapter) will intercept and swallow the keystroke.  
    c. TextCompositionManager receives the message and after much magic raises the 
       TextInput event on KeyProcessors. 
      i. Note: How the key is entered changes which field on TextComposition has the text.  
         For normal printable input the text will be on the Text property.  For items like 
         CTRL-M it will be on the ControlText property. 
      ii. One of the key processors is VsKeyProcessor which will turn every character in the 
        Text property of the argument into a TYPECHAR command. 
 
 Another way to look at it from a component perspective from when a message is recieved 

  - msenv::ProcessMessage
    - msenv::SCM_MsoStdCompMgr::FPreTranslateMessage
      - msenv::CMsoComponent::FPreTranslateMessage
        - msenv::CMsoComponent::MainFTranslateMessage
          - IVsWindowManager::TranslateAccelerator
            - IVsCodeWindow::PreTranslateMessage
              - IVsFilterKeysAdapter::TranslateAccelerator
          - Visual Studio Commands.
    - IVsWindowManager::PreTranslateInput
      - System.Windows.Interop.ComponentDispatcher.RaiseThreadMessage
         - TextCompositionManager 
            - KeyProcessor.KeyDown
            - KeyProcessor.TextInput
      - If that returns true then done
  - TranslateMessage
  - DispatchMessage

ここでは、msenv::ProcessMessageからIVsFilterKeysAdapter::TranslateAcceleratorに注目します.公式ドキュメントには直接的な拡張点が見つかりません.CommandsはEnDTEのDTEを試してみることができます.events.CommandEventsインタフェースはリスニングを実現し、ここでは編集コマンド(copy paste save cut redo undo)を直接キャプチャすることができます.
その後の過程の中のKeyProcessorは、MEFの方式を通じてIKEyProcessorProviderインタフェースを実現する形式で拡張することができ、この部分の内容は大物たちの再フォーラムの討論を参考にすることができる.
part4
検索中にマイクロソフトチームがgithubで公開しているvs extensionサンプルプロジェクトを見つけました.その中でTyping_Speed_Meterプロジェクト3ではキーボードイベントの傍受に関する操作が用いられるが,これは従来の考え方とは異なり,Io 1 eCommandコマンドを用いて一部のキーボード入力イベントをフィルタリングする.
シナリオ検証
最後にkeyProcessorとIo 1 eCommandの2つの方式を検証した.
##keyProcessor方式では、チェックアウトボタンとリターンボタンのkeyDownイベントCtrlコンビネーションボタンの入力文字イベントを傍受できません.入力方式に遭遇したとき、イベントが受け取った内容はImeProcessedです.
##Io 1 eCommandスキームこのセクションは、コードウィンドウに基づくtextViewリスニングコマンドイベントですが、時間配布メカニズムの問題で、このレイヤに転送されたイベントはテキスト編集関連のみで、copy pasteとcut関連のコマンドは受信できません.このセクションでは、チェックアウトとリターンイベントを監視できます.
ソリューション
いくつかの客観的な理由から、ここでは最終的に損傷のある受信方法を選択し、keyProcessorを通じて普通のキーボードイベントを傍受し、Io 1 eCommand方式でスペースとリターンイベントを傍受し、それ以外にCommandEventsインタフェースを通じてよく見られるコマンドイベントを傍受する.
https://github.com/jaredpar/VsVim/blob/master/Src/VsVim/KeyboardInputRouting.txt ↩︎ ↩︎
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9f0798d5-99a3-43be-91f9-dd09c183bb7b/catching-keyboard-input?forum=vsx ↩︎
https://github.com/Microsoft/VSSDK-Extensibility-Samples/tree/master/Typing_Speed_Meter ↩︎