2009-07-03 4 views
2

Excel 2007 Addin을 작성했습니다. VS2008 및 .net 3.5, C#을 사용합니다.C# : Excel 2007 Addin, Windows 후크 방법 이벤트 활성화 및 비활성화

Microsoft.Office.Interop.Excel.Application의 WindowActivate 및 WindowDeActivate 이벤트를 포착했습니다.

WindowActivate 및 Deactivate는 두 Excel Windows간에 전환 할 때만 트리거된다는 것을 알고 놀랐습니다. 내가 메모장으로 전환하면, 나는 Deactivate가 트리거 될 것으로 예상하지만, 그것은 일어나지 않는다. 메모장에서 윈도우로 전환하는 것과 같은 방식으로, 나는 Activate가 트리거되지만 그 일은 일어나지 않을 것이라고 기대합니다. 문제는 창문이 MDI-Child 창임을 나타냅니다.

이제 Excel의 Mainwindow의 HWnd를 가져오고 dllimport 기능을 사용하여 Window Activate 및 Deactivates를 실행합니다.

누구든지 내게 이것을 안내 할 수 있습니까?

감사합니다.

답변

6

Excel 추가 기능을 작성할 때 비슷한 문제가 발생했습니다. dll 가져 오기가 필요하지 않습니다. System.Windows.Forms.NativeWindow 클래스를 사용하여이 문제를 해결했습니다.

처음에 NativeWindow 클래스에서 상속받은 클래스를 만들고 Activated 및 Deactivate를 선언하고 마지막으로 WndProc() 메서드를 재정 의하여 WMnACroc 메서드가 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

0

마지막으로 하나의 솔루션을 찾았습니다. 활성화/비활성화 만 작동합니다. 이것은 완벽한 방법이 아닙니다. 그러나 나는 좋은 대안을 찾지 못했습니다. 이 메서드는 폴링을 사용합니다. 포커스를 in/out 체크하기 위해 각 10ms 간격으로 다음 함수를 호출해야합니다.

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