#region License Information (GPL v3) /* ShareX - A program that allows you to take screenshots and share any file type Copyright (c) 2007-2022 ShareX Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Optionally you can also view the license at . */ #endregion License Information (GPL v3) using System.Diagnostics; using System.Windows.Forms; namespace ShareX.HelpersLib { public class HotkeyForm : Form { public delegate void HotkeyEventHandler(ushort id, Keys key, Modifiers modifier); public event HotkeyEventHandler HotkeyPress; public int HotkeyRepeatLimit { get; set; } private Stopwatch repeatLimitTimer; public HotkeyForm() { HotkeyRepeatLimit = 1000; repeatLimitTimer = Stopwatch.StartNew(); } public void RegisterHotkey(HotkeyInfo hotkeyInfo) { if (hotkeyInfo != null && hotkeyInfo.Status != HotkeyStatus.Registered) { if (!hotkeyInfo.IsValidHotkey) { hotkeyInfo.Status = HotkeyStatus.NotConfigured; return; } if (hotkeyInfo.ID == 0) { string uniqueID = Helpers.GetUniqueID(); hotkeyInfo.ID = NativeMethods.GlobalAddAtom(uniqueID); if (hotkeyInfo.ID == 0) { DebugHelper.WriteLine("Unable to generate unique hotkey ID: " + hotkeyInfo); hotkeyInfo.Status = HotkeyStatus.Failed; return; } } if (!NativeMethods.RegisterHotKey(Handle, hotkeyInfo.ID, (uint)hotkeyInfo.ModifiersEnum, (uint)hotkeyInfo.KeyCode)) { NativeMethods.GlobalDeleteAtom(hotkeyInfo.ID); DebugHelper.WriteLine("Unable to register hotkey: " + hotkeyInfo); hotkeyInfo.ID = 0; hotkeyInfo.Status = HotkeyStatus.Failed; return; } hotkeyInfo.Status = HotkeyStatus.Registered; } } public bool UnregisterHotkey(HotkeyInfo hotkeyInfo) { if (hotkeyInfo != null) { if (hotkeyInfo.ID > 0) { bool result = NativeMethods.UnregisterHotKey(Handle, hotkeyInfo.ID); if (result) { NativeMethods.GlobalDeleteAtom(hotkeyInfo.ID); hotkeyInfo.ID = 0; hotkeyInfo.Status = HotkeyStatus.NotConfigured; return true; } } hotkeyInfo.Status = HotkeyStatus.Failed; } return false; } protected override void WndProc(ref Message m) { if (m.Msg == (int)WindowsMessages.HOTKEY && CheckRepeatLimitTime()) { ushort id = (ushort)m.WParam; Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); Modifiers modifier = (Modifiers)((int)m.LParam & 0xFFFF); OnKeyPressed(id, key, modifier); return; } base.WndProc(ref m); } protected void OnKeyPressed(ushort id, Keys key, Modifiers modifier) { HotkeyPress?.Invoke(id, key, modifier); } private bool CheckRepeatLimitTime() { if (HotkeyRepeatLimit > 0) { if (repeatLimitTimer.ElapsedMilliseconds >= HotkeyRepeatLimit) { repeatLimitTimer.Reset(); repeatLimitTimer.Start(); } else { return false; } } return true; } } }