2009-07-03 57 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; 
    }