2009-07-03 11 views
2

私はExcel 2007アドインを作成しています。 VS2008と.net 3.5、C#を使用しています。C#:Excel 2007アドイン、Windowsをフックする方法イベントのアクティブ化と非アクティブ化

Microsoft.Office.Interop.Excel.ApplicationのWindowActivateイベントとWindowDeActivateイベントを捕まえました。

WindowActivateとDeactivateは、2つのExcel Windowsを切り替えるときにトリガすることに驚きました。私はメモ帳に切り替えると、私はDeactivateが発生すると予想しますが、それは起こっていません。同じように私がウィンドウをExcelに切り替えると、私はActivateが引き起こされるが、起こっていないと思う。動作は、ウィンドウがMDI-Childウィンドウであることを示しているようです。

今私がしたいのは、ExcelのメインウィンドウのHWndを取得し、dllimport機能を使用してWindow ActivateとDeactivateをフックすることです。

誰もが私にこれをガイドできますか?

よろしくです。

答えて

6

Excelアドインを書くときに同様の問題を解決しました。 DLLのインポートは必要ありません。私はSystem.Windows.Forms.NativeWindowクラスを使ってこの問題を解決しました。

最初に、NativeWindowクラスから継承したクラスを作成し、ActivatedとDeactivateの2つのイベントを宣言し、WndProc()メソッドをオーバーライドしてWMnACrocメソッドに渡しました。 "メッセージ"パラメータによると、WParmはExcelウィンドウが有効または無効になっています。

public class ExcelWindow: NativeWindow 
{ 
    public const int WM_ACTIVATED = 0x0006; 

    public ExcelWindow():base(){} 

    //events 
    public event EventHandler Activated; 
    public event EventHandler Deactivate; 

    //catching windows messages 
    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg== WM_ACTIVATED) 
     { 
      if (m.WParam.ToInt32() == 1) 
      { 
       //raise activated event 
       if (Activated!=null) 
       { 
        Activated(this, new EventArgs()); 
       } 
      } 
      else if (m.WParam.ToInt32() == 0) 
      { 
       //raise deactivated event 
       if (Deactivate!=null) 
       { 
        Deactivate(this, new EventArgs()); 
       } 
      } 
     } 
     base.WndProc(ref m); 
    } 
} 

は、その後、私は私のアドインクラスフィールド「ExcelWindow myExcelWindow」で行われた、私のアドインのOnConnectionにメソッドに次のコードを追加しました:

ExcelWindow myExcelWindow; 
void Extensibility.IDTExtensibility2.OnConnection(object application, Extensibility.ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) 
{ 
    excel = application as Excel.Application; 
    myExcelWindow = new ExcelWindow(); 
    myExcelWindow.AssignHandle(new IntPtr(excel.Hwnd)); 
    myExcelWindow.Activated += new EventHandler(myExcelWindow_Activated); 
    myExcelWindow.Deactivate += new EventHandler(myExcelWindow_Deactivate); 

    //addin code here 

} 

void myExcelWindow_Activated(object sender, EventArgs e) 
{ 
    //do some stuff here 
} 
void myExcelWindow_Deactivate(object sender, EventArgs e) 
{ 
    //do some stuff here 
} 

私は、これはあなたを助けることを願っています。

+0

これは素晴らしいことですが、Word/PowerPointでこれを行う方法があるかどうか知っていますか?具体的には、それらのアプリの.Hwndタイプの属性がありますか? – Tom

0

最後に、解決策を見つけました。これは、有効化/無効化のみです。 これは完全な方法ではありません。しかし、私は良い選択肢が見つかりませんでした。 このメソッドはポーリングを使用します。私はフォーカスをチェックイン/アウトするために10ミリ秒毎に次の関数を呼び出さなければなりません。

public static bool ApplicationIsActivated() 
    { 
     var activatedHandle = GetForegroundWindow(); 
     if (activatedHandle == IntPtr.Zero) 
     { 
      return false;  // No window is currently activated 
     } 

     var procId = Process.GetCurrentProcess().Id; 
     int activeProcId; 
     GetWindowThreadProcessId(activatedHandle, out activeProcId); 

     return activeProcId == procId; 
    } 
関連する問題