问题描述
当输入
键时,我想更改单元格颜色。一切都很好,除了该代码在活动的Excel 2013中不起作用,只有当它在后台时。如何解决这个问题?
I want to change cell color when Enter
key is pressed. Everything is fine except, that code doesn't work in active Excel 2013, only when it is in background. How can I solve this problem?
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在后台时才有效。
Also I have tried to do like this, but same, works only if Excel 2013 is in background....
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
。以下代码允许您捕获任何按键,检查修饰符并调用某些操作。
The main mistake you made in your code is using WH_KEYBOARD_LL
. It will not work well in Excel, use WH_KEYBOARD
instead. The code below allows you to catch any key pressed, check modifiers and invoke some action.
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()
方法。
To use this class, call Start()
and Stop()
methods.
这篇关于Excel VSTO钥匙钩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!