VSTOを使って、Officeのメニューバー・右クリックメニューに独自の項目を追加できるのですが、この子の挙動がどうもおかしい。 メニューを選択しても設定したコールバック関数が呼ばれない という謎のケースに遭遇。 何がどうなってるの…
// C# コードイメージ // ctrls に メニューを1個追加する private void AddMenu(Office.CommandBarControls ctrls) { object missing = System.Type.Missing; Office.CommandBarButton button; button = (Office.CommandBarButton)ctrls.Add(Office.MsoControlType.msoControlButton, missing, missing, missing, false); button.Caption = "かしら"; button.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(button_Click); } private void button_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault) { MessageBox.Show("からし!!"); }
CommandBarControls.Add() によってメニュー項目が追加され、クリック時の挙動を Click イベントにセットしています。
見た目は正しいんです。 そして、動くんです…が、動かないんです。 私が把握している限り、Excel 2003/2007 で全く動かない、Word 2003 / PowerPoint 2003 だと動きはするんです…が、何回か項目を選択しているといつの間にかコールバック関数が呼ばれなくなります。 動いてたのに動かなくなるとかどういう事なの……
原因
Webで調べてみたところ、原因は……
button がガベコレされちゃうから反応なくなっちゃうよ!
という話。 ………ってええええ ('A`) VSTO側が CommandBarControls.Add() の中で創った CommandBarButton インスタンス保持していてごにょごにょしてるんじゃないのコレー!? インスタンス管理してるから、VSTOフレームワークの中から Click イベント呼んでるんじゃないのコレー!?
つまりは、
という話でした。「こんなの絶対おかしいよ」
対策
CommandBarButton を メンバ変数として持たせて、ガベコレの魔の手から救ってあげましょう。
// C# コードイメージ // クラスのメンバ変数とする private Office.CommandBarButton button; // ctrls に メニューを1個追加する private void AddMenu(Office.CommandBarControls ctrls) { object missing = System.Type.Missing; // メンバ変数に保持しておいてあげるのぉぉお"お"お" !!! button = (Office.CommandBarButton)ctrls.Add(Office.MsoControlType.msoControlButton, missing, missing, missing, false); button.Caption = "かしら"; button.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(button_Click); } private void button_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault) { MessageBox.Show("からし!!"); }
それだけ。
…エー ('A`)
というわけで
日本語ベースの情報源が無かったように思えたので書いてみた