2

Excel 2007 アドインを作成しています。VS2008 と .net 3.5、C# を使用。

Microsoft.Office.Interop.Excel.Application の WindowActivate および WindowDeActivate イベントをキャッチしました。

WindowActivate と Deactivate は、2 つの Excel Windows を切り替えたときにのみトリガーされることを知って驚きました。メモ帳に切り替えると、非アクティブ化がトリガーされると予想されますが、発生しません。Excelウィンドウに切り替えると、メモ帳から同じように、アクティブ化がトリガーされると予想されますが、発生しません。ウィンドウがMDI子ウィンドウであることを示す動作のようです。

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

誰でもこれについて私に案内できますか。

よろしく

4

2 に答える 2

6

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

最初に、NativeWindow クラスから継承した独自のクラスを作成し、その中で Activated と Deactivate の 2 つのイベントを宣言し、最後に 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
}

これがお役に立てば幸いです。

于 2009-11-23T15:55:04.737 に答える
0

最後に、アクティブ化/非アクティブ化のみで機能する 1 つの解決策を見つけました。これは完璧な方法ではありません。しかし、私は良い代替手段を見つけられませんでした。このメソッドはポーリングを使用します。フォーカスのイン/アウトをチェックするには、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 に答える