windowcapture
исходный код / App/LauncherApp.cs

LauncherApp.cs

135 строк · 5,503 байт · модуль App
  1using System;
  2using System.Drawing;
  3using System.Runtime.InteropServices;
  4using System.Threading;
  5using System.Windows.Forms;
  6using WindowCapture.UI;
  7
  8namespace WindowCapture.App
  9{
 10    /// <summary>The launcher hub: a tray icon + a global hotkey (Ctrl+Alt+Space) that pops a
 11    /// radial menu to start the separate apps. Re-running "--launcher" (or the launcher hotkey)
 12    /// surfaces the wheel.</summary>
 13    public class LauncherApp : ApplicationContext
 14    {
 15        private NotifyIcon tray;
 16        private HotkeyWindow hotkeyWindow;
 17        private LauncherForm wheel;
 18        private EventWaitHandle showEvent;
 19        private Thread showListener;
 20        private volatile bool stopping;
 21
 22        public LauncherApp()
 23        {
 24            hotkeyWindow = new HotkeyWindow();
 25            hotkeyWindow.HotkeyPressed += ShowWheel;
 26
 27            var menu = new ContextMenuStrip();
 28            menu.Items.Add("Открыть меню (Ctrl+Alt+Space)", null, delegate { ShowWheel(); });
 29            menu.Items.Add("-");
 30            foreach (AppMode m in new[] { AppMode.Screenshot, AppMode.TextAssist, AppMode.Clipboard, AppMode.Soundpad, AppMode.Search })
 31            {
 32                var mm = m; // capture
 33                menu.Items.Add(AppModes.Title(mm), null, delegate { AppModes.Launch(mm); });
 34            }
 35            menu.Items.Add("-");
 36            menu.Items.Add("Настройки", null, delegate { try { using (var d = new SettingsDialog()) d.ShowDialog(); } catch { } });
 37            menu.Items.Add("Выход", null, delegate { ExitThread(); });
 38
 39            tray = new NotifyIcon
 40            {
 41                Icon = AppModes.CreateDiscIcon(Color.FromArgb(120, 170, 240)),
 42                Text = "WindowCapture — Лаунчер (Ctrl+Alt+Space)",
 43                Visible = true,
 44                ContextMenuStrip = menu
 45            };
 46            tray.MouseClick += delegate(object s, MouseEventArgs e) { if (e.Button == MouseButtons.Left) ShowWheel(); };
 47
 48            SetupShowListener();
 49        }
 50
 51        private void SetupShowListener()
 52        {
 53            bool created;
 54            showEvent = new EventWaitHandle(false, EventResetMode.AutoReset, AppModes.ShowEventName(AppMode.Launcher), out created);
 55            showListener = new Thread(delegate ()
 56            {
 57                while (!stopping)
 58                {
 59                    try { if (showEvent.WaitOne(500) && !stopping && hotkeyWindow != null) hotkeyWindow.BeginInvoke(new Action(ShowWheel)); }
 60                    catch { }
 61                }
 62            }) { IsBackground = true };
 63            showListener.Start();
 64        }
 65
 66        private void ShowWheel()
 67        {
 68            if (wheel != null && !wheel.IsDisposed) { try { wheel.Activate(); } catch { } return; }
 69            wheel = new LauncherForm();
 70            wheel.ItemChosen += delegate(AppMode m) { AppModes.Launch(m); };
 71            wheel.FormClosed += delegate { wheel = null; };
 72            wheel.Show();
 73        }
 74
 75        protected override void Dispose(bool disposing)
 76        {
 77            if (disposing)
 78            {
 79                stopping = true;
 80                try { if (showEvent != null) showEvent.Set(); } catch { }
 81                if (tray != null) { tray.Visible = false; tray.Dispose(); }
 82                if (hotkeyWindow != null) hotkeyWindow.Dispose();
 83                if (wheel != null && !wheel.IsDisposed) wheel.Dispose();
 84            }
 85            base.Dispose(disposing);
 86        }
 87
 88        /// <summary>Invisible message-only-ish window that owns the global hotkey registration.</summary>
 89        private class HotkeyWindow : Form
 90        {
 91            public event Action HotkeyPressed;
 92            [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
 93            [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
 94            private const uint MOD_ALT = 0x1, MOD_CONTROL = 0x2, MOD_NOREPEAT = 0x4000;
 95            private const int WM_HOTKEY = 0x0312;
 96            private const int HOTKEY_ID = 0xB001;
 97            private bool registered;
 98
 99            public HotkeyWindow()
100            {
101                FormBorderStyle = FormBorderStyle.None;
102                ShowInTaskbar = false;
103                StartPosition = FormStartPosition.Manual;
104                Location = new Point(-2000, -2000);
105                Size = new Size(1, 1);
106                var force = Handle; // force handle creation
107            }
108
109            protected override void OnHandleCreated(EventArgs e)
110            {
111                base.OnHandleCreated(e);
112                try { registered = RegisterHotKey(Handle, HOTKEY_ID, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x20 /*VK_SPACE*/); }
113                catch { registered = false; }
114            }
115
116            protected override void SetVisibleCore(bool value) { base.SetVisibleCore(false); } // never visible
117
118            protected override void WndProc(ref Message m)
119            {
120                if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == HOTKEY_ID)
121                {
122                    var h = HotkeyPressed;
123                    if (h != null) h();
124                }
125                base.WndProc(ref m);
126            }
127
128            protected override void Dispose(bool disposing)
129            {
130                if (disposing && registered) { try { UnregisterHotKey(Handle, HOTKEY_ID); } catch { } }
131                base.Dispose(disposing);
132            }
133        }
134    }
135}