Excel VSTO钥匙钩

Enter键时,我想改变单元格的颜色。 一切都很好,除非在活动Excel 2013中,只有在后台才能使用该代码。 我怎么解决这个问题?

 using MouseKeyboardActivityMonitor; using MouseKeyboardActivityMonitor.WinApi; 

  public KeyboardHookListener k_keyListener; private void ThisAddIn_Startup(object sender, System.EventArgs e) { k_keyListener = new KeyboardHookListener(new GlobalHooker()); k_keyListener.Enabled = true; k_keyListener.KeyDown += new KeyEventHandler(k_keyListener_KeyDown); } void k_keyListener_KeyDown(object sender, KeyEventArgs e) { if(e.KeyValue == 13) { Excel.Range rng2 = this.Application.get_Range("A1"); rng2.Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red); } } 

我也试图这样做,但同样,只适用于Excel 2013的背景….

  public partial class ThisAddIn { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private static IntPtr hookId = IntPtr.Zero; private delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam); private static HookProcedure procedure = HookCallback; [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll", SetLastError = true)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, HookProcedure lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); private void ThisAddIn_Startup(object sender, System.EventArgs e) { hookId = SetHook(procedure); } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { UnhookWindowsHookEx(hookId); } private static IntPtr SetHook(HookProcedure procedure) { using (Process process = Process.GetCurrentProcess()) using (ProcessModule module = process.MainModule) return SetWindowsHookEx(WH_KEYBOARD_LL, procedure, GetModuleHandle(module.ModuleName), 0); } private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { int pointerCode = Marshal.ReadInt32(lParam); string pressedKey = ((Keys)pointerCode).ToString(); //Do some sort of processing on key press var thread = new Thread(() => { MessageBox.Show(pressedKey); }); thread.Start(); } return CallNextHookEx(hookId, nCode, wParam, lParam); } 

您在代码中犯的主要错误是使用WH_KEYBOARD_LL 。 它不会在Excel中正常工作,而是使用WH_KEYBOARD 。 下面的代码允许你捕捉任何按键,检查修饰符并调用一些操作。

 using System; using System.Runtime.InteropServices; using System.Windows.Forms; using Microsoft.Office.Interop.Excel; namespace SimpleExcelAddIn { static class ShortcutManager { delegate int LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); static readonly LowLevelKeyboardProc _proc = HookCallback; static IntPtr _hookID = IntPtr.Zero; const int WH_KEYBOARD = 2; const int HC_ACTION = 0; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern bool UnhookWindowsHookEx(IntPtr idHook); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] static extern short GetKeyState(int nVirtKey); static bool _keyHookingStarted; public static void Start() { if (!_keyHookingStarted) { #pragma warning disable 0618 _hookID = SetWindowsHookEx(WH_KEYBOARD, _proc, IntPtr.Zero, (uint) AppDomain.GetCurrentThreadId()); #pragma warning restore 0618 _keyHookingStarted = true; } } public static void Stop() { if (_keyHookingStarted) { UnhookWindowsHookEx(_hookID); _hookID = IntPtr.Zero; _keyHookingStarted = false; } } static void OnKeyPress(uint keys) { Func<Keys, bool> checkKey = key => keys == (uint) key && IsKeyDown(key); //checks that shift, alt, ctrl and win keys are not pressed Func<bool> checkModifiers = () => !IsKeyDown(Keys.ShiftKey) && !IsKeyDown(Keys.Menu) // Keys.Menu is Alt button code && !IsKeyDown(Keys.LWin) && !IsKeyDown(Keys.RWin); if (checkModifiers() && (checkKey(Keys.Enter) || checkKey(Keys.Return))) { // Make you actions here. If it is some long action, do it in background thread // this code is just and example Worksheet ws = Globals.ThisAddIn.Application.ActiveSheet; Range cell = ws.Cells[1, 1]; cell.Interior.Color = 0xFF0000; } } static bool IsKeyDown(Keys keys) { return (GetKeyState((int) keys) & 0x8000) == 0x8000; } static int HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode < 0) { return (int) CallNextHookEx(_hookID, nCode, wParam, lParam); } if (nCode == HC_ACTION) { OnKeyPress((uint) wParam); } return (int) CallNextHookEx(_hookID, nCode, wParam, lParam); } } } 

要使用这个类,调用Start()Stop()方法。