以编程方式取消C#中的键盘命令

时间:2014-07-24 16:01:54

标签: c# excel winapi vsto keyboard-shortcuts

我试图使用VSTO在MS Excel中编写一个钩子,而且我非常接近我需要的东西,但我有一个小问题。

我使用了低级别的WINAPI调用来获取键盘事件并检查键击(效果很好)。

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, KeyCaptureDelegate 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 static IntPtr KeyCaptureCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0)
        {
            int pointerCode = Marshal.ReadInt32(lParam);

            bool result = false;

            if (wParam == (IntPtr)WM_KEYDOWN)
            {
                if (KeyDown != null)
                {
                    result = KeyDown(pointerCode);
                }
            }

            //if (result)
                //return IntPtr.Zero;
        }

        return CallNextHookEx(_keyCaptureHook, nCode, wParam, lParam);
    }

所有内容都已连接并运行良好(使用SetWindowsHookEx),我的代码通过KeyDown调用,没有任何问题。唯一的问题是我试图在Excel中覆盖默认命令,即Ctrl + Shift + 1。这会导致默认功能发生。

在我的代码中,结果返回是否应该覆盖行为(即使用我的新行为,而不是默认行为)。我希望,或许,返回IntPtr.Zero会破坏并从泵中移除钥匙,但这似乎没有做任何事情。

有没有办法阻止其他(默认)行为?我想通过取消/处理事件(就像我们可以在WinForms / WPF中),应该有一些方法来防止键击进一步迁移到Excel。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

所以,我需要做一些小改动:

    private delegate IntPtr KeyCaptureDelegate(int nCode, IntPtr wParam, IntPtr lParam);

成为:

    private delegate int KeyCaptureDelegate(int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

成为:

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

这允许我将其重写为:

    private static int KeyCaptureCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0)
        {
            int pointerCode = Marshal.ReadInt32(lParam);

            bool result = false;

            if (wParam == (IntPtr)WM_KEYDOWN)
            {
                if (KeyDown != null)
                {
                    result = KeyDown(pointerCode);
                }
            }

            if (result)
            {
                return 1;
            }
        }

        return CallNextHookEx(_keyCaptureHook, nCode, wParam, lParam);
    }