从后台C#应用程序发送Win API paste cmd
目标:编写一个在后台运行的C#应用程序,侦听组合键Win-V,当出现这种情况时,将剪贴板内容粘贴到当前活动窗口(某些任意应用程序)。基本上我是在模仿,但我不想先把文本转换成纯文本 问题:粘贴到当前活动窗口不起作用 详细信息:要在后台收听按键操作,我使用的是来自的globalKeyboardHook类。我能够捕获Win-V事件,但无法正确发送粘贴命令。我可以使用函数SendKeys.send或keybd\u event发送粘贴。但是,他们向管道发送另一个“V”键,该键被gkh_KeyDown事件捕获,并导致多个粘贴事件触发 我希望我需要使用SendMessage或PostMessage,但到目前为止,我所有的尝试都失败了。下面是最后一个函数的完整代码,SendCtrlV,它是我们感兴趣的函数之一。这些评论解释了我迄今为止所做的一切。你能看到我遗漏了什么吗从后台C#应用程序发送Win API paste cmd,c#,winforms,winapi,winforms-interop,C#,Winforms,Winapi,Winforms Interop,目标:编写一个在后台运行的C#应用程序,侦听组合键Win-V,当出现这种情况时,将剪贴板内容粘贴到当前活动窗口(某些任意应用程序)。基本上我是在模仿,但我不想先把文本转换成纯文本 问题:粘贴到当前活动窗口不起作用 详细信息:要在后台收听按键操作,我使用的是来自的globalKeyboardHook类。我能够捕获Win-V事件,但无法正确发送粘贴命令。我可以使用函数SendKeys.send或keybd\u event发送粘贴。但是,他们向管道发送另一个“V”键,该键被gkh_KeyDown事件捕
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Utilities;
namespace KeyHookTest
{
public partial class Form1 : Form
{
private bool LWin_down;
private bool V_down;
globalKeyboardHook gkh = new globalKeyboardHook();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static public extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwnd, int msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
gkh.HookedKeys.Add(Keys.V);
gkh.HookedKeys.Add(Keys.LWin);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
}
void gkh_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.LWin)
LWin_down = false;
else
V_down = false;
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.LWin)
LWin_down = true;
else
V_down = true;
if (LWin_down && V_down)
{
LogDebug("Enter Win+V");
try
{
SendCtrlV();
}
catch { }
}
}
private void SendCtrlV()
{
uint KEYEVENTF_KEYUP = 2;
int KEYDOWN = 0x0100;
int KEYUP = 0x0101;
byte KEY_LCONTROL1 = 0x11;
IntPtr KEY_LCONTROL2 = new IntPtr(0x11);
byte KEY_V1 = 0x56;
IntPtr KEY_V2 = new IntPtr(0x56);
int WM_PASTE1 = 0x302;
uint WM_PASTE2 = 0x302;
IntPtr hWnd = GetForegroundWindow();
// Works, but causes multiple gkh_KeyDown to fire so it's slow and buggy
/*keybd_event(KEY_LCONTROL1, 0, 0, 0);
keybd_event(KEY_V1, 0, 0, 0);
keybd_event(KEY_V1, 0, KEYEVENTF_KEYUP, 0);
keybd_event(KEY_LCONTROL1, 0, KEYEVENTF_KEYUP, 0);*/
// Works, but causes multiple gkh_KeyDown to fire so it's slow and buggy
//SendKeys.Send("^v");
// Doesn't work, causes UAC prompt
//SendKeys.Send("{^}v");
// Doesn't work, nothing gets pasted to the foregroundwindow
//SendMessage(hWnd, WM_PASTE1, 0, 0);
// Doesn't work, nothing gets pasted to the foregroundwindow
//PostMessage(hWnd, WM_PASTE2, IntPtr.Zero, IntPtr.Zero);
// Doesn't work, nothing gets pasted to the foregroundwindow
/*SendMessage(hWnd, KEYDOWN, KEY_LCONTROL1, 0);
SendMessage(hWnd, KEYDOWN, KEY_V1, 0);
SendMessage(hWnd, KEYUP, KEY_V1, 0);
SendMessage(hWnd, KEYUP, KEY_LCONTROL1, 0);*/
// Doesn't work, nothing gets pasted to the foregroundwindow
/*PostMessage(hWnd, 0x0100, KEY_LCONTROL2, IntPtr.Zero);
PostMessage(hWnd, 0x0100, KEY_V2, IntPtr.Zero);
PostMessage(hWnd, 0x0101, KEY_V2, IntPtr.Zero);
PostMessage(hWnd, 0x0101, KEY_LCONTROL2, IntPtr.Zero);*/
}
private void LogDebug(string msg)
{
string logpath = Environment.GetEnvironmentVariable("USERPROFILE") + @"\Desktop\KeyHookTest.txt";
File.AppendAllText(logpath, DateTime.Now.ToString("HH:mm:ss:fff") + ": " + msg + "\r\n");
}
}
}
这些额外的链接帮助我找到了答案:
private void SendCtrlV()
{
IntPtr hWnd = GetFocusedHandle();
PostMessage(hWnd, WM_PASTE, IntPtr.Zero, IntPtr.Zero);
}
static IntPtr GetFocusedHandle()
{
var info = new GuiThreadInfo();
info.cbSize = Marshal.SizeOf(info);
if (!GetGUIThreadInfo(0, ref info))
throw new Win32Exception();
return info.hwndFocus;
}
它可以工作,但必须使用TextBox的本机窗口句柄如果您希望它有效IIRC,则不需要将
WM_PASTE
消息发送到窗口句柄;将其发送到要直接粘贴内容的控件的句柄。您必须在hWnd
上使用EnumChildWindows
,从getforegroughindow
获取该控件的句柄。(您不会粘贴到窗口本身,而是粘贴到窗口上的编辑控件中。)这当然是有道理的。通过快速搜索,我还没有找到很多关于如何做到这一点的方法,但我会继续朝这个方向看。如果你查看文档中的EnumChildWindows
,考虑到你迄今为止所写的代码,我怀疑你会有太多的困难来理解它(肯定比我在C中更容易-在C或Delphi中很容易)。顺便说一句,问题是+1-我忙着写评论,第一次忘了写了。:-)也许会有帮助。我是从那里得到的。看看这个: