SendInputメソッドを使用してマウス入力をシミュレートしようとしています。クリックなどが正しく機能していますが、座標が正しく設定されていません。入力が実行されるたびに、マウスカーソルが画面の右下隅に移動します。 MOUSEINPUT XとY座標を長いデータ型as listed in the MSDN documentationに変更しようとしましたが、SendInputメソッドは常にエラーを返し、入力は実行されません。C# - SendInputを使用するとMOUSEINPUT座標が正しく設定されない
以下は、これを試みるために使用しているコードです。 KEYBDINPUT構造体が作成され実行された同様の実装からこのコードを移植しました。その実装は完全に機能したので、私はなぜそうではないのか混乱しています。私は、それが問題を引き起こしている座標だけで、マウスクリックなどがうまく実行されると、非常に小さいものだと確信しています。
ここで何がうまくいかないかについての洞察があれば、援助をいただければ幸いです。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace SequenceAutomation
{
#region Stucture declarations
public struct MOUSEINPUT
{
public int X;
public int Y;
public uint MouseData;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
public struct HARDWAREINPUT
{
public uint Msg;
public ushort ParamL;
public ushort ParamH;
}
public struct KEYBDINPUT
{
public ushort KeyCode;
public ushort Scan;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Explicit)]
public struct MOUSEKEYBDHARDWAREINPUT
{
[FieldOffset(0)]
public MOUSEINPUT Mouse;
[FieldOffset(0)]
public KEYBDINPUT Keyboard;
[FieldOffset(0)]
public HARDWAREINPUT Hardware;
}
public struct INPUT
{
public uint Type;
public MOUSEKEYBDHARDWAREINPUT Data;
}
#endregion
public class PlayRecording
{
#region Variable declarations
public bool stopPlayback;
private RecordingManager recManager;
private float timeFactor;
private Dictionary<long, Dictionary<IntPtr, Dictionary<string, int>>> mouseDict;
private Dictionary<long, INPUT[]> keysToPlay;
private Stopwatch watch;
private long currentEntry;
#endregion
#region Libary importations
// Importation of native libraries
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
#endregion
#region Public methods
public PlayRecording(string inputJson, float timeFactor)
{
currentEntry = 0;
this.timeFactor = timeFactor;
stopPlayback = false;
watch = new Stopwatch();
recManager = new RecordingManager(inputJson);
recManager.getDictionaries(inputJson);
mouseDict = recManager.mouseDict;
inputsToPlay = new Dictionary<long, INPUT[]>();
prepareInputsToPlay();
}
public void Start()
{
currentEntry = 0;
watch.Reset();
watch.Start();
IEnumerator<long> enumerator = inputsToPlay.Keys.GetEnumerator();
while (enumerator.MoveNext())
{
while (watch.ElapsedTicks < (enumerator.Current * timeFactor)) { }
if (!stopPlayback)
uint err = SendInput((uint)keysToPlay[enumerator.Current].Length, keysToPlay[enumerator.Current], Marshal.SizeOf(typeof(INPUT)));
currentEntry = enumerator.Current;
}
}
public bool Stop()
{
watch.Stop();
return true;
}
#endregion
#region Private methods
private void prepareInputsToPlay()
{
foreach (KeyValuePair<long, Dictionary<IntPtr, Dictionary<string, int>>> kvp in mouseDict)
{
List<INPUT> inputs = new List<INPUT>();
foreach (KeyValuePair<IntPtr, Dictionary<string, int>> kvp2 in kvp.Value)
{
int x = 0;
int y = 0;
foreach (KeyValuePair<string, int> kvp3 in kvp2.Value)
{
if (kvp3.Key == "X")
x = Convert.ToInt32(kvp3.Value);
if (kvp3.Key == "Y")
y = Convert.ToInt32(kvp3.Value);
}
inputs.Add(loadMouse(x, y, getFlags(kvp2.Key)));
}
inputsToPlay.Add(kvp.Key, inputs.ToArray());
}
}
// This is where the flags are set
private uint getFlags(IntPtr activity)
{
string activityInt = Convert.ToString(activity);
switch(activityInt)
{
return 0x0002;
case "512":
return 0x0001;
case "513":
return 0x0002;
case "514":
return 0x0004;
case "516":
return 0x0008;
case "517":
return 0x0010;
case "522":
return 0x0800;
default:
return 0;
}
}
// This is where the input structures are being created
private INPUT loadMouse(int x, int y, uint flags)
{
return new INPUT
{
Type = 0,
Data =
{
Mouse = new MOUSEINPUT
{
X = x,
Y = y,
MouseData = 0,
Flags = flags,
Time = 0,
ExtraInfo = IntPtr.Zero
}
}
};
}
#endregion
}
}
左クリック、右クリックなどの他のフラグを渡している間、そのフラグをどのように渡すことができますか?また、絶対座標を使用する必要がある場合はどうしますか?私は記録し、マウス入力を正確にシミュレートしようとしているので、最初に記録されたものと一致するように座標を必要とします。 – Briscoooe
使用する必要がある他のフラグとその番号だけ。 'getFlags(kvp2.Key)のようなもの| 0x8000'を入力してください.Add line –
これでコードに変更を加えました。カーソルが右下ではなく左上に撃たれます。しかし、それは動き回る。これは記録された通りの動きをまねしますが、左上隅の微少な領域にしかありません。ここで起こっていることは何ですか?アプリケーションが画面サイズを約2cm x 2cmと考えているかのようです。これは、longsではなくintである座標に関連していますか? – Briscoooe