C#:Excel 2007 插件,如何挂钩 Windows 激活和停用事件
Posted
技术标签:
【中文标题】C#:Excel 2007 插件,如何挂钩 Windows 激活和停用事件【英文标题】:C#: Excel 2007 Addin, How to Hook Windows Activate and Deactivate Events 【发布时间】:2009-07-03 12:36:35 【问题描述】:我正在编写一个 Excel 2007 插件。使用 VS2008 和 .net 3.5,C#。
我捕获了 Microsoft.Office.Interop.Excel.Application 的 WindowActivate 和 WindowDeActivate 事件。
令人惊讶的是,WindowActivate 和 Deactivate 仅在我在两个 Excel 窗口之间切换时触发。如果我切换到记事本,我希望 Deactivate 被触发,但它没有发生。如果我切换到 excel 窗口,从记事本以同样的方式,我希望激活被触发,但它没有发生。看起来该行为表明窗口是 MDI 子窗口。
现在我要做的是获取 Excel 主窗口的 HWnd 并使用 dllimport 功能挂钩窗口激活和停用。
谁能指导我这个。
问候
【问题讨论】:
【参考方案1】:我在编写 Excel 插件时解决了类似的问题。不需要 dll 导入。我使用 System.Windows.Forms.NativeWindow 类解决了这个问题。
首先,我创建了我自己的类继承自 NativeWindow 类,并在其中声明了两个事件 Activated 和 Deactivate,最后重写了 WndProc() 方法以在将消息 WM_ACTIVATE 传递给 WndProc 方法时引发这些事件。根据“Message”参数,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
希望对你有帮助。
【讨论】:
这太棒了,你知道在 Word/PowerPoint 中有没有办法做到这一点?更具体地说,这些应用程序是否有 .Hwnd 类型的属性?【参考方案2】:最后我找到了一个解决方案..它只适用于激活/停用。 这不是完美的方法。但我没有找到任何好的选择。 此方法使用轮询。我必须每隔 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;
【讨论】:
以上是关于C#:Excel 2007 插件,如何挂钩 Windows 激活和停用事件的主要内容,如果未能解决你的问题,请参考以下文章
设置 Font.Color 时 Excel 2007 VSTO 插件异常