问题
I need to detect when a user presses Ctrl+V(regardless of window focus - my app will likely be minimised) but I must not stop the actual paste operation.
I have tried a few things: (I am successfully binding to keystrokes with RegisterHotKey)
I have:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x312)
hotKey();
base.WndProc(ref m);
}
and I've tried the following:
void hotKey()
{
SendKeys.SendWait("^v"); //just puts 'v' instead of clipboard contents
}
and
void hotKey()
{
SendKeys.SendWait(ClipBoard.GetText());
/* This works, but since Ctrl is still down, it triggers
* all the shortcut keys for the app, e.g. if the keyboard
* contains 's' then instead of putting 's' in the app, it
* calls Ctrl+S which makes the app think the user wants
* to save.
*/
}
Currently the only working solution I have is to bind to something different, e.g. Ctrl+B and then call SendKeys.SendWait("^v");
however this isn't ideal.
An ideal solution would be if my window didn't intercept the keystroke in the first place, just reacted.
回答1:
You can do this by leveraging hooks using SetWindowsHookEx().
HHOOK WINAPI SetWindowsHookEx(
__in int idHook,
__in HOOKPROC lpfn,
__in HINSTANCE hMod,
__in DWORD dwThreadId
);
Basically, you can set up a low-level keyboard hook:
_hookHandle = SetWindowsHookEx(
WH_KEYBOARD_LL,
KbHookProc, // Your keyboard handler
(IntPtr)0,
0); // Set up system-wide hook.
to capture system-wide keyboard events. But it also allows you to make those keyboard events pass through to other apps. For your particular case, you can define KbHookProc
as:
private static int KbHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0) // This means we can intercept the event.
{
var hookStruct = (KbLLHookStruct)Marshal.PtrToStructure(
lParam,
typeof(KbLLHookStruct));
// Quick check if Ctrl key is down.
// See GetKeyState() doco for more info about the flags.
bool ctrlDown =
GetKeyState(VK_LCONTROL) != 0 ||
GetKeyState(VK_RCONTROL) != 0;
if (ctrlDown && hookStruct.vkCode == 0x56) // Ctrl+V
{
// Replace this with your custom action.
Clipboard.SetText("Hi");
}
}
// Pass to other keyboard handlers. Makes the Ctrl+V pass through.
return CallNextHookEx(_hookHandle, nCode, wParam, lParam);
}
I coded a quick and dirty WinForms app to illustrate this. For the full code listing, see http://pastebin.com/uCSvqwb4.
来源:https://stackoverflow.com/questions/6838540/detecting-ctrlv-with-registerhotkey-but-not-intercepting-it