using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using OnTopReplica.Native; using OnTopReplica.Properties; namespace OnTopReplica.MessagePumpProcessors { /// /// HotKey registration helper. /// class HotKeyManager : BaseMessagePumpProcessor { public HotKeyManager() { Enabled = true; } delegate void HotKeyHandler(); /// /// Wraps hot key handler registration data. /// private class HotKeyHandlerRegistration : IDisposable { private HotKeyHandlerRegistration() { } private HotKeyHandlerRegistration(IntPtr hwnd, int key, HotKeyHandler handler) { if (hwnd == IntPtr.Zero) throw new ArgumentException(); if (handler == null) throw new ArgumentNullException(); _hwnd = hwnd; RegistrationKey = key; Handler = handler; } static int _lastUsedKey = 0; /// /// Registers a new hotkey and returns a handle to the registration. /// /// Returns null on failure. public static HotKeyHandlerRegistration Register(Form owner, int keyCode, int modifiers, HotKeyHandler handler) { var key = ++_lastUsedKey; if (!HotKeyMethods.RegisterHotKey(owner.Handle, key, modifiers, keyCode)) { Console.Error.WriteLine("Failed to create hotkey on keys {0}.", keyCode); return null; } return new HotKeyHandlerRegistration(owner.Handle, key, handler); } IntPtr _hwnd; public int RegistrationKey { get; private set; } public HotKeyHandler Handler { get; private set; } public void Dispose() { if (!HotKeyMethods.UnregisterHotKey(_hwnd, RegistrationKey)) { Console.Error.WriteLine("Failed to unregister hotkey #{0}.", RegistrationKey); } } } Dictionary _handlers = new Dictionary(); public override void Initialize(MainForm form) { base.Initialize(form); RefreshHotkeys(); } public override bool Process(ref Message msg) { if (Enabled && msg.Msg == HotKeyMethods.WM_HOTKEY) { int keyId = msg.WParam.ToInt32(); if (!_handlers.ContainsKey(keyId)) return false; _handlers[keyId].Handler.Invoke(); } return false; } public bool Enabled { get; set; } /// /// Refreshes registered hotkeys from Settings. /// /// /// Application settings contain hotkey registration strings that are used /// automatically by this registration process. /// public void RefreshHotkeys() { ClearHandlers(); RegisterHandler(Settings.Default.HotKeyCloneCurrent, HotKeyCloneHandler); RegisterHandler(Settings.Default.HotKeyShowHide, HotKeyShowHideHandler); } private void RegisterHandler(string spec, HotKeyHandler handler) { if (string.IsNullOrEmpty(spec)) return; //this can happen and is allowed => simply don't register if (handler == null) throw new ArgumentNullException(); int modifiers = 0, keyCode = 0; try { HotKeyMethods.TranslateStringToKeyValues(spec, out modifiers, out keyCode); } catch (ArgumentException) { //TODO: swallowed exception return; } var reg = HotKeyHandlerRegistration.Register(Form, keyCode, modifiers, handler); if(reg != null) _handlers.Add(reg.RegistrationKey, reg); } private void ClearHandlers() { foreach (var hotkey in _handlers) { hotkey.Value.Dispose(); } _handlers.Clear(); } protected override void Shutdown() { ClearHandlers(); } #region Hotkey callbacks /// /// Handles "show/hide" hotkey. Ensures the form is in restored state and switches /// between shown and hidden states. /// void HotKeyShowHideHandler() { Form.FullscreenManager.SwitchBack(); if (!Program.Platform.IsHidden(Form)) { Program.Platform.HideForm(Form); } else { Form.EnsureMainFormVisible(); } } /// /// Handles the "clone current" hotkey. /// void HotKeyCloneHandler() { var handle = Win32Helper.GetCurrentForegroundWindow(); if (handle.Handle == Form.Handle) return; Form.SetThumbnail(handle, null); } #endregion } }