2

我正在编写一个 Excel 2007 插件。使用 VS2008 和 .net 3.5,C#。

我发现了 Microsoft.Office.Interop.Excel.Application 的 WindowActivate 和 WindowDeActivate 事件。

令人惊讶的是,WindowActivate 和 Deactivate 仅在我在两个 Excel Windows 之间切换时触发。如果我切换到记事本,我希望 Deactivate 被触发,但它没有发生。如果我切换到 excel 窗口,从记事本以同样的方式,我希望激活被触发,但它没有发生。看起来该行为表明窗口是 MDI 子窗口。

现在我要做的是获取 Excel 主窗口的 HWnd 并使用 dllimport 功能挂钩窗口激活和停用。

任何人都可以在这方面指导我。

问候

4

2 回答 2

6

我在编写 Excel 插件时解决了类似的问题。不需要 dll 导入。我使用 System.Windows.Forms.NativeWindow 类解决了这个问题。

起初,我创建了我自己的类继承自 NativeWindow 类,并在其中声明了两个事件 Activated 和 Deactivate,最后重写了 WndProc() 方法以在将消息 WM_ACTIVATE 传递给 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
}

我希望这能帮到您。

于 2009-11-23T15:55:04.737 回答
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;
    }
于 2013-10-31T06:41:29.907 回答