背景

有一个这样的业务需求:我们希望监听用户在编写代码时的键盘事件

基本分析

part1

如果把vs看做一个桌面应用程序,那么我们就是希望介入到这个窗体应用的键盘事件处理过程
当然我直观上认为vs不会直接把键盘事件处理接口暴露给我

这一个观点在我验证jaredpar大佬的经验分享1的时候得到了一定验证,我还没有找到窗体键盘处理事件的扩展点

part2

接下来,我尝试寻找其他方式来直接或者间接的方式得到键盘事件,这时候我得到了第一种方案,我通过监听代码文件对应的文档对象的内容变化事件来确认键盘事件,因为我们的编码过程,每一次键盘敲击的主要目的都是修改代码文本。

这部分的内容可以通过 EnDTE.DTE2.events.DocumentEvents 暴露出来的接口来实现

但是上面的方案存在着一定问题,我们的一次键盘事件可能对应着一段输入(参考tab键,copy paste,使用中文输入法输入中文),或者多次键盘事件对应着一次输入(使用中文输入法输入中文和组合键),所以上面的方案存在着缺陷

part3

而后我找到了jaredpar大佬的经验分享1,我对vs处理键盘事件有了少量的理解,下面摘录大佬的分享的原话。

Let’s start off with a high level view of the events and systems and the order in which they
fire1. PreTranslateMessage – Native windows messages.  May handle and swallow a message2. WPF and TextCompositionManagera. KeyDownb. TranslateAccelatorb. TextInputNow how the components in Visual Studio play together to route key input1. 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 #22. WPFa. 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 certaincomponents (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接口的形式扩展,这部分的内容可以参考大佬们再论坛里的讨论2.

part4

我在检索的时候找到了微软团队在github上公开的vs extension样例项目,其中Typing_Speed_Meter项目3中用到监听键盘事件相关的操作,这个与之前的思路不太一样,用的是Io1eCommand命令,来过滤一部分的键盘输入事件。

方案验证

最后验证了keyProcessor 和 Io1eCommand 两种方式

##keyProcessor 方案
无法监听到退格和回车按钮的keyDown事件
Ctrl组合按键的输入字符事件会被吞掉
在遇到输入法的时候,事件收到的内容是ImeProcessed

##Io1eCommand 方案
这部分是基于代码窗口的textView监听命令事件,但是由于时间派发机制的问题,转发到这一层的事件只有文本编辑相关的,copy paste和cut相关的命令还是收不到。
这部分可以监听到退格和回车事件

解决方案

由于一些客观上的原因,这里最终选择一种有损的接收方式,我通过keyProcessor 监听普通的键盘事件,而后通过Io1eCommand 方式监听空格和回车事件,在此之外通过CommandEvents接口监听常见的命令事件


  1. https://github.com/jaredpar/VsVim/blob/master/Src/VsVim/KeyboardInputRouting.txt ↩︎ ↩︎

  2. https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9f0798d5-99a3-43be-91f9-dd09c183bb7b/catching-keyboard-input?forum=vsx ↩︎

  3. https://github.com/Microsoft/VSSDK-Extensibility-Samples/tree/master/Typing_Speed_Meter ↩︎

vs extension 监听键盘输入相关推荐

  1. [C#]非阻塞监听键盘输入

    摘要 最近需要调研监控用户键盘输入的内容,然后收集数据进行用户行为分析.然后就用控制台程序弄了一个demo. 代码如下 class Program{static void Main(string[] ...

  2. 监听键盘输入pynput.keyboard

    [小白从小学Python.C.Java] [计算机等级考试+500强双证书] [Python-数据分析] 监听键盘输入 pynput.keyboard 选择题 关于以下python代码说法错误的是? ...

  3. ios 动态监听键盘输入法和高度

    //监听键盘高度变化 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasChan ...

  4. python监听键盘输入_Python监听模拟鼠标键盘

    1.监听鼠标和键盘的输入 from pynput import keyboard,mouse def on_press(key): print('alphanumeric key {0} presse ...

  5. python监听键盘输入 linux_Linux下使用Python捕获键盘输入

    在Linux下如何用Python监控键盘记录 思路 在上篇已经说到如何使用Python获取/dev/input目录下event对应的设备的名字.那么我们可以知道设备的名字,就可以通过名字知道哪些eve ...

  6. python 监听键盘输入并收集数据进行分析

    文章目录 1.键盘监听库pynput 2.进行键盘输入的数据保存 3.从键盘监听中我们能看出什么 3.1 疯狂的ctrl=读代码ing 3.2 看起来有意义的字符串并以Key.enter结尾≈输入某个 ...

  7. 用python pynput 监听键盘输入

    个人的学习记录,发上来当日志吧.方便初学者也方便自己寻找.废话不要太多,直接上代码: from pynput import keyboarddef push(key):if key == keyboa ...

  8. Linux C高阶(21)监听键盘单个按键输入

    文章目录 1 前言 2 终端IO的三种模式 2.1 canonical 模式 2.2 nocanonical 模式 2.3 raw 模式 3 终端控制结构 1 前言 编写测试工具的时候,需要实时的读取 ...

  9. 修改某个UITextField的键盘的返回键类型以及监听键盘的高度变化,取到键盘动画退出弹出的时间,一起随着键盘顶出来或者压下去,...

    1.修改某个UITextField的键盘的返回键类型: [_bottomTextView setReturnKeyType:UIReturnKeyDone]; 1.1.textFied点击return ...

最新文章

  1. 集成“PDF预览”和“页面翻译”的亿简浏览器0.5.0 alpha
  2. C#自动实现Dll(OCX)控件注册的两种方法
  3. python学习笔记之函数(方法)
  4. Spring-国际化信息02-MessageSource接口
  5. python3精要(26)-map
  6. Kubernetes,多云和低代码数据科学:2020年最热门的数据管理趋势
  7. 使用poi调整字体格式、添加单元格注释、自动调整列宽
  8. android之相机开发
  9. 接口测试实例(jmeter)
  10. python3.7下载教程视频_视频 | 我选择Python3.7来学习!顺便把教程分享给大家
  11. 【Mac】Mac iTerm2 使用笔记 远程连接
  12. 在springcacheinvokecontext中没找到field_CNN中的感受野
  13. pycharm主题方案
  14. linux中tftp怎么配置文件,linux的tftp命令参数及用法详解
  15. 微信公众号 模板消息 定时推送 java
  16. 爬取豆瓣电影分类排行榜
  17. 微信小程序前端合包流程weshop
  18. 配对交易之统计套利配对:介绍
  19. 多项式计算的Horner方法
  20. 【C语言】解决 “address of stack memory associated with local variable ‘num‘ returned”

热门文章

  1. 【分享】免费的国际一级域名和100M支持asp、cgi空间
  2. JavaScript设计模式有哪些?
  3. python监控文件或目录变化
  4. 如何使用Kumo Java Word Cloud?
  5. java中最基本的数据类型,java中的基本数据类型
  6. 智慧供水管网监测方案助力水资源高效利用
  7. Wireshark lua插件
  8. c#操作word图表(一)
  9. 低代码,拯救“疯狂”的程序员
  10. 舔砖加瓦(java)之异常