using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using WinAPI;

namespace ryCommon
{
    /// <summary>
    /// 对鼠标或键盘的自动化操作
    /// </summary>
   public class Auto
    {
        /// <summary>
        /// 鼠标左键
        /// </summary>
        public const int MK_LBUTTON = 1;//鼠标左键
        /// <summary>
        /// 鼠标中键
        /// </summary>
        public const int MK_MBUTTON = 16;//鼠标中键
        /// <summary>
        /// 鼠标右键
        /// </summary>
        public const int MK_RBUTTON = 2;//鼠标右键
        //移动鼠标 
        //const int MOUSEEVENTF_MOVE = 0x0001;
        //模拟鼠标左键按下 
        const int MOUSEEVENTF_LEFTDOWN = 0x0002;
        //模拟鼠标左键抬起 
        const int MOUSEEVENTF_LEFTUP = 0x0004;
        //模拟鼠标右键按下 
        const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
        //模拟鼠标右键抬起 
        const int MOUSEEVENTF_RIGHTUP = 0x0010;
        //模拟鼠标中键按下 
        const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
        //模拟鼠标中键抬起 
        const int MOUSEEVENTF_MIDDLEUP = 0x0040;
        //标示是否采用绝对坐标 
        //const int MOUSEEVENTF_ABSOLUTE = 0x8000;
        //模拟鼠标滚轮滚动操作，必须配合dwData参数
        //const int MOUSEEVENTF_WHEEL = 0x0800;
        const uint WM_LBUTTONDOWN = 0x201;
        const uint WM_LBUTTONUP = 0x202;
        const int WM_RBUTTONDOWN = 516; // 鼠标右键按下  
        const int WM_RBUTTONUP = 517; // 鼠标右键抬起  
        const int WM_MBUTTONDOWN = 519; // 鼠标中键按下  
        const int WM_MBUTTONUP = 520; // 鼠标中键抬起  
        const uint WM_MOUSEWHEEL = 0x020A;
        const uint WM_MOUSEMOVE = 0x0200;
        const uint WM_KEYDOWN = 0x0100;
        const uint WM_KEYUP = 0x0101;

        private static int MakeLParam(int LoWord, int HiWord)
        {
            return ((HiWord << 16) | (LoWord & 0xffff));
        }
        /// <summary>
        /// 模拟键盘按键
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="key"></param>
        /// <param name="isPress">按下还是抬起</param>
        public static void KeyButton(IntPtr hWnd, int key, bool isPress)
        {
            if (isPress)
               User32.SendMessage(hWnd, WM_KEYDOWN, key, 0);
            else
                User32.SendMessage(hWnd, WM_KEYUP, key, 0);
        }
        /// <summary>
        /// 鼠标滚轮
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="mouse_position"></param>
        /// <param name="delta"></param>
        public static void Mouse_Wheel(IntPtr hWnd, Point mouse_position, int delta)
        {
            User32.SendMessage(hWnd, WM_MOUSEWHEEL, delta * 65536, mouse_position.X + mouse_position.Y * 65536);
        }
        /// <summary>
        /// 鼠标移动
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="button"></param>
        /// <param name="mouse_position"></param>
        public static void Mouse_Move(IntPtr hWnd, int button, Point mouse_position)
        {
            User32.SendMessage(hWnd, WM_MOUSEMOVE, button, mouse_position.X + mouse_position.Y * 65536);
        }
        /// <summary>
        /// 自定义鼠标按下或抬起
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="button"></param>
        /// <param name="mouse_position"></param>
        /// <param name="isPress"></param>
        public static void Mouse_Button(IntPtr hWnd,MouseButtons button, Point mouse_position, bool isPress)
        {
            if (button == MouseButtons.Middle)
            {
                if (isPress)
                    User32.SendMessage(hWnd, WM_MBUTTONDOWN, MK_MBUTTON, mouse_position.X + mouse_position.Y * 65536);
                else
                    User32.SendMessage(hWnd, WM_MBUTTONUP, 0, mouse_position.X + mouse_position.Y * 65536);
            }
            else if (button == MouseButtons.Right)
            {
                if (isPress)
                    User32.SendMessage(hWnd, WM_RBUTTONDOWN, MK_RBUTTON, mouse_position.X + mouse_position.Y * 65536);
                else
                    User32.SendMessage(hWnd, WM_RBUTTONUP, 0, mouse_position.X + mouse_position.Y * 65536);
            }
            else if (button == MouseButtons.Left)
            {
                if (isPress)
                    User32.SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, mouse_position.X + mouse_position.Y * 65536);
                else
                    User32.SendMessage(hWnd, WM_LBUTTONUP, 0, mouse_position.X + mouse_position.Y * 65536);
            }
        }
        /// <summary>
        ///左键单击鼠标(支持后台单击)
        /// </summary>
        /// <param name="handle">指定要发送单击命令的句柄</param>
        /// <param name="x">坐标x(句柄内的坐标,非屏幕坐标)</param>
        /// <param name="y">坐标y(句柄内的坐标,非屏幕坐标)</param>
        public static void LeftClick(IntPtr handle, int x, int y)
        {
            User32.SendMessage(handle, WM_LBUTTONDOWN, 1, MakeLParam(x, y));
            User32.SendMessage(handle, WM_LBUTTONUP, 0, MakeLParam(x, y));
        }
        /// <summary>
        ///左键单击鼠标(支持后台单击)
        /// </summary>
        /// <param name="handle">指定要发送单击命令的句柄</param>
        /// <param name="point">坐标(句柄内的坐标,非屏幕坐标)</param>
        public static void LeftClick(IntPtr handle,Point point)
        {
            LeftClick(handle,point.X,point.Y);
        }
        /// <summary>
        ///右键单击鼠标(支持后台单击)
        /// </summary>
        /// <param name="handle">指定要发送单击命令的句柄</param>
        /// <param name="x">坐标x(句柄内的坐标,非屏幕坐标)</param>
        /// <param name="y">坐标y(句柄内的坐标,非屏幕坐标)</param>
        public static void RightClick(IntPtr handle, int x, int y)
        {
            User32.SendMessage(handle, WM_RBUTTONDOWN, 1, MakeLParam(x, y));
            User32.SendMessage(handle, WM_RBUTTONUP, 0, MakeLParam(x, y));
        }
        /// <summary>
        ///右键单击鼠标(支持后台单击)
        /// </summary>
        /// <param name="handle">指定要发送单击命令的句柄</param>
        /// <param name="point">坐标(句柄内的坐标,非屏幕坐标)</param>
        public static void RightClick(IntPtr handle, Point point)
        {
            RightClick(handle, point.X, point.Y);
        }
        /// <summary>
        ///中键单击鼠标(支持后台单击)
        /// </summary>
        /// <param name="handle">指定要发送单击命令的句柄</param>
        /// <param name="x">坐标x(句柄内的坐标,非屏幕坐标)</param>
        /// <param name="y">坐标y(句柄内的坐标,非屏幕坐标)</param>
        public static void MiddleClick(IntPtr handle, int x, int y)
        {
            User32.SendMessage(handle, WM_MBUTTONDOWN, 1, MakeLParam(x, y));
            User32.SendMessage(handle, WM_MBUTTONUP, 0, MakeLParam(x, y));
        }
        /// <summary>
        ///中键单击鼠标(支持后台单击)
        /// </summary>
        /// <param name="handle">指定要发送单击命令的句柄</param>
        /// <param name="point">坐标(句柄内的坐标,非屏幕坐标)</param>
        public static void MiddleClick(IntPtr handle, Point point)
        {
            MiddleClick(handle, point.X, point.Y);
        }
        /// <summary>
        ///左键单击鼠标(不支持后台单击)
        /// </summary>
        /// <param name="x">坐标x(屏幕坐标)</param>
        /// <param name="y">坐标y(屏幕坐标)</param>
        public static void LeftClick(int x, int y)
        {
            Cursor.Position = new System.Drawing.Point(x,y);
            User32.mouse_event(MOUSEEVENTF_LEFTDOWN , 0,0, 0, 0);
            User32.mouse_event(MOUSEEVENTF_LEFTUP, 0,0, 0, 0);
        }
        /// <summary>
        ///左键单击鼠标(不支持后台单击)
        /// </summary>
        /// <param name="point">坐标(屏幕坐标)</param>
        public static void LeftClick(Point point)
        {
            LeftClick(point.X, point.Y); 
        }
        /// <summary>
        ///右键单击鼠标(不支持后台单击)
        /// </summary>
        /// <param name="x">坐标x(屏幕坐标)</param>
        /// <param name="y">坐标y(屏幕坐标)</param>
        public static void RightClick(int x, int y)
        {
            Cursor.Position = new System.Drawing.Point(x, y);
            User32.mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
            User32.mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
        }
        /// <summary>
        ///右键单击鼠标(不支持后台单击)
        /// </summary>
        /// <param name="point">坐标(屏幕坐标)</param>
        public static void RightClick(Point point)
        {
            RightClick(point.X, point.Y);
        }
        /// <summary>
        ///中键单击鼠标(不支持后台单击)
        /// </summary>
        /// <param name="x">坐标x(屏幕坐标)</param>
        /// <param name="y">坐标y(屏幕坐标)</param>
        public static void MiddleClick(int x, int y)
        {
            Cursor.Position = new System.Drawing.Point(x, y);
            User32.mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
            User32.mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
        }
        /// <summary>
        ///中键单击鼠标(不支持后台单击)
        /// </summary>
        /// <param name="point">坐标(屏幕坐标)</param>
        public static void MiddleClick(Point point)
        {
            MiddleClick(point.X, point.Y);
        }
        /// <summary>
        /// 粘贴文本
        /// </summary>
        /// <param name="text"></param>
        public static void PasteText(string text)
        {
            try
            {
                Clipboard.SetText(text);
            }
            catch { }
            SendKeys.SendWait("^{V}");
        }
        /// <summary>
        /// 获取指定句柄的大小及位置
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static Rectangle GetRect(IntPtr handle, out Size size)
        {
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            Rectangle windowRect = new Rectangle();
            size = new Size(0, 0);
            if (hdcSrc == IntPtr.Zero) { return windowRect; }
            User32.GetWindowRect(handle, out windowRect);
            int width = windowRect.Right - windowRect.Left;
            int height = windowRect.Bottom - windowRect.Top;
            size = new Size(width, height);
            return windowRect;
        }
        /// <summary>
        /// 设置指定句柄的大小
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="size"></param>
        public static void SetRect(IntPtr handle, Size size)
        {
            var rect = GetRect(handle, out _);
            User32.MoveWindow(handle, rect.Left, rect.Top, size.Width, size.Height, true);
        }
        /// <summary>
        /// 判断鼠标位置是不是在指定的矩形中
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="mouse_position"></param>
        /// <returns></returns>
        public static bool IsInRect(Rectangle rect, Point mouse_position)
        {
            return mouse_position.X >= rect.Left && mouse_position.X <= rect.Right && mouse_position.Y >= rect.Top && mouse_position.Y <= rect.Bottom;
        }
        /// <summary>
        /// 判断2张图是否相似度超90
        /// </summary>
        /// <param name="bmpOne"></param>
        /// <param name="bmpTwo"></param>
        /// <returns></returns>
        public static bool ImageEquals(Bitmap bmpOne, Bitmap bmpTwo)
        {
            if (bmpOne == null && bmpTwo == null) { return true; }
            if (bmpOne == null || bmpTwo == null) { return false; }
            for (int i = 0; i < bmpOne.Width; i++)
            {
                for (int j = 0; j < bmpOne.Height; j++)
                {
                    double xsd = GetXsd(bmpOne.GetPixel(i, j), bmpTwo.GetPixel(i, j));
                    if (xsd < 90)
                        return false;
                }
            }
            return true;
        }
        /// <summary>
        /// /获取2种颜色的相似度,范围为0~100
        /// </summary>
        /// <param name="c1"></param>
        /// <param name="c2"></param>
        /// <returns></returns>
        public static double GetXsd(Color c1, Color c2)
        {
            //像素点相似度公式(255 - abs(r1 - r2) * 0.297 - abs(g1 - g2) * 0.593 - abs(b1 - b2) * 0.11) / 255
            double xsd2 = (255 - Math.Abs(c1.R - c2.R) * 0.297 - Math.Abs(c1.G - c2.G) * 0.593 - Math.Abs(c1.B - c2.B) * 0.11) / 255;
            return xsd2 * 100;
        }

    }
}
