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

namespace SysFuns
{
    /// <summary>
    /// 功能键
    /// </summary>
    [Flags()]
    public enum KeyModifiers
    {
        /// <summary>
        /// 无
        /// </summary>
        None = 0,
        /// <summary>
        /// Alt键
        /// </summary>
        Alt = 1,
        /// <summary>
        /// Ctrl键
        /// </summary>
        Ctrl = 2,
        /// <summary>
        /// Shift键
        /// </summary>
        Shift = 4,
        /// <summary>
        /// Win键
        /// </summary>
        WindowsKey = 8
    }
    /// <summary>
    /// 热键类
    /// </summary>
    public class WinHotReg : System.Windows.Forms.IMessageFilter
    {
        //如果函数执行成功，返回值不为0。
        //如果函数执行失败，返回值为0。要得到扩展错误信息，调用GetLastError。
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool RegisterHotKey(
            IntPtr hWnd,                //要定义热键的窗口的句柄
            int id,                     //定义热键ID（不能与其它ID重复）           
            KeyModifiers fsModifiers,   //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效
            Keys vk                     //定义热键的内容
            );

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool UnregisterHotKey(
            IntPtr hWnd,                //要取消热键的窗口的句柄
            int id                      //要取消热键的ID
            );

        readonly IntPtr handle;
        /// <summary>
        /// 热键类
        /// </summary>
        /// <param name="_handle"></param>
        public WinHotReg(IntPtr _handle)
        {
            handle = _handle;
            System.Windows.Forms.Application.AddMessageFilter(this);
        }
        /// <summary>
        /// 热键注销
        /// </summary>
        ~WinHotReg()
        {
            UnHotKey();
            System.Windows.Forms.Application.RemoveMessageFilter(this);
        }
        /// <summary>
        /// 热键是否有效
        /// </summary>
        public bool Enabled { get; set; } = true;
        /// <summary>
        /// 释放热键
        /// </summary>
        public void Free()
        {
            UnHotKey();
            System.Windows.Forms.Application.RemoveMessageFilter(this);
        }

        readonly List<HotKeyType> list_hotkey = new List<HotKeyType>();
        /// <summary>
        /// 注册热键
        /// </summary>
        /// <param name="id"></param>
        /// <param name="fsModifiers"></param>
        /// <param name="vk"></param>
        /// <returns></returns>
        public bool RegHotKey(int id, KeyModifiers fsModifiers, Keys vk)
        {
            bool result = RegisterHotKey(handle, id, fsModifiers, vk);
            if (result)
            {
                list_hotkey.Add(new HotKeyType(id, fsModifiers, vk));
            }
            return result;
        }
        /// <summary>
        /// 注册热键
        /// </summary>
        /// <param name="id"></param>
        /// <param name="fsModifiers"></param>
        /// <param name="vk"></param>
        /// <returns></returns>
        public bool RegHotKey(int id, int fsModifiers, Keys vk)
        {
            if (!Enum.IsDefined(typeof(KeyModifiers), fsModifiers))
            {
                return false;
            }
            bool result = RegisterHotKey(handle, id, (KeyModifiers)fsModifiers, vk);
            if (result)
            {
                list_hotkey.Add(new HotKeyType(id, (KeyModifiers)fsModifiers, vk));
            }
            return result;
        }
        /// <summary>
        /// 获取热键数量
        /// </summary>
        public int Count { get {  return list_hotkey.Count; }  }
        /// <summary>
        /// 删除热键
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool UnHotKey(int id)
        {
            bool result = UnregisterHotKey(handle, id);
            if (result)
            {
                var index = list_hotkey.FindIndex(a => a.id == id);
                if (index >= 0) { list_hotkey.RemoveAt(index); }
            }
            return result;
        }
        /// <summary>
        /// 删除所有热键
        /// </summary>
        public void UnHotKey()
        {
            for (int i = list_hotkey.Count - 1; i >= 0; i--)
            {
                HotKeyType item = (HotKeyType)list_hotkey[i];
                bool result = UnregisterHotKey(handle, item.id);
                if (result)
                {
                    list_hotkey.RemoveAt(i);
                }
            }
        }
        /// <summary>
        /// 删除所有热键
        /// </summary>
        public void Clear()
        {
            UnHotKey();
        }
        /// <summary>
        /// 热键事件
        /// </summary>
        /// <param name="HotKeyID"></param>
        public delegate void HotkeyEventHandler(int HotKeyID);
        /// <summary>
        /// 当使用热键时发生的事件
        /// </summary>
        public event HotkeyEventHandler OnHotkey;
        /// <summary>
        /// 热键消息过滤
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public bool PreFilterMessage(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == 0x312)
            {
                if (OnHotkey != null)
                {
                    if (!Enabled) { return true; }
                    for (int i = list_hotkey.Count - 1; i >= 0; i--)
                    {
                        HotKeyType item = (HotKeyType)list_hotkey[i];
                        if ((UInt32)m.WParam == item.id)
                        {
                            OnHotkey((int)m.WParam);
                            return true;
                        }
                        //OnHotkey((int)m.WParam);
                    }
                    //OnHotkey((int)m.WParam);
                }
            }
            return false;
        }
    }
    /// <summary>
    /// 热键类型
    /// </summary>
    public class HotKeyType
    {
        /// <summary>
        /// 热键id
        /// </summary>
        public int id;
        /// <summary>
        /// 功能键
        /// </summary>
        public KeyModifiers fsModifiers;
        /// <summary>
        /// 普通键
        /// </summary>
        public Keys vk;
        /// <summary>
        /// 热键类型
        /// </summary>
        /// <param name="id"></param>
        /// <param name="fsModifiers"></param>
        /// <param name="vk"></param>
        public HotKeyType(int id, KeyModifiers fsModifiers, Keys vk)
        {
            this.id = id;
            this.fsModifiers = fsModifiers;
            this.vk = vk;
        }
    }
}
