13

Visual Studio 2008 で VSTO を使用して Word 2007-2010 アドインを開発しています。私のアドインでは、開いている Word ドキュメントごとにカスタム作業ウィンドウが必要です。基本的に、ドキュメントごとに作業ウィンドウを作成し、ドキュメント ウィンドウに適切な作業ウィンドウを表示し、ドキュメントを閉じるときに何かを実行してから、作業ウィンドウとその作業ウィンドウへのすべての参照を削除する必要があります。

これは私がこれまでに行ったことです:

タスク ペインの作成

次のように、新しいドキュメント、開いたドキュメント、または既存のオンロード ドキュメントごとにカスタム タスク ペインを作成します。

((ApplicationEvents4_Event) Application).NewDocument += CreateTaskPaneWrapper;
Application.DocumentOpen += CreateTaskPaneWrapper;
foreach (Document document in Application.Documents)
{
    CreateTaskPaneWrapper(document);
}

CreateTaskPaneWrapper メソッドで、ドキュメントの作業ウィンドウが既に存在するかどうかを Dictionary<Document, TaskPaneWrapper> で確認します。これを行うのは、既に開いているドキュメントを開こうとすると open イベントが発生するためです。存在しない場合は、新しい TaskPaneWrapper クラスを作成します。そのコンストラクターで、新しい作業ウィンドウを作成し、CustomTaskPanes コレクションに追加します。

Globals.ThisAddIn.CustomTaskPanes.Add(taskPane, "Title");

MSDN によると、これにより作業ウィンドウが現在アクティブなウィンドウに関連付けられます。

タスク ペインのシャットダウン

Document.Close と Application.DocumentBeforeClose の両方のイベントは、ユーザーがドキュメントを閉じる確認を行う前に発生するため、私には適していません。そこで、次のように TaskPaneWrapper クラスで Microsoft.Office.Tools.Word.Document.Shutdown イベントを使用します。

_vstoDocument = document.GetVstoObject();
_vstoDocument.Shutdown += OnShutdown;

private void OnShutdown(object sender, EventArgs eventArgs)
{
    Globals.ThisAddIn.CustomTaskPanes.Remove(_taskPane);
    //additional shutdown logic
}

これらはすべてうまく機能しているようで、作業ウィンドウが作成され、対応するウィンドウにバインドされ、正常に削除されます。ただし、まだ問題が 1 つあります。Word を起動すると、空白の文書が開きます。次に、空白のドキュメントを変更せずに既存のドキュメントを開くと、Document.Close、Application.DocumentBeforeClose、および Microsoft.Office.Tools.Word.Document.Shutdown イベントが発生することなく、空白のドキュメントとそのウィンドウが削除されます。OnShutdown は呼び出されず、空白のドキュメントの作業ウィンドウは削除されないため、次のドキュメント ウィンドウには 2 つの作業ウィンドウ (非常に新しい作業ウィンドウと最初の (孤立した) 作業ウィンドウ) が含まれます。この孤立した作業ウィンドウを削除するにはどうすればよいですか? 削除されたドキュメントまたはウィンドウ参照にアクセスすると、COMException ("オブジェクトが削除されました") がスローされます。私は一時的にこのハックを使用しています:

//A property in my TaskPaneWrapper class
public bool IsWindowAlive()
{
    try
    {
        var window = _vstoDocument.ActiveWindow;
        return true;
    }
    catch (COMException)
    {
        return false;
    }
}

CreateTaskPaneWrapper メソッドで、既存のすべてのラッパーについてこのプロパティをチェックし、プロパティが false のラッパーをシャットダウンします。もちろん、例外をキャッチするのはいくらかコストがかかります。この解決策はかなりハックなので、もっと良い方法はないかと考えていました。この質問では CustomTaskPane.Window プロパティが null かどうかチェックされますが、null が返されることはありません。

また、現在のロジックを使用して遭遇する可能性のある他の問題はありますか? 複数のドキュメントの複数の作業ウィンドウを管理する一般的な方法は何ですか?

4

3 に答える 3

6

MSDNのこの回答

CreateTaskPaneWrapper を呼び出す前に、DocumentOpen イベント ハンドラーから次のメソッドを呼び出すことにより、既存のドキュメントを開いた後に孤立した作業ウィンドウを事後的にクリーンアップする代わりに、事前にクリーンアップすることができます。このコードは、アドインに属する各カスタム作業ウィンドウをループ処理します。作業ウィンドウにウィンドウが関連付けられていない場合、コードは作業ウィンドウをコレクションから削除します。

private void RemoveOrphanedTaskPanes()
{
    for (int i = Globals.ThisAddIn.CustomTaskPanes.Count; i > 0; i--)
    {
        CustomTaskPanes ctp = Globals.ThisAddIn.CustomTaskPanes[i - 1];
        if (ctp.Window == null)
        {
            this.CustomTaskPanes.Remove(ctp);
        }
    }
}

private void Application_DocumentOpen(Word.Document Doc)
{
    RemoveOrphanedTaskPanes();
    CreateTaskPaneWrapper(document);
}
于 2016-01-03T22:20:44.763 に答える
6

この問題については、MSDN の記事「Managing Task Panes in Multiple Word and InfoPath Documents 」で詳しく説明されています。

孤立した CTP (つまり、ウィンドウが接続されていないもの) を削除するメソッドを作成する必要があります。

私はこの記事に従い、孤児を削除する CustomTaskPane マネージャーを正常に実装しました。

于 2014-08-20T10:36:53.803 に答える
0

試してみること::

  1. DocumentNew イベントと DocumentOpen イベントで "Word.Application.Documents.Count" をチェックして、実際に開いているドキュメントを追跡できます。

  2. ドキュメントが既に開いているかどうかを確認するには (おそらく、アクティブなドキュメントを再度開くことに関連しています)、開いているドキュメントの辞書を使用できます。キーは一意のドキュメント名にすることができます。

  3. IsWindowAlive() メソッドの代わりに、次のように Disposed-Event をキャッチできます

_vstoDocument.Disposed += _vstoDocument_Disposed;

        void _vstoDocument_Disposed(object sender, EventArgs e)
        {
            //Remove from dictionary of open documents 
        }
于 2014-06-10T09:40:48.477 に答える