private int CwpProc(int nCode, IntPtr wParam, IntPtr lParam) { CwpStruct cwpStruct = (CwpStruct)Marshal.PtrToStructure(lParam, typeof(CwpStruct)); if (nCode < 0) { return(WindowsInterop.CallNextHookEx(_hHookCwp, nCode, wParam, lParam)); } if (cwpStruct.message == WindowsInterop.WM_MOUSEACTIVATE) { // We got a WM_MOUSEACTIVATE message. Now we will check that the target handle is a workbook window. // Workbook windows have the name "EXCEL7". bool isWorkbookWindow = false; try { StringBuilder cname = new StringBuilder(256); WindowsInterop.GetClassNameW(cwpStruct.hwnd, cname, cname.Capacity); if (cname.ToString() == "EXCEL7") { isWorkbookWindow = true; } } catch (Exception e) { Debug.Print("Could not get the window name: {0}", e); } if (isWorkbookWindow) { // If the window is not activated, then Excel will activate it and then discard the message. That's why the user cannot select a range at the same time. // The following statement will activate the window before Excel treats the message, thus it will not activate the window and it will keep proceeding the message. // In that way, it is possible to select the range. try { WindowsInterop.SetFocus(cwpStruct.hwnd); } catch (Exception e) { Debug.Print("Failed to set the focus: {0}", e); } // If the user chooses a cell which was already selected, then the event SheetSelectionChange will not be raised. // A workaround is to send the current selection when the Excel window gets the focus. // Note that if the user selects a different range, then 2 events will be raised: a first one with the current selection, // and a second one with the new selection. try { OnNewSelection(null, (Range)_application.Selection); } catch { } } } return(WindowsInterop.CallNextHookEx(_hHookCwp, nCode, wParam, lParam)); }
public void Stop() { _application.SheetSelectionChange -= OnNewSelection; if (!WindowsInterop.UnhookWindowsHookEx(_hHookCwp)) { Debug.Print("Error: Failed to unhook WH_CALLWNDPROC"); } }
public ExcelSelectionTracker(int excelThreadId) { _application = (Microsoft.Office.Interop.Excel.Application)ExcelDnaUtil.Application; _application.SheetSelectionChange += OnNewSelection; _excelThreadId = excelThreadId; _procCwp = CwpProc; _hHookCwp = WindowsInterop.SetWindowsHookEx(HookType.WH_CALLWNDPROC, _procCwp, (IntPtr)0, excelThreadId); if (_hHookCwp == 0) { throw new Exception("Failed to hook WH_CALLWNDPROC"); } }