VSTO Word 2016:不影响撤消的波浪下划线
VSTO Word 2016: Squiggly underline without affecting undo
我正在开发一个实时语言分析工具,它需要在 Word 2016 中使用 VSTO 加载项突出显示单词以引起作者的注意,该加载项使用 C# 在 .NET4.6.1 中编写。想一想 grammar/spelling 检查,它会在单词下方添加一条波浪线,告诉您该单词有语法或拼写错误。我正在为我自己定义的一些规则添加类似的功能。
我四处搜索添加波浪线,偶然发现了 Font.Underline
和 Font.UnderlineColor
。我将其设置在一个词的范围内,它似乎提供了我想要引起注意的视觉刺激。但是有一个问题。我添加的每个下划线或我更改的下划线颜色都会向撤消堆栈添加一个撤消操作。
我不希望发生这种情况,或者我想要一种方法来从堆栈中弹出我刚刚在代码中执行的操作。目的是让用户能够使用 CTRL+Z 删除他更改的 text,而不影响我的语言分析结果。
我该怎么做?
不幸的是,这个问题似乎没有简单的解决方案。据我所见,您有两个选择:
- 您可以使用 Document.UndoClear 清除整个撤消堆栈。但是,这对用户来说不是很友好,因为之前的所有操作都不再位于撤消列表中。
- 与 UndoRecord class 一起工作。在调用
StartCustomRecord
和 EndCustomRecord
之间,代码中的所有操作只会在撤消堆栈中生成一项。 CTRL+Z 仍然会影响你的语言分析,但整个撤消堆栈不会像以前那样被污染。
我知道这不是你想要的,but even Microsoft MVPs don't have a better solution。
我偶然发现了这个问题,它问的是完全相同的事情:
Prevent actions to be added to the word undo redo OR Remove actions from the undo redo CommandBarComboBox
正如@Manu 指出的那样,在 MSDN 也有人问过同样的问题,答案是:
The UndoClear method will empty the list. That's the best you can do.
这里也有类似的问题Word VSTO override CTRL+Z / CTRL+Y
这表明 Microsoft.Office.Interop.Word.UndoRecord
路由或 AddIns 中的 MessageHooks。
经过更多研究后,我注意到此线程末尾的一个好主意:MSDN Draw my own squigglies on Word document 您可以在其中跟踪您的操作,然后在撤消和重做操作中跳过它们。
这是执行 "transactional undo/redo's" Can I create an undo transaction in Word or Excel? (VSTO) 的优秀代码示例。除了一个大问题外,您可以在 VSTO 中执行相同的方法,正如 Dirk Vollmar 在他的回答中指出的那样:
I don't think that overwriting built-in Word commands is possible using VSTO alone, though
我在 VSTO 中使用键盘挂钩事件覆盖了一些 built-in 命令来拦截命令:How to perform .Onkey Event in an Excel Add-In created with Visual Studio 2010?
但是我不确定您是否可以重新创建功能区来拦截按钮命令。更具体地说,撤消和重做是功能区 UI 中的 built-in 库,您无法使用 built-in 功能区库执行任何操作。在 2010 等版本中,Undo/Redo 按钮位于标题栏中 - 您不能 add/edit buttons on the title bar using VSTO:
因此,如果您担心捕获按钮命令(我认识的每个人都使用 Ctrl+Z & Y),您可以注入 VBA 代码来获得访问权限EditUndo
和 EditRedo
事件,例如:
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) 三个月后回答。他使用了一个隐藏文档,并在需要时将其放置在真实文档中,以便将任意数量的 VSTO 操作一次撤消。
仍然没有解决阻止操作被记录在撤消历史记录中的问题。
我确实尝试过使用注册表项将 UndoHistory 限制为 0 并将其重置回 100(以便在添加操作时禁用历史记录),但它似乎仅适用于 Excel
https://support.microsoft.com/en-gb/kb/211922
可能有一个未记录的注册表项可以完全禁用 Undo/Redo 历史记录,但它只会在启动时由 Word 读取。我认为包含数字的 UndoHistory 键会在每个 Undo/Redo 之前被读取,但这种方法完全没有运气。
这不是一个容易解决的问题,有很大的局限性,所以可能更容易:
a) 接受你的 spell/grammer 检查器 Add-In 包含在 Undo/Redo 列表中(失败)。
b) 确定 line/text 在屏幕上的位置并显示突出显示问题的透明工具提示。这比看起来要难得多,也不理想,这里有两个很好的答案可以指导您使用此方法:Detecting text changes in Word 2016 from VSTO add-in or a much simpler approach to detect XY positions from this Microsoft email thread: 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) 仅通过键盘 和交易 Undo/Redo 的 捕获 Undo/Redo 事件,并让用户看到原子 Undo/Redo 的事件使用按钮。删除 Undo/Redo 按钮会非常不可靠,这会导致大量 我的“撤消”按钮不见了? 支持案例。所以不要这样做,如果你很好奇,可以从“.qat”文件中完成快速访问工具栏自定义。参考:https://support.microsoft.com/en-us/kb/926805
d) 使用 Mouse Hook 并检测何时单击 Undo/Redo 按钮。这是连接鼠标的代码,请注意,这不会很好地与公司 Anti-Virus 产品一起使用,我不推荐它:https://blogs.msdn.microsoft.com/andreww/2009/02/24/message-hooks-in-add-ins/ or https://github.com/gmamaladze/globalmousekeyhook。
e) 尝试拦截原始 windows 消息,例如 Excel CustomTaskPane with WebBrowser control - keyboard/focus issues just beware as per my comment referencing BUG: Cant choose dates on a DatePicker that fall outside a floating VSTO Add-In Office 中的消息泵有时会表现出奇怪的行为。
我正在开发一个实时语言分析工具,它需要在 Word 2016 中使用 VSTO 加载项突出显示单词以引起作者的注意,该加载项使用 C# 在 .NET4.6.1 中编写。想一想 grammar/spelling 检查,它会在单词下方添加一条波浪线,告诉您该单词有语法或拼写错误。我正在为我自己定义的一些规则添加类似的功能。
我四处搜索添加波浪线,偶然发现了 Font.Underline
和 Font.UnderlineColor
。我将其设置在一个词的范围内,它似乎提供了我想要引起注意的视觉刺激。但是有一个问题。我添加的每个下划线或我更改的下划线颜色都会向撤消堆栈添加一个撤消操作。
我不希望发生这种情况,或者我想要一种方法来从堆栈中弹出我刚刚在代码中执行的操作。目的是让用户能够使用 CTRL+Z 删除他更改的 text,而不影响我的语言分析结果。
我该怎么做?
不幸的是,这个问题似乎没有简单的解决方案。据我所见,您有两个选择:
- 您可以使用 Document.UndoClear 清除整个撤消堆栈。但是,这对用户来说不是很友好,因为之前的所有操作都不再位于撤消列表中。
- 与 UndoRecord class 一起工作。在调用
StartCustomRecord
和EndCustomRecord
之间,代码中的所有操作只会在撤消堆栈中生成一项。 CTRL+Z 仍然会影响你的语言分析,但整个撤消堆栈不会像以前那样被污染。
我知道这不是你想要的,but even Microsoft MVPs don't have a better solution。
我偶然发现了这个问题,它问的是完全相同的事情: Prevent actions to be added to the word undo redo OR Remove actions from the undo redo CommandBarComboBox
正如@Manu 指出的那样,在 MSDN 也有人问过同样的问题,答案是:
The UndoClear method will empty the list. That's the best you can do.
这里也有类似的问题Word VSTO override CTRL+Z / CTRL+Y
这表明 Microsoft.Office.Interop.Word.UndoRecord
路由或 AddIns 中的 MessageHooks。
经过更多研究后,我注意到此线程末尾的一个好主意:MSDN Draw my own squigglies on Word document 您可以在其中跟踪您的操作,然后在撤消和重做操作中跳过它们。
这是执行 "transactional undo/redo's" Can I create an undo transaction in Word or Excel? (VSTO) 的优秀代码示例。除了一个大问题外,您可以在 VSTO 中执行相同的方法,正如 Dirk Vollmar 在他的回答中指出的那样:
I don't think that overwriting built-in Word commands is possible using VSTO alone, though
我在 VSTO 中使用键盘挂钩事件覆盖了一些 built-in 命令来拦截命令:How to perform .Onkey Event in an Excel Add-In created with Visual Studio 2010? 但是我不确定您是否可以重新创建功能区来拦截按钮命令。更具体地说,撤消和重做是功能区 UI 中的 built-in 库,您无法使用 built-in 功能区库执行任何操作。在 2010 等版本中,Undo/Redo 按钮位于标题栏中 - 您不能 add/edit buttons on the title bar using VSTO:
因此,如果您担心捕获按钮命令(我认识的每个人都使用 Ctrl+Z & Y),您可以注入 VBA 代码来获得访问权限EditUndo
和 EditRedo
事件,例如:
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) 三个月后回答。他使用了一个隐藏文档,并在需要时将其放置在真实文档中,以便将任意数量的 VSTO 操作一次撤消。
仍然没有解决阻止操作被记录在撤消历史记录中的问题。
我确实尝试过使用注册表项将 UndoHistory 限制为 0 并将其重置回 100(以便在添加操作时禁用历史记录),但它似乎仅适用于 Excel https://support.microsoft.com/en-gb/kb/211922
可能有一个未记录的注册表项可以完全禁用 Undo/Redo 历史记录,但它只会在启动时由 Word 读取。我认为包含数字的 UndoHistory 键会在每个 Undo/Redo 之前被读取,但这种方法完全没有运气。
这不是一个容易解决的问题,有很大的局限性,所以可能更容易:
a) 接受你的 spell/grammer 检查器 Add-In 包含在 Undo/Redo 列表中(失败)。
b) 确定 line/text 在屏幕上的位置并显示突出显示问题的透明工具提示。这比看起来要难得多,也不理想,这里有两个很好的答案可以指导您使用此方法:Detecting text changes in Word 2016 from VSTO add-in or a much simpler approach to detect XY positions from this Microsoft email thread: 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) 仅通过键盘 和交易 Undo/Redo 的 捕获 Undo/Redo 事件,并让用户看到原子 Undo/Redo 的事件使用按钮。删除 Undo/Redo 按钮会非常不可靠,这会导致大量 我的“撤消”按钮不见了? 支持案例。所以不要这样做,如果你很好奇,可以从“.qat”文件中完成快速访问工具栏自定义。参考:https://support.microsoft.com/en-us/kb/926805
d) 使用 Mouse Hook 并检测何时单击 Undo/Redo 按钮。这是连接鼠标的代码,请注意,这不会很好地与公司 Anti-Virus 产品一起使用,我不推荐它:https://blogs.msdn.microsoft.com/andreww/2009/02/24/message-hooks-in-add-ins/ or https://github.com/gmamaladze/globalmousekeyhook。
e) 尝试拦截原始 windows 消息,例如 Excel CustomTaskPane with WebBrowser control - keyboard/focus issues just beware as per my comment referencing BUG: Cant choose dates on a DatePicker that fall outside a floating VSTO Add-In Office 中的消息泵有时会表现出奇怪的行为。