我正在尝试以编程方式模拟按下键盘上的向上箭头键进行端到端测试。使用下面的代码,GUI控件没有接收到消息(WM_KEYDOWN,WM_GETDLGCODE,WM_KEYUP)。我使用Spy++来检测传入的消息。您知道为什么吗?\您可以建议其他解决方案吗?
该控件继承自UserControl类(WinForms)。此外,由于我使用了Control.InvokeRequired()
和所有相关内容,因此没有跨线程异常。
我试了两次第一次是
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
public static int WM_KEYDOWN = 0x100;
public static int WM_KEYUP = 0x101;
public static int VK_UP = 0x26;
public void SimulateKeystrokeEventMethod()
{
Thread.Sleep(20000);
Control control = Control.FromHandle(MyGUICOntrol.Handle);
if (control.InvokeRequired)
{
System.Action safeStimulation = delegate
{
SetForegroundWindow(Handle);
const uint MK_LBUTTON = 0x0001;
Point ClickPos = new Point(330, 401); //The position on top of the objects
IntPtr lParam = (IntPtr)((401 << 16) | 330);
IntPtr result = IntPtr.Zero;
SendMessage(Handle, WM_LBUTTONDOWN, new IntPtr(MK_LBUTTON), lParam);
SendMessage(Handle, WM_LBUTTONUP, IntPtr.Zero, lParam);
for (int i = 0; i < 100; i++)
{
lParam = (IntPtr)(0);
PostMessage(Handle, WM_KEYDOWN, new IntPtr(VK_UP), lParam);
SendMessage(Handle, WM_GETDLGCODE, 0x00, 0x00);
PostMessage(Handle, WM_KEYUP, new IntPtr(VK_UP), lParam);
}
};
control.Invoke(safeStimulation);
}
第二次尝试:
public void SimulateKeystrokeEventMethod()
{
Thread.Sleep(20000);
Control control = Control.FromHandle(MyGUICOntrol.Handle);
if (control.InvokeRequired)
{
System.Action safeStimulation = delegate
{
SetForegroundWindow(Handle);
const uint MK_LBUTTON = 0x0001;
Point ClickPos = new Point(330, 401); //The position on top of the objects
IntPtr lParam = (IntPtr)((401 << 16) | 330);
IntPtr result = IntPtr.Zero;
SendMessage(Handle, WM_LBUTTONDOWN, new IntPtr(MK_LBUTTON), lParam);
SendMessage(Handle, WM_LBUTTONUP, IntPtr.Zero, lParam);
////for (ushort tryScanCode = 0x79; tryScanCode < 0xFF; tryScanCode++)
{
ushort tryScanCode = 0x48;
Input[] inputs1 = new Input[]
{
new Input
{
type = (int) InputType.Keyboard,
u = new InputUnion
{
ki = new KeyboardInput
{
wVk = 0,
wScan = 0x48,
dwFlags = (uint) (KeyEventF.KeyDown | KeyEventF.Scancode),
dwExtraInfo = GetMessageExtraInfo()
}
}
}
};
Input[] inputs2 = new Input[]
{
new Input
{
type = (int)InputType.Keyboard,
u = new InputUnion
{
ki = new KeyboardInput
{
wVk = 0,
wScan = 0x48,
dwFlags = (uint)(KeyEventF.KeyUp | KeyEventF.Scancode),
dwExtraInfo = GetMessageExtraInfo()
}
}
}
};
SetForegroundWindow(Handle);
SendInput((uint)inputs1.Length, inputs1, Marshal.SizeOf(typeof(Input)));
SendMessage(Handle, WM_GETDLGCODE, 0x00, 0x00);
SendInput((uint)inputs2.Length, inputs2, Marshal.SizeOf(typeof(Input)));
}
};
control.Invoke(safeStimulation);
}
}
这是来自Simulate the pressing of the UP arrow key on a keyboard的后续问题
非常感谢您的帮助!
2条答案
按热度按时间iqxoj9l91#
关于SendInput()的一些注解,与您尝试执行的操作有关。
SetFocus()
的调用可能会失败,因此我们事先附加到该Thread。这里,我使用GetCurrentThreadId()并与GetWindowThreadProcessId()进行比较,以验证调用者线程和目标线程是否不同。
如果它们不相同,则调用AttachThreadInput()。
如果目标主窗口被最小化(请参见对IsIconic()的调用),它将被还原,调用SetWindowPlacement()并使用BringWindowToTop()将其置于前台。
然后调用SetFocus()将焦点移动到目标句柄(假设它可以接收焦点,也就是说-函数无论如何都应该返回success)。
最后,收集需要在不同的
INPUT
结构体中发送的所有Key(每个Key Modifiers都在自己的结构体中),并对SendInput()
进行一次调用。例如:
将Up键发送到目标控制柄:
发送Ctrl + Shift + Home:
它是这样工作的:
标准的PictureBox无法聚焦,因此当调用
SetFocus()
时,您将看到Button闪烁Sample Project for testing (Google Drive)
本机方法:
abithluo2#
吉米,你帮了我很大的忙!从你的回答中,我修复了我的代码。我提交了另一个答案来解决我的问题。