InteropServices.ComException при закрытии документа после добавления нового документа с ленты - PullRequest
0 голосов
/ 31 мая 2019

Я пытаюсь написать надстройку Word, которая использует CustomTaskPane.Я могу создать CustomTaskPane и синхронизировать его между открытыми документами, и я не получаю ошибок, пока использую меню Word, когда добавляю новый или открываю существующий документ.Однако, если я добавляю новый документ через кнопку ленты, которая вызывает Globals.ThisAddIn.Application.Documents.Add(), я начинаю получать исключения COMException при закрытии документов.

Проблема возникает, когда я добавляю новый документ, используя событие нажатия кнопки в CtpMainRibbon.cs вместо меню Word, свойство Globals.ThisAddIn.Application.ActiveWindow становится недействительным после закрытия открытого документа.При получении для свойства CurrentCustomTaskPane ActiveWindow возвращает System.Runtime.InteropServices.COMException: 'This command is not available because no document is open.' при Microsoft.Office.Interop.Word.ApplicationClass.get_ActiveWindow().Я искал ошибку, но большинство проблем возникает, когда люди пытаются использовать Word Interop на сервере или на странице ASP.net, но я получаю это на своем компьютере разработчика.Кроме того, если я использую метод Document.Add(), состояние проверки кнопки «Показать» отображается некорректно (если у меня открыта панель CustomTaskPane в одном документе, затем нажмите кнопку «Создать документ» на ленте, кнопка «Показать» нового документа будет проверена дажехотя панель задач не отображается. Если я переключаюсь в другое окно, а затем снова переключаюсь на новый документ, проверяется статус кнопки, когда она не проверяется.

Я попытался перебрать Globals.ThisAddIn.CustomTaskPanes, чтобы проверить,есть несоответствие между свойствами ctp.Window.Hwnd, но, насколько я могу судить, каждый ctp.Window имеет свой уникальный Hwnd. Я получаю сообщение, даже когда открыты другие документы и окна.

Вот соответствующие файлы кода 2. Я использую CurrentCustomTaskPane, чтобы кнопка ленты могла синхронизироваться со свойством Visible панели задач.

ThisAddIn.cs:

private const string TaskPaneTitle = "Main Custom Task Panel";
public static CustomTaskPane CurrentCustomTaskPane
{
    get
    {
        return Globals.ThisAddIn.CustomTaskPanes
              .FirstOrDefault(ctp => !ctp.Control.IsDisposed && 
                Globals.ThisAddIn.Application.ActiveWindow != null && 
                ReferenceEquals(ctp.Window, Globals.ThisAddIn.Application.ActiveWindow) && 
                ctp.Title == TaskPaneTitle);
    }
}

private void InternalStartup()
{
    Startup += ThisAddIn_Startup;
    Shutdown += ThisAddIn_Shutdown;
}

private void ThisAddIn_Startup(object sender, EventArgs e)
{
    if (Application.Documents.Count > 0)
    AddNewTaskPane(Application.ActiveDocument);
    Word.ApplicationEvents4_Event event4 = Application;
    event4.NewDocument += OnNewDocument;
    event4.DocumentOpen += OnDocumentOpen;
    event4.WindowActivate += ApplicationOnWindowActivate;
}

private static void ThisAddIn_Shutdown(object sender, EventArgs e) { }

private void OnNewDocument(Word.Document doc) => AddNewTaskPane(doc);

private void OnDocumentOpen(Word.Document doc) => AddNewTaskPane(doc);

private void ApplicationOnWindowActivate(Word.Document doc, Word.Window wn) => SetRibbonButtonToggle();

private void AddNewTaskPane(Word._Document doc)
{
    RemoveOrphanedTaskPanes();
    CustomTaskPane newPane = CustomTaskPanes.Add(new MainCustomTaskPanel(), TaskPaneTitle, doc.ActiveWindow);
    newPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionLeft;
    newPane.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
    newPane.Width = 700;
    newPane.VisibleChanged += TaskPaneOnVisibleChanged;
}

private void TaskPaneOnVisibleChanged(object sender, EventArgs e) => SetRibbonButtonToggle();

private void SetRibbonButtonToggle()
{
    if (CurrentCustomTaskPane != null)
    Globals.Ribbons.CtpWordRibbon.RbnButtonShowTaskPane.Checked = CurrentCustomTaskPane.Visible;
}

private void RemoveOrphanedTaskPanes()
{
    foreach (CustomTaskPane ctp in CustomTaskPanes)
    {
        if (ctp.Window == null || ctp.Control.IsDisposed)
            CustomTaskPanes.Remove(ctp);
    }
}

CtpWordRibbon.cs:

private void RbnButtonShowCtp_Click(object sender, RibbonControlEventArgs e)
{
    if (ThisAddIn.CurrentCustomTaskPane != null)
        ThisAddIn.CurrentCustomTaskPane.Visible = ((RibbonToggleButton)sender).Checked;
}

private void RbnButtonCreateNewDocument_Click(object sender, RibbonControlEventArgs e)
{
    Globals.ThisAddIn.Application.Documents.Add();
}

Очевидно, что есть разница между тем, как Word обрабатывает добавление нового документа через меню Word и добавление его с помощью Application.Documents.Add() метод.Как я могу проверить, будет ли свойство ActiveDocument вызывать исключение COMException, прежде чем я на самом деле получу к нему доступ?Или есть лучший способ создать новый документ через ленту или обработать событие OnNewDocument, чтобы я не получил эти ошибки?

...