【问题标题】:VSTO Word 2016: Squiggly underline without affecting undoVSTO Word 2016:波浪线下划线而不影响撤消
【发布时间】:2016-11-27 13:14:17
【问题描述】:

我正在开发一个实时语言分析工具,该工具需要在 Word 2016 中使用 VSTO 插件突出显示单词以引起作者的注意,该插件是用 .NET4.6.1 和 C# 编写的。想想语法/拼写检查,它会在单词下方添加一条波浪线,以显示该单词存在语法或拼写错误。我正在为我自己定义的一些规则添加类似的功能。

我四处搜索添加波浪线,偶然发现Font.UnderlineFont.UnderlineColor。我将其设置在一个单词的范围内,它似乎提供了我所追求的视觉效果来引起注意。但是,有一个问题。我添加的每个下划线或我更改的下划线颜色都会向撤消堆栈添加一个撤消操作。

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

我该怎么做呢?

【问题讨论】:

    标签: c# .net ms-word vsto


    【解决方案1】:

    我偶然发现了这个问题,它问的是完全相同的问题: Prevent actions to be added to the word undo redo OR Remove actions from the undo redo CommandBarComboBox

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

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

    这里也有类似的问题Word VSTO override CTRL+Z / CTRL+Y 建议使用 Microsoft.Office.Interop.Word.UndoRecord 路由或 AddIns 中的 MessageHooks。


    经过更多研究后,我注意到这个帖子末尾的一个好主意:MSDN Draw my own squigglies on Word document,您可以在其中跟踪您的操作,然后在撤消和重做操作中跳过它们。

    这是执行“事务性撤消/重做”Can I create an undo transaction in Word or Excel? (VSTO) 的一个很好的代码示例。正如 Dirk Vollmar 在他的回答中指出的那样,除了一个大问题之外,您可以在 VSTO 中执行相同的方法:

    我认为单独使用 VSTO 无法覆盖内置 Word 命令

    我已经使用键盘挂钩事件覆盖了 VSTO 中的一些内置命令以拦截命令:How to perform .Onkey Event in an Excel Add-In created with Visual Studio 2010? 但是我不确定您是否可以重新创建功能区来拦截按钮命令。更具体地说,撤消和重做是功能区 UI 中的内置库,您无法使用内置功能区库执行任何操作。在 2010 等版本中,撤消/重做按钮位于标题栏中 - 你不能 add/edit buttons on the title bar using 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);
    

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


    同一质量检查中的另一个答案 Can I create an undo transaction in Word or Excel? (VSTO) 是 Mike Regan,他在 Dirk 3 个月后回答。他使用了一个隐藏文档,并在需要时将其放置在真实文档中,以使任何数量的 VSTO 操作都成为一次撤消。

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


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

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


    这不是一个容易解决的问题,有很大的限制,所以可能更容易:

    a) 接受您的拼写/语法检查插件包含在撤消/重做列表中(失败)。

    b) 找出行/文本在屏幕上的位置,并显示一个透明的工具提示来突出问题。这比看起来要困难得多,而且不太理想,这里有两个很好的答案来指导您使用这种方法:Detecting text changes in Word 2016 from VSTO add-in 或更简单的方法来从这个 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) 仅通过键盘使用事务性撤消/重做捕获撤消/重做事件,并让用户看到使用按钮的原子撤消/重做。删除撤消/重做按钮会非常不明智,这会导致大量我的撤消按钮不见了? 支持案例。所以不要这样做,如果你很好奇,可以从“.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) 尝试拦截原始 Windows 消息,例如 Excel CustomTaskPane with WebBrowser control - keyboard/focus issues 只是注意,根据我引用 BUG: Cant choose dates on a DatePicker that fall outside a floating VSTO Add-In 的评论,Office 中的消息泵有时会表现出奇怪的行为。

    【讨论】:

      【解决方案2】:

      不幸的是,看起来这个问题并没有简单的解决方案。据我所知,您有两种选择:

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

      我知道这不是你想要的,but even Microsoft MVPs don't have a better solution

      【讨论】:

      • 谢谢!这大大改善了当前的情况。
      猜你喜欢
      • 1970-01-01
      • 2015-03-24
      • 2017-09-13
      • 2020-09-02
      • 1970-01-01
      • 2017-03-25
      • 2017-05-02
      • 2018-01-16
      相关资源
      最近更新 更多