VSTO Word 2016:Squiggly下划线而不影响撤消

我正在开发一个实时语言分析工具,需要使用VSTO加载项(使用C#编写的.NET4.6.1编写)突出显示Word 2016中编写者的注意力。 想一想语法/拼写检查,它会在单词下面添加一条波浪线,表明单词有语法错误或拼写错误。 我正在为我自己定义的一些规则添加一个类似的function。

我搜索了添加波浪线,并偶然发现Font.UnderlineFont.UnderlineColor 。 我把它设置在一个单词的范围内,似乎提供了我想要吸引注意力的视觉效果。 但是有一个问题。 我添加或加下划线颜色的每个下划线都会向撤消堆栈添加撤消操作。

我不希望这种情况发生,或者我想要一种方法来弹出我刚才在堆栈代码中执行的操作。 目的是让用户能够使用CTRL + Z删除他更改的文本 ,而不会影响我的语言分析结果。

我该怎么做呢?

我偶然发现了这个问题,它提出了完全相同的问题: 阻止将操作添加到撤消重做单词中或从撤消重做CommandBarComboBox中删除操作

正如@Manu所指出的那样,在MSDN上也提出了同样的问题,答案是:

UndoClear方法将清空列表。 这是你能做的最好的事情。

此处还有一个类似的问题Word VSTO覆盖CTRL + Z / CTRL + Y ,它表示Microsoft.Office.Interop.Word.UndoRecord路由或AddIns中的MessageHooks。


经过更多的研究,我在这个post的最后注意到了一个好主意: MSDN在Word文档中绘制我自己的波浪线,在那里你可以跟踪你的行为,然后在撤消和重做操作中跳过它们。

这是一个很好的代码来做“事务性撤销/重做” 我可以在Word或Excel中创建撤销事务吗? (VSTO) 。 除了一个大问题之外,你可以在VSTO中使用相同的方法,正如Dirk Vollmar在他的回答中指出的那样:

我不认为仅使用VSTO就可以覆盖内置的Word命令

我已经使用键盘挂钩事件覆盖了VSTO中的一些内置命令来拦截命令: 如何在使用Visual Studio 2010创建的Excel加载项中执行.Onkey事件? 但是,我不确定您是否可以重新创建function区来拦截按钮命令。 更具体地说,Undo和Redo是Ribbon UI中的内置库,您无法对内置的Ribbon库执行任何操作。 在2010版本中,撤消/重做按钮位于标题栏中 – 您无法使用VSTO在标题栏上添加/编辑按钮 :

在此处输入图像描述

因此,如果您关注捕获按钮命令( 我知道每个人都使用Ctrl + Z和Y ),您可能会注入VBA代码以访问EditUndoEditRedo事件,例如:

 VB._VBComponent vbModule = VBProj.VBE.ActiveVBProject.VBComponents.Add(VB.vbext_ComponentType.vbext_ct_StdModule); String functionText = "Public Sub EditUndo() \n"; functionText += "MsgBox \"Undo Happened\"\n"; functionText += "End Sub"; vbModule.CodeModule.AddFromString(functionText); 

这种方法的主要问题是需要授予信任。


同一QA中的另一个答案我可以在Word或Excel中创建撤消事务吗? (VSTO)是由Mike Regan在Dirk之后3个月回答的。 他使用隐藏文档并在需要时将其放在真实文档中,以便将任何数量的VSTO操作单个撤消。

仍然无法解决阻止在撤消历史记录中记录操作的问题。


我确实尝试使用注册表项将UndoHistory限制为0并将其重置为100(为了在添加操作时禁用历史记录),但它似乎仅适用于Excel https://support.microsoft.com/en- GB / KB / 211922

可能有一个未记录的注册表来完全禁用撤消/重做历史记录,但它只能在启动时由Word读取。 我认为在每次撤销/重做之前都会读取包含数字的UndoHistory键,但根本没有运气。


解决这个问题不是一个容易解决的问题,因此可能更容易:

a)接受你的拼写/语法检查程序加载项包含在撤消/重做列表中(失败)。

b)找出线/文本在屏幕上的位置,并显示突出显示问题的透明工具提示。 这比看起来要难得多,并且不太理想,这里有两个很好的答案来指导你这个方法: 从VSTO加载项中检测Word 2016中的文本更改或从这个Microsoft电子邮件中检测XY位置的更简单的方法主题: https : //groups.google.com/forum/#!topic / microsoft.public.word.vba.general / pKq4PsqD3cM

 //position dialog relative to word insertion point (caret) int left = 0; int top = 0; int width = 0; int height = 0; MSWord.Range r = Globals.ThisDocument.Application.Selection.Range; MSWord.Window w = Globals.ThisDocument.ActiveWindow; w.GetPoint(out left, out top, out width, out height, r); frmPopUp newForm = new frmPopUp(); newForm.SetDesktopLocation( left + width + 2, top - newForm.Height + height ); 

c)仅通过具有事务撤消/重做的键盘捕获撤消/重做事件,并让用户使用按钮查看primefaces撤消/重做。 删除撤消/重做按钮会非常狡猾,这会导致我的撤销按钮的哪个部分消失了? 支持案例。 所以不要这样做,如果你很好奇,可以从“.qat”文件快速访问工具栏定制。 参考: https : //support.microsoft.com/en-us/kb/926805

d)使用鼠标钩并检测何时单击“撤消/重做”按钮。 这是连接鼠标的代码,注意这不会与公司的反病毒产品很好玩,我不推荐它: https : //blogs.msdn.microsoft.com/andreww/2009/02/24/message-hooks -in-add-ins /或https://github.com/gmamaladze/globalmousekeyhook 。

e)尝试拦截原始窗口消息,例如带有WebBrowser控件的Excel CustomTaskPane – 键盘/焦点问题根据我的评论引用BUG:请勿在DatePicker上选择日期不属于浮动VSTO加载项的日期表现出奇怪的行为。

不幸的是,它看起来并不像这个问题有一个简单的解决方案。 从我所看到的,你有两个选择:

  1. 您可以使用Document.UndoClear清除整个撤消堆栈。 但是,这将不是非常用户友好,因为之前的所有操作都不在撤消列表中。
  2. 使用UndoRecord类。 在对StartCustomRecordEndCustomRecord调用之间,代码中的所有操作都只会在撤消堆栈中生成一个项目。 CTRL + Z仍将影响您的语言分析,但整个撤消堆栈不会像以前那样受到污染。

我知道这不是你想要的, 但即使是微软的MVP也没有更好的解决方案 。