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 が返されることはありません。
また、現在のロジックを使用して遭遇する可能性のある他の問題はありますか? 複数のドキュメントの複数の作業ウィンドウを管理する一般的な方法は何ですか?