在摆弄了SendInput、SendKeys、PostMessage、SendMessage、SendNotifyMessage、keybd_event等各种问题之后,我想知道。为了找到那口井..。尝试将键盘输入发送到另一个非前台进程是相当挑剔和不可靠的。
我尝试了一种SendInput的方法,我欺骗了Z顺序(将当前窗口保持在顶部),并快速地突出第三方窗口,发送输入,然后重新突出我的窗口。它最终失败了,而且不知何故,还设法在不是前台的情况下处理了我的窗口上的击键(导致了两个窗口之间的发送和接收的无限循环,直到我设法关闭了该进程)。
我尝试过SendMessage和PostMessage的不同组合。一个代表down,一个代表up,因为同时使用down和up会导致问题,就像同时使用PostMessage一样,会导致接收窗口上的密钥重复。或者同时使用SendMessage,这会导致文本输入出现问题,但其他功能运行正常。keydown的SendMessage和keyUp的PostMessage适用于所有功能,但可靠性大幅下降,并增加了关键事件的延迟。只有用于keydown的PostMessage和用于keyup的SendMessage的组合才能做任何有用的事情,可能有5-10%的keyup注册失败率。SentNotifyMessage也是如此(就可靠性而言,其行为方式与SendMessage基本相同)。
所以从本质上讲,我已经走到了尽头,我想知道如何直接将钩子注入到目标窗口中,并以这种方式向目标窗口发送击键,绕过消息队列等。这样做不会处理全局键事件,而只会影响目标窗口。唯一的问题是,当涉及到注射/钩子等问题时,我相当不了解。所以我求助于你,社区。
怎么办?
发布于 2012-09-29 19:36:42
这是一小段代码,允许您向后台应用程序发送消息。例如,要发送"A“字符,只需调用sendKeystroke(Keys.A),并且不要忘记使用名称空间System.windows.forms来使用Keys对象。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace keybound
{
class WindowHook
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public static void sendKeystroke(ushort k)
{
const uint WM_KEYDOWN = 0x100;
const uint WM_SYSCOMMAND = 0x018;
const uint SC_CLOSE = 0x053;
IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");
IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, ((IntPtr)k), (IntPtr)0);
//IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
}
}
}
https://stackoverflow.com/questions/10407769
复制相似问题