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 SuperForm
    {
        private Form form;
        private IntPtr handle = IntPtr.Zero;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="_form"></param>
        public SuperForm(Form _form)
        {
            form = _form;
            handle = form.Handle;
            wndProcDelegate = new WndProcDelegate(WndProc);
            oldWndFunc = SetWindowLong(handle, MyDb.RyWin32.GWL_WNDPROC, wndProcDelegate);
        }
        /// <summary>
        /// 析构
        /// </summary>
        ~SuperForm()
        {
            User32.SetWindowLong(handle, MyDb.RyWin32.GWL_WNDPROC, oldWndFunc);
        }
        private bool isMouseDown = false;
        private Point FormLocation;     //form的location
        private Point mouseOffset;      //鼠标的按下位置
        const int HTLEFT = 10;
        const int HTRIGHT = 11;
        const int HTTOP = 12;
        const int HTTOPLEFT = 13;
        const int HTTOPRIGHT = 14;
        const int HTBOTTOM = 15;
        const int HTBOTTOMLEFT = 0x10;
        const int HTBOTTOMRIGHT = 17;
        private readonly IntPtr oldWndFunc;
        private delegate IntPtr WndProcDelegate(IntPtr hwnd, int Msg, IntPtr wParam, IntPtr lParam);
        private readonly WndProcDelegate wndProcDelegate;
        [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, WndProcDelegate wndProcDelegate);
        /// <summary>
        /// 设置让窗体支持移动
        /// </summary>
        public void SetFormMove(Control ctl)
        {
            ctl.MouseMove += new MouseEventHandler((object o, MouseEventArgs e) =>
            {
                try
                {
                    int _x = 0;
                    int _y = 0;
                    if (isMouseDown)
                    {
                        Point pt = Control.MousePosition;
                        _x = mouseOffset.X - pt.X;
                        _y = mouseOffset.Y - pt.Y;

                        form.Location = new Point(FormLocation.X - _x, FormLocation.Y - _y);
                    }
                }
                catch (Exception) { }
            });
            ctl.MouseDown+=new MouseEventHandler((object o, MouseEventArgs e) =>
            {
                try
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        isMouseDown = true;
                        FormLocation = form.Location;
                        mouseOffset = Control.MousePosition;
                    }
                }
                catch (Exception) { }
            });
            ctl.MouseUp+=new MouseEventHandler((object o, MouseEventArgs e) =>
            {
                isMouseDown = false;
            });

        }
        /// <summary>
        /// 是否允许可调节大小
        /// </summary>
        public bool Resizable { get; set; }
        /// <summary>
        /// 可调节窗体大小的宽度
        /// </summary>
        public int ResizeBorderWidth { get; set; } = 5;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="m"></param>
        protected virtual void WndProc(ref Message m)
        {
            m.Result = User32.CallWindowProc(oldWndFunc, m.HWnd, m.Msg, m.WParam, m.LParam);
            switch (m.Msg)
            {
                case 0x0084:
                    //base.WndProc(ref m);
                    if (!Resizable) { return; }
                    Point vPoint = new Point((int)m.LParam & 0xFFFF,
                        (int)m.LParam >> 16 & 0xFFFF);
                    vPoint =form.PointToClient(vPoint);
                    if (vPoint.X <= ResizeBorderWidth)
                        if (vPoint.Y <= ResizeBorderWidth)
                            m.Result = (IntPtr)HTTOPLEFT;
                        else if (vPoint.Y >= form.ClientSize.Height - ResizeBorderWidth)
                            m.Result = (IntPtr)HTBOTTOMLEFT;
                        else m.Result = (IntPtr)HTLEFT;
                    else if (vPoint.X >= form.ClientSize.Width - ResizeBorderWidth)
                        if (vPoint.Y <= ResizeBorderWidth)
                            m.Result = (IntPtr)HTTOPRIGHT;
                        else if (vPoint.Y >= form.ClientSize.Height - ResizeBorderWidth)
                            m.Result = (IntPtr)HTBOTTOMRIGHT;
                        else m.Result = (IntPtr)HTRIGHT;
                    else if (vPoint.Y <= ResizeBorderWidth)
                        m.Result = (IntPtr)HTTOP;
                    else if (vPoint.Y >= form.ClientSize.Height - ResizeBorderWidth)
                        m.Result = (IntPtr)HTBOTTOM;
                    break;
                case 0x0201://鼠标左键按下的消息 
                            //m.Msg = 0x00A1;//更改消息为非客户区按下鼠标 
                            //m.LParam = IntPtr.Zero;//默认值 
                            //m.WParam = new IntPtr(2);//鼠标放在标题栏内 

                    //以下做了一些修正，确保放大缩小按钮区域可以正常使用
                    Point point = Control.MousePosition;
                    point = form.PointToClient(point);
                    if (point.X < form.Width - 100 && point.Y < 30)
                    {
                        m.Msg = 0x00A1;//更改消息为非客户区按下鼠标 
                        m.LParam = IntPtr.Zero;//默认值 
                        m.WParam = new IntPtr(2);//鼠标放在标题栏内 
                    }
                    //base.WndProc(ref m);
                    break;
                default:
                    //base.WndProc(ref m);
                    break;
            }
        }
        private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)
        {
            System.Windows.Forms.Message m = System.Windows.Forms.Message.Create(hWnd, msg, wParam, lParam);
            WndProc(ref m);
            return m.Result;
        }
    }
}
