问题
这是我在后台发送按键的功能。
class SendMessage
{
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
public static void sendKeystroke(string appName)
{
const int WM_KEYDOWN = 0x100;
IntPtr hWnd = FindWindow(null, appName);
IntPtr editx = FindWindowEx(hWnd, IntPtr.Zero, "edit", null);
PostMessage(editx, WM_KEYDOWN, (IntPtr)Keys.A, (IntPtr)0);
}
}
此代码适用于notepad
,例如,让appName ="记事本"。
但是,我可以设法在其他应用程序中执行..我在LINE应用程序上练习。
正如您在图片中看到的那样lpszClass variable
="编辑" (小红圈)用于记事本。
我需要为LINE应用找到它,所以我使用WinSpy++
来捕获这些类名。
我发现它的班级名称是" ATL:00B53BE8" (大红圈)我可以输入消息
在WinSpy ++中输入,它将显示为Line textbox(蓝色圆圈)。
结论
我尝试用" edit"替换捕获类名称。但没有希望。
我不明白为什么捕获类名不可用请帮助或给我一些提示。
我不知道可能是系统应用程序的层次结构有所不同(粉红色)
我不知道FindWindowEx中的哪些参数意味着那么多。
我的最终目标是将关键笔划发送到其他应用程序而不关注它们。
答案 0 :(得分:1)
您不能指望发送到没有焦点的应用程序的WM_KEYDOWN
消息具有所需的效果。它根本不受支持。根据Windows规则,接收WM_KEYDOWN
消息意味着您的应用程序具有焦点。只有专注的应用程序才能获得键盘输入。
所以你在尝试可能在某些情况下工作,但不能保证工作。如果应用程序接收键盘输入,应用程序可能会做出非常合理的假设,即它具有焦点。
如果它在记事本中“有效”,那是因为记事本是一个非常 dumb 的简单应用程序。它只是一个带菜单栏的编辑控件。它对WM_KEYDOWN
消息的处理可能只不过是将由消息参数指示的密钥表示的字符添加到编辑控件。大多数其他应用程序更复杂。甚至记事本也不能保证在所有情况下都能正常工作。例如,当其窗口最小化时。在本网站的其他地方和Interwebz上有很多关于此类问题的报告。
简单地说:发送WM_KEYDOWN
及其朋友不就像在Windows中模拟键盘输入一样。这有两种基本方法。第一种是使用SendInput
函数;另一种是安装WH_JOURNALPLAYBACK
钩子。对于.NET中的SendKeys
类,不同版本的实现都采用了不同的方法。它们都将合成输入发送到聚焦窗口,因为在Windows中,这是接收所有输入的窗口。
如果这是完全可行的,那么你绝对必须找到另一种方法。在评论中,David建议使用UI Automation,这是专为此目的而设计的工具。它是conveniently wrapped by the .NET Framework。目前还不清楚你为何拒绝这个建议。使用UI自动化,您可以使用嵌套树结构轻松浏览应用程序中窗口的层次结构。此树是从进程中的所有窗口句柄自动构建的。这使您可以轻松找到要操作的控件。然后,您获得适当的control patterns,并执行您想要的任何操作。
答案 1 :(得分:0)
与David Herffernan
的讨论
“您需要多次调用才能遍历父级子层次结构”
现在,我可以让我的代码工作..但是,这似乎不是正确的做法(黑客)
但是,我想回答这个问题以供我参考
关键是使用FindWindowEx
它的工作方式为David Herffernan
。
而非......
public static void sendKeystroke(string appName)
{
const int WM_KEYDOWN = 0x100;
IntPtr hWnd = FindWindow(null, appName);
IntPtr editx = FindWindowEx(hWnd, IntPtr.Zero, "edit", null);
PostMessage(editx, WM_KEYDOWN, (IntPtr)Keys.A, (IntPtr)0);
}
我编辑到这个..
public static void sendKeystroke(string appName)
{
const int WM_KEYDOWN = 0x100;
IntPtr hWnd = FindWindow(null, appName);
IntPtr editx1 = FindWindowEx(hWnd, IntPtr.Zero, "SkinScrollWnd", null);
IntPtr editx2 = FindWindowEx(editx1, IntPtr.Zero, "SkinScrollMidWnd", null);
IntPtr editx3 = FindWindowEx(editx2, IntPtr.Zero, "ATL:00B53BE8", null);
PostMessage(editx3, WM_KEYDOWN, (IntPtr)Keys.A, (IntPtr)0);
}