SendKeys.Send() 没有像我预期的那样发送或做出反应
SendKeys.Send() does not send or react as I expect
我在 C# 应用程序中使用 Sendkeys.Send
时遇到问题,我真的不明白为什么。使用它时,它不会将我期望的内容发送到活动应用程序。我将它与全局热键管理器一起使用,https://github.com/thomaslevesque/NHotkey
我已经创建了这个简单的 PoC,至少就我而言,它能够重现我的问题。只需启动 写字板 并按下热键 ALT + O
:
using System.Windows.Forms;
using System.Diagnostics;
using NHotkey.WindowsForms;
namespace WindowsFormsApp5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Convert string to keys
string hotkey = "Alt + O";
KeysConverter cvt;
Keys key;
cvt = new KeysConverter();
key = (Keys)cvt.ConvertFrom(hotkey);
// Setup the hotkey
HotkeyManager.Current.AddOrReplace("MyID", key, HotkeyAction);
// Copy some text to the clipboard that I want to paste to the active application
Clipboard.SetText("My String");
}
private void HotkeyAction(object sender, NHotkey.HotkeyEventArgs e)
{
Debug.WriteLine("Pressed the hotkey");
SendKeys.Send("^v");
// SendKeys.Send("Test string");
e.Handled = true;
}
}
}
当我在 写字板 中执行此操作时,它不会粘贴剪贴板(^v
等于 CTRL + V
),而是尝试“选择性粘贴”:
即使我做了最简单的事情,然后只是在 SendKeys.Send
中输入了一些文本,那么它似乎会弄乱 写字板 中的菜单? SendKeys.SendWait
没有什么不同。
我已经尝试解决这个问题很长一段时间了,但我只是不明白为什么会这样。基本上,我需要将剪贴板粘贴到热键上,尽管它不需要使用这种确切的方法,所以如果有人知道另一种方法,那么我会很感激一些提示。
我的实施方案
基于已接受的答案,我确实稍微更改了我的实现,因为我无法仅使用计时器来实现它。我可能遗漏了一些东西(?),但这是有效的。
在基本情况下,一旦检测到热键,我就会将焦点转移到我的应用程序,以避免与活动应用程序中的修改键(ALT
等)发生冲突。然后我创建一个不可见的表单,当我检测到 KeyUp
事件时,我会检查修改键,如果 none 被按下,我会启用一个计时器并立即将焦点切换回原始应用程序。 50 毫秒后,剪贴板将粘贴到活动应用程序。
像这样:
// Somewhere else in code but nice to know
// IntPtr activeApp = GetForegroundWindow(); // get HWnd for active application
// SetForegroundWindow(this.Handle); // switch to my application
private System.Timers.Timer timerPasteOnHotkey = new System.Timers.Timer();
// Main
public PasteOnHotkey()
{
InitializeComponent();
// Define the timer
timerPasteOnHotkey.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timerPasteOnHotkey.Interval = 50;
timerPasteOnHotkey.Enabled = false;
// Make the form invisble
this.Size = new System.Drawing.Size(0, 0);
this.Opacity = 0.0;
}
private void PasteOnHotkey_KeyUp(object sender, KeyEventArgs e)
{
// Check if modifier keys are pressed
bool isShift = e.Shift;
bool isAlt = e.Alt;
bool isControl = e.Control;
// Proceed if no modifier keys are pressed down
if (!isShift && !isAlt && !isControl)
{
Hide();
// Start the timer and change focus to the active application
timerPasteOnHotkey.Enabled = true;
SetForegroundWindow(activeApp);
}
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
timerPasteOnHotkey.Enabled = false;
SendKeys.SendWait("^v"); // send "CTRL + v" (paste from clipboard)
}
当您使用 SendKeys.Send
响应按键时,您发送的按键可能会与您当时持有的物理按键结合使用。在这种情况下,您按住 Alt,因此写字板假定您按下的是 Alt-Ctrl-V 而不是 Ctrl-V。 Alt 也会打开菜单,因此发送其他键可能与那里的热键有关。
添加延迟将消除此问题,并且通常在发送按键时会与其他按键无关,因此不会有问题。
我在 C# 应用程序中使用 Sendkeys.Send
时遇到问题,我真的不明白为什么。使用它时,它不会将我期望的内容发送到活动应用程序。我将它与全局热键管理器一起使用,https://github.com/thomaslevesque/NHotkey
我已经创建了这个简单的 PoC,至少就我而言,它能够重现我的问题。只需启动 写字板 并按下热键 ALT + O
:
using System.Windows.Forms;
using System.Diagnostics;
using NHotkey.WindowsForms;
namespace WindowsFormsApp5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Convert string to keys
string hotkey = "Alt + O";
KeysConverter cvt;
Keys key;
cvt = new KeysConverter();
key = (Keys)cvt.ConvertFrom(hotkey);
// Setup the hotkey
HotkeyManager.Current.AddOrReplace("MyID", key, HotkeyAction);
// Copy some text to the clipboard that I want to paste to the active application
Clipboard.SetText("My String");
}
private void HotkeyAction(object sender, NHotkey.HotkeyEventArgs e)
{
Debug.WriteLine("Pressed the hotkey");
SendKeys.Send("^v");
// SendKeys.Send("Test string");
e.Handled = true;
}
}
}
当我在 写字板 中执行此操作时,它不会粘贴剪贴板(^v
等于 CTRL + V
),而是尝试“选择性粘贴”:
即使我做了最简单的事情,然后只是在 SendKeys.Send
中输入了一些文本,那么它似乎会弄乱 写字板 中的菜单? SendKeys.SendWait
没有什么不同。
我已经尝试解决这个问题很长一段时间了,但我只是不明白为什么会这样。基本上,我需要将剪贴板粘贴到热键上,尽管它不需要使用这种确切的方法,所以如果有人知道另一种方法,那么我会很感激一些提示。
我的实施方案
基于已接受的答案,我确实稍微更改了我的实现,因为我无法仅使用计时器来实现它。我可能遗漏了一些东西(?),但这是有效的。
在基本情况下,一旦检测到热键,我就会将焦点转移到我的应用程序,以避免与活动应用程序中的修改键(ALT
等)发生冲突。然后我创建一个不可见的表单,当我检测到 KeyUp
事件时,我会检查修改键,如果 none 被按下,我会启用一个计时器并立即将焦点切换回原始应用程序。 50 毫秒后,剪贴板将粘贴到活动应用程序。
像这样:
// Somewhere else in code but nice to know
// IntPtr activeApp = GetForegroundWindow(); // get HWnd for active application
// SetForegroundWindow(this.Handle); // switch to my application
private System.Timers.Timer timerPasteOnHotkey = new System.Timers.Timer();
// Main
public PasteOnHotkey()
{
InitializeComponent();
// Define the timer
timerPasteOnHotkey.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timerPasteOnHotkey.Interval = 50;
timerPasteOnHotkey.Enabled = false;
// Make the form invisble
this.Size = new System.Drawing.Size(0, 0);
this.Opacity = 0.0;
}
private void PasteOnHotkey_KeyUp(object sender, KeyEventArgs e)
{
// Check if modifier keys are pressed
bool isShift = e.Shift;
bool isAlt = e.Alt;
bool isControl = e.Control;
// Proceed if no modifier keys are pressed down
if (!isShift && !isAlt && !isControl)
{
Hide();
// Start the timer and change focus to the active application
timerPasteOnHotkey.Enabled = true;
SetForegroundWindow(activeApp);
}
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
timerPasteOnHotkey.Enabled = false;
SendKeys.SendWait("^v"); // send "CTRL + v" (paste from clipboard)
}
当您使用 SendKeys.Send
响应按键时,您发送的按键可能会与您当时持有的物理按键结合使用。在这种情况下,您按住 Alt,因此写字板假定您按下的是 Alt-Ctrl-V 而不是 Ctrl-V。 Alt 也会打开菜单,因此发送其他键可能与那里的热键有关。
添加延迟将消除此问题,并且通常在发送按键时会与其他按键无关,因此不会有问题。