我目前正在设计一个功能,可以搜索窗口图片上的子图片。如果搜索成功,则单击此子图片的中心。奇怪的是,它总是点击低于预期的位置。
搜索算法工作正常 - 我仍然检查它。提供的函数坐标是正确的。但ClientToScreen功能很奇怪。例如:
我的子图片是在x = 352,y = 70时发现的 - 坐标是相对于窗口的左上角。 窗口的左上角相对于屏幕位于x = 91,y = 303。 所以,我希望坐标相对于屏幕点击如下:
X_Click = Window.Left + X_Click_rel2Wnd = 352 + 91= 443;
Y_Click = Window.Top + Y_Click_rel2Wnd = 70 + 303 = 373;
该函数返回: 447/396
任何人都有想法,哪有错?
代码下方:
public static class ClickOnPointTool{
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
private const uint MOUSEEVENTF_RIGHTUP = 0x10;
private const uint MOUSEEVENTF_MIDDLEDOWN = 0x00000020;
private const uint MOUSEEVENTF_MIDDLEUP = 0x00000040;
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct TPoint{
public int X;
public int Y;
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool ClientToScreen(System. IntPtr hWnd, ref TPoint lpPoint);
#pragma warning disable 649
internal struct INPUT{
public System.UInt32 Type;
public MOUSEKEYBDHARDWAREINPUT Data;
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPArray), System.Runtime.InteropServices.In] INPUT[] pInputs, int cbSize);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
internal struct MOUSEKEYBDHARDWAREINPUT{
[System.Runtime.InteropServices.FieldOffset(0)]
public MOUSEINPUT Mouse;
}
internal struct MOUSEINPUT{
public System.Int32 X;
public System.Int32 Y;
public System.UInt32 MouseData;
public System.UInt32 Flags;
public System.UInt32 Time;
public System.IntPtr ExtraInfo;
}
#pragma warning restore 649
public static void ClickOnPoint(System.IntPtr wndHandle, int x, int y, bool KeepCursor = false, bool RightButton = false, bool DoubleClick = false, System.Data.DataTable WndBoundings = null){
int nTimes = 0;
TPoint clientPoint;
clientPoint.X = x;
clientPoint.Y = y;
System.Drawing.Point oldPos = System.Windows.Forms.Cursor.Position;
//System.Windows.Forms.MessageBox.Show("Click to " + clientPoint.X + " / " + clientPoint.Y + "");
if(DoubleClick){nTimes = 2;}else{nTimes = 1;}
/// get screen coordinates
if(WndBoundings == null){
ClientToScreen(wndHandle, ref clientPoint);
}else{
clientPoint.X += (int)WndBoundings.Rows[0]["Left"];
clientPoint.Y += (int)WndBoundings.Rows[0]["Top"];
}
//System.Windows.Forms.MessageBox.Show("Click to " + clientPoint.X + " / " + clientPoint.Y + "");
/// set cursor on coords, and press mouse
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(clientPoint.X, clientPoint.Y);
INPUT inputMouseDown = new INPUT();
inputMouseDown.Type = 0; /// input type mouse
if(RightButton){
inputMouseDown.Data.Mouse.Flags = MOUSEEVENTF_RIGHTDOWN; ///right button down
}else{
inputMouseDown.Data.Mouse.Flags = MOUSEEVENTF_LEFTDOWN; /// left button down
}
INPUT inputMouseUp = new INPUT();
inputMouseUp.Type = 0; /// input type mouse
if(RightButton){
inputMouseUp.Data.Mouse.Flags = MOUSEEVENTF_RIGHTUP; /// right button up
}else{
inputMouseUp.Data.Mouse.Flags = MOUSEEVENTF_LEFTUP; /// left button up
}
var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
for(int i=0;i<nTimes;i++){
SendInput((uint)inputs.Length, inputs, System.Runtime.InteropServices.Marshal.SizeOf(typeof(INPUT)));
}
/// return mouse
if(!KeepCursor){System.Windows.Forms.Cursor.Position = oldPos;}
}
}
答案 0 :(得分:1)
谢谢大家。运行良好:
private static System.Drawing.Point GetWindowCornerLU(System.IntPtr hWnd){
if(hWnd == System.IntPtr.Zero){throw new System.Exception("ERROR: Window handle is not referenced!");}
WindowHandle.User32.Rect rect = new WindowHandle.User32.Rect();
WindowHandle.User32.GetWindowRect(hWnd, ref rect);
return new System.Drawing.Point(rect.left, rect.top);
}
#pragma warning restore 649
public static void ClickOnPoint(System.IntPtr wndHandle, int x, int y, bool KeepCursor = false, bool RightButton = false, bool DoubleClick = false){
int nTimes = 0;
TPoint clientPoint;
clientPoint.X = x;
clientPoint.Y = y;
System.Drawing.Point oldPos = System.Windows.Forms.Cursor.Position;
//System.Windows.Forms.MessageBox.Show("Click to " + clientPoint.X + " / " + clientPoint.Y + "");
if(DoubleClick){nTimes = 2;}else{nTimes = 1;}
/// get screen coordinates
//ClientToScreen(wndHandle, ref clientPoint);
System.Drawing.Point prtLU = GetWindowCornerLU(wndHandle);
clientPoint.X += prtLU.X;
clientPoint.Y += prtLU.Y;
//System.Windows.Forms.MessageBox.Show("Click to " + clientPoint.X + " / " + clientPoint.Y + "");
/// set cursor on coords, and press mouse
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(clientPoint.X, clientPoint.Y);
INPUT inputMouseDown = new INPUT();
inputMouseDown.Type = 0; /// input type mouse
if(RightButton){
inputMouseDown.Data.Mouse.Flags = MOUSEEVENTF_RIGHTDOWN; ///right button down
}else{
inputMouseDown.Data.Mouse.Flags = MOUSEEVENTF_LEFTDOWN; /// left button down
}
INPUT inputMouseUp = new INPUT();
inputMouseUp.Type = 0; /// input type mouse
if(RightButton){
inputMouseUp.Data.Mouse.Flags = MOUSEEVENTF_RIGHTUP; /// right button up
}else{
inputMouseUp.Data.Mouse.Flags = MOUSEEVENTF_LEFTUP; /// left button up
}
var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
for(int i=0;i<nTimes;i++){
SendInput((uint)inputs.Length, inputs, System.Runtime.InteropServices.Marshal.SizeOf(typeof(INPUT)));
}
/// return mouse
if(!KeepCursor){System.Windows.Forms.Cursor.Position = oldPos;}
}
}