在文档不受保护后访问受保护的组件
Accessing protected components after a document becomes unprotected
我想在 DocumentOpen 事件中修改文档,在适当的地方向现有文本添加一些内容控件并更改格式。这工作正常,但在受保护文档不受保护后触发 DocumentOpen 事件时变得更加复杂:
单击"Enable Editing" 开始"unprotecting" 一个文档的处理,我定义的DocumentOpen 事件此时触发。因为该事件似乎在默认未受保护的 window 打开之前触发,但是,创建内容控件仍然被认为是不可用的。当文档处于不受保护的过程中时不会成功的简单示例:
private void ThisAddIn_Startup(object sender, EventArgs e)
{
Application.DocumentOpen += application_DocumentOpen;
}
private void application_DocumentOpen(Document doc)
{
doc.ContentControls.Add(
WdContentControlType.wdContentControlRichText,
doc.Range(doc.Content.Start, doc.Content.End - 1));
}
有什么方法可以加快取消保护过程,也就是说,仍然能够执行我的代码?或者当文档编辑可用时可预见地触发的另一个事件?我查看了与保护模式相关的触发事件 in the Microsoft documentation,但没有看到任何适合我需要的事件。不幸的是,Document.Unprotect()
和更改 Document.ActiveWindow.View.Type
也没有用,因为 "Protected Mode" 似乎是完全不同的、不可编辑的 window。要求在打开文档时或之后尽快进行这些格式修改。
它不是很漂亮,但我最终通过定义一个包含我要执行的代码的委托解决了这个问题,与每个文档的容器相关联,并检查委托是否可以在内部执行 Application.WindowActivate
:
public class DocumentContainer
{
public Action ProtectedDeferredExecution { get; set; }
public DocumentContainer(Action deferred)
{
ProtectedDeferredExecution = deferred;
}
}
public partial class ThisAddIn
{
private Dictionary<Document, DocumentContainer> DocumentContainerDict { get; set; }
private void ThisAddIn_Startup(object sender, EventArgs e)
{
DocumentContainerDict = new Dictionary<Document, DocumentContainer>();
Application.WindowActivate += application_WindowActivate;
Application.DocumentOpen += application_DocumentOpen;
Application.DocumentBeforeClose += application_DocumentClose;
}
private void application_DocumentOpen(Document doc)
{
// define code that is unsafe when document is protected
Action initialization = () =>
{
doc.ContentControls.Add(
WdContentControlType.wdContentControlRichText,
doc.Range(doc.Content.Start, doc.Content.End - 1));
};
// if the current window isn't "protected", able to execute the unsafe code
if (Application.ActiveProtectedViewWindow == null)
{
initialization();
initialization = null;
}
// send either the unsafe delegate or null to the constructor
DocumentContainerDict.Add(doc, new VersioningDocumentContainer(initialization));
}
private void application_WindowActivate(Document doc, Window wn)
{
// skip execution if the window is still protected or isn't the view we want
if (wn.View.Type != WdViewType.wdPrintView || Application.ActiveProtectedViewWindow != null)
{
return;
}
DocumentContainer container;
// find the document container, if any, and the delegate to execute
if (DocumentContainerDict.TryGetValue(doc, out container)
&& container.ProtectedDeferredExecution != null)
{
container.ProtectedDeferredExecution();
container.ProtectedDeferredExecution = null;
}
}
// clean up
private void application_DocumentClose(Document doc, ref bool cancel)
{
DocumentContainerDict.Remove(doc);
}
}
其他元数据也可以在此容器中轻松定义(这就是我使用它的目的),因此我为使用加载项创建的每个文档创建一个。
我想在 DocumentOpen 事件中修改文档,在适当的地方向现有文本添加一些内容控件并更改格式。这工作正常,但在受保护文档不受保护后触发 DocumentOpen 事件时变得更加复杂:
单击"Enable Editing" 开始"unprotecting" 一个文档的处理,我定义的DocumentOpen 事件此时触发。因为该事件似乎在默认未受保护的 window 打开之前触发,但是,创建内容控件仍然被认为是不可用的。当文档处于不受保护的过程中时不会成功的简单示例:
private void ThisAddIn_Startup(object sender, EventArgs e)
{
Application.DocumentOpen += application_DocumentOpen;
}
private void application_DocumentOpen(Document doc)
{
doc.ContentControls.Add(
WdContentControlType.wdContentControlRichText,
doc.Range(doc.Content.Start, doc.Content.End - 1));
}
有什么方法可以加快取消保护过程,也就是说,仍然能够执行我的代码?或者当文档编辑可用时可预见地触发的另一个事件?我查看了与保护模式相关的触发事件 in the Microsoft documentation,但没有看到任何适合我需要的事件。不幸的是,Document.Unprotect()
和更改 Document.ActiveWindow.View.Type
也没有用,因为 "Protected Mode" 似乎是完全不同的、不可编辑的 window。要求在打开文档时或之后尽快进行这些格式修改。
它不是很漂亮,但我最终通过定义一个包含我要执行的代码的委托解决了这个问题,与每个文档的容器相关联,并检查委托是否可以在内部执行 Application.WindowActivate
:
public class DocumentContainer
{
public Action ProtectedDeferredExecution { get; set; }
public DocumentContainer(Action deferred)
{
ProtectedDeferredExecution = deferred;
}
}
public partial class ThisAddIn
{
private Dictionary<Document, DocumentContainer> DocumentContainerDict { get; set; }
private void ThisAddIn_Startup(object sender, EventArgs e)
{
DocumentContainerDict = new Dictionary<Document, DocumentContainer>();
Application.WindowActivate += application_WindowActivate;
Application.DocumentOpen += application_DocumentOpen;
Application.DocumentBeforeClose += application_DocumentClose;
}
private void application_DocumentOpen(Document doc)
{
// define code that is unsafe when document is protected
Action initialization = () =>
{
doc.ContentControls.Add(
WdContentControlType.wdContentControlRichText,
doc.Range(doc.Content.Start, doc.Content.End - 1));
};
// if the current window isn't "protected", able to execute the unsafe code
if (Application.ActiveProtectedViewWindow == null)
{
initialization();
initialization = null;
}
// send either the unsafe delegate or null to the constructor
DocumentContainerDict.Add(doc, new VersioningDocumentContainer(initialization));
}
private void application_WindowActivate(Document doc, Window wn)
{
// skip execution if the window is still protected or isn't the view we want
if (wn.View.Type != WdViewType.wdPrintView || Application.ActiveProtectedViewWindow != null)
{
return;
}
DocumentContainer container;
// find the document container, if any, and the delegate to execute
if (DocumentContainerDict.TryGetValue(doc, out container)
&& container.ProtectedDeferredExecution != null)
{
container.ProtectedDeferredExecution();
container.ProtectedDeferredExecution = null;
}
}
// clean up
private void application_DocumentClose(Document doc, ref bool cancel)
{
DocumentContainerDict.Remove(doc);
}
}
其他元数据也可以在此容器中轻松定义(这就是我使用它的目的),因此我为使用加载项创建的每个文档创建一个。