我试图使用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。有什么想法吗?
答案 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);
}