调用 SendInput 函数后,屏幕变为空白。为什么会这样?又该如何避免呢?这是屏幕变为空白的 c# 代码:
[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
public static void ClickM(IntPtr wHandle, int X = 0, int Y = 0, int delay = 100)
{
if (wHandle == IntPtr.Zero)
{
MessageBox.Show("App is not running.");
return;
}
INPUT[] Inputs = new INPUT[3];
INPUT Input = new INPUT();
Input.type = 0;
Input.U.mi.dx = X;
Input.U.mi.dy = Y;
Input.U.mi.time = (uint)delay;
Input.U.mi.dwFlags = MOUSEEVENTF.MOVE;
Inputs[0] = Input;
Input.type = 0;
Input.U.mi.dx = X;
Input.U.mi.dy = Y;
Input.U.mi.time = (uint)delay;
Input.U.mi.dwFlags = MOUSEEVENTF.LEFTDOWN;
Inputs[1] = Input;
Input.type = 0;
Input.U.mi.dx = X;
Input.U.mi.dy = Y;
Input.U.mi.time = (uint)delay;
Input.U.mi.dwFlags = MOUSEEVENTF.LEFTUP;
Inputs[2] = Input;
SendInput((uint)Inputs.Length, Inputs, INPUT.Size);
}
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
internal InputType type;
internal InputUnion U;
internal static int Size
{
get { return Marshal.SizeOf(typeof(INPUT)); }
}
}
此外,其中一台显示器会在几秒钟后挂起,而第二台显示器则保持死机,直到您关闭程序/按“Esc”。在 Delphi 上的一个类似问题中,该案例在“非归零数组”中,并且正在处理 ZeroMemory,但据我所知,这种方法在 C# 中不相关,还是我弄错了?!顺便说一句,我还无法应用 ZeroMemory,但我正在努力 :) 该程序以管理员权限启动,Windows 10 用户帐户控制不会影响这一点:我试图完全禁用它 - 没有变化。我知道有自动脚本形式的替代方案,例如,可以实现类似的目标,但是当我的程序专门执行操作时,我有兴趣使用这种特殊机制。
将通话分为 3 个部分。
SendInput((uint)1, Inputs1, INPUT.Size);
SendInput((uint)1, Inputs2, INPUT.Size);
SendInput((uint)1, Inputs3, INPUT.Size);
当调用 move 和 Leftdown 时,一切正常(我不确定会发生什么,因为窗口中的焦点不会消失:)),但是当我调用最后一个函数来释放按钮时,屏幕变为空白。
这些是我使用的关键定义:
[Flags]
public enum MOUSEEVENTF
{
MOVE = 0x01,
LEFTDOWN = 0x02,
LEFTUP = 0x04,
RIGHTDOWN = 0x08,
RIGHTUP = 0x10
}
使用 P/Invoke Windows API 函数时,首先要做的是仔细阅读文档。其次,您需要确保结构正确编组。
显示器可能会因为 Windows 错误地感知您的输入而变为空白,例如,作为某种鼠标手势(任何不可预知的行为),甚至可以将屏幕倒置,我不知道您的系统是如何配置的。
我已经准备好
SendInput为键盘和鼠标生成输入的代码。即使有 XML 注释。
接下来,让我们重写您的方法来修复错误。主要错误是您在字段中传递了一些数字 100
time。它不会延迟,但会在按下键时为应用程序提供信息 - 时间戳。也就是说,你需要在那里传递 0 。
而对于点击之间的延迟,你需要在你的应用程序中明确地等待,例如,
Thread.Sleep(100)甚至更好await Task.Delay(100)。但是,让我们立即开始吧。没有额外的东西。顺便说一句,有
SendInput一个返回值。也就是说,通过这个数字,您可以确定有多少来自数组的输入被成功处理。