2009-07-03 92 views
2

我正在寫一個Excel 2007插件。使用VS2008和.NET 3.5,C#。C#:Excel 2007 Addin,如何掛鉤Windows激活和停用事件

我捕獲了Microsoft.Office.Interop.Excel.Application的WindowActivate和WindowDeActivate事件。

當我在兩個Excel窗口之間切換時,知道WindowActivate和Deactivate僅觸發器時感到驚訝。如果我切換到記事本,我期望停用被觸發,但不會發生。同樣的方式從記事本,如果我切換到Excel窗口,我期望激活被觸發,但它沒有發生。它看起來像行爲表明窗口是MDI-Child窗口。

現在我想要做的是獲取Excel的主窗口的HWnd和鉤子窗口激活和使用dllimport功能停用。

任何人都可以在此指導我。

Regards

回答

6

我在編寫Excel插件時解決了類似的問題。沒有dll導入是必要的。我使用System.Windows.Forms.NativeWindow類解決了這個問題。

起初,我讓自己的類繼承自NativeWindow類,並在其中聲明瞭兩個事件Activated和Deactivate,並在WM_ACTIVATE消息傳遞給WndProc方法時最終重寫WndProc()方法以產生這些事件。根據「消息」參數,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 2013-10-03 20:44:22

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; 
    }