using AppLauncher.Models; using AppLauncher.Windows.Forms; using Newtonsoft.Json; using RyzStudio.Windows.Forms; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; namespace AppLauncher { public partial class MainForm : AForm { [DllImport("user32.dll")] protected static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk); [DllImport("user32.dll")] protected static extern bool UnregisterHotKey(IntPtr hWnd, int id); //protected const int MOD_ALT = 0x1; //protected const int MOD_CONTROL = 0x2; //protected const int MOD_SHIFT = 0x4; //protected const int MOD_WIN = 0x8; protected const int WM_HOTKEY = 0x312; protected OptionsForm optionsForm = null; protected string sessionFilename = null; public MainForm() : base() { InitializeComponent(); this.StartPosition = FormStartPosition.WindowsDefaultBounds; } protected override void OnLoad(EventArgs e) { ThreadControl.SetVisible(this, false); base.OnLoad(e); } protected async override void OnShown(EventArgs e) { base.OnShown(e); string jsonfigFilename = Path.ChangeExtension(Application.ExecutablePath, "jsonfig"); if (File.Exists(jsonfigFilename)) { await loadFile(jsonfigFilename); } else { this.CurrentSession = new LauncherSession(); ThreadControl.SetVisible(this, true); } } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); if (this.CurrentSession == null) this.CurrentSession = new LauncherSession(); if (string.IsNullOrWhiteSpace(sessionFilename)) { // do nothing } else { if (this.CurrentSession.AutoSave == LauncherSession.AutoSaveOption.Prompt) { DialogResult dr = MessageBox.Show("Save existing session?", "Exit", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (dr == DialogResult.Yes) { bool rv = saveFile(sessionFilename, false); if (!rv) { e.Cancel = true; } } else if (dr == DialogResult.No) { // do nothing } else if (dr == DialogResult.Cancel) { e.Cancel = true; } } else if (this.CurrentSession.AutoSave == LauncherSession.AutoSaveOption.Yes) { saveFile(sessionFilename, false); } } if (this.CurrentSession.HotKey != null) { if (this.CurrentSession.HotKey.KeyCode != Keys.None) { UnregisterHotKey((IntPtr)Handle, 1); } } } protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg != WM_HOTKEY) return; switch (m.WParam.ToInt32()) { case 1: this.Visible = !this.Visible; break; default: break; } } public LauncherSession CurrentSession { get; set; } = null; /// /// New /// /// /// private void toolStripMenuItem5_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(sessionFilename)) { newSession(); } else { DialogResult dr = MessageBox.Show("Save existing session?", "New session", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (dr == DialogResult.Yes) { bool rv = saveFile(sessionFilename, false); if (rv) { newSession(); sessionFilename = null; } } else if (dr == DialogResult.No) { newSession(); sessionFilename = null; } else if (dr == DialogResult.Cancel) { return; } } } /// /// Open /// /// /// private async void toolStripMenuItem7_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(sessionFilename)) { if (openFileDialog1.ShowDialog() == DialogResult.OK) { await loadFile(openFileDialog1.FileName); } } else { DialogResult dr = MessageBox.Show("Save existing session?", "Open session", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (dr == DialogResult.Yes) { bool rv = saveFile(sessionFilename, false); if (rv) { if (openFileDialog1.ShowDialog() == DialogResult.OK) { await loadFile(openFileDialog1.FileName); } } } else if (dr == DialogResult.No) { if (openFileDialog1.ShowDialog() == DialogResult.OK) { await loadFile(openFileDialog1.FileName); } } else if (dr == DialogResult.Cancel) { return; } } } /// /// Close /// /// /// private void toolStripMenuItem8_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(sessionFilename)) { flowLayoutPanel1.Controls.Clear(); } else { DialogResult dr = MessageBox.Show("Save existing session?", "Close session", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (dr == DialogResult.Yes) { bool rv = saveFile(sessionFilename, false); if (rv) { flowLayoutPanel1.Controls.Clear(); sessionFilename = null; } } else if (dr == DialogResult.No) { flowLayoutPanel1.Controls.Clear(); sessionFilename = null; } else if (dr == DialogResult.Cancel) { return; } } } /// /// Save /// /// /// private void toolStripMenuItem6_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(sessionFilename)) { saveAsFile(); } else { saveFile(sessionFilename, true); } } /// /// Save As /// /// /// private void toolStripMenuItem2_Click(object sender, EventArgs e) => saveAsFile(); /// /// Always On Top /// /// /// private void toolStripMenuItem1_Click(object sender, EventArgs e) => this.TopMost = !this.TopMost; /// /// Exit /// /// /// private void exitToolStripMenuItem_Click(object sender, EventArgs e) => this.Close(); private void optionToolStripMenuItem_Click(object sender, EventArgs e) { if (optionsForm == null) optionsForm = new OptionsForm(this); optionsForm.ShowDialog(); invalidateHotKey(); } protected override void imageBox3_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (this.CurrentSession == null) { this.Close(); } else { if (this.CurrentSession.HideOnClose) { this.Visible = !this.Visible; } else { this.Close(); } } } } protected async Task collapseWindow(int width, int increment = 6) { await Task.Run(() => { while (this.Width > width) { ThreadControl.SetWidth(this, (this.Width - increment)); Application.DoEvents(); } ThreadControl.SetWidth(this, width); }); } protected async Task expandWindow(int width, int increment = 8) { await Task.Run(() => { while (this.Width < width) { ThreadControl.SetWidth(this, (this.Width + increment)); Application.DoEvents(); } ThreadControl.SetWidth(this, width); }); } protected void invalidateHotKey() { if (this.InvokeRequired) { this.Invoke(new MethodInvoker(() => { UnregisterHotKey((IntPtr)Handle, 1); })); } else { UnregisterHotKey((IntPtr)Handle, 1); } if (this.CurrentSession.HotKey != null) { if (this.CurrentSession.HotKey.KeyCode != Keys.None) { if (this.InvokeRequired) { this.Invoke(new MethodInvoker(() => { RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.HotKey.ModifierCode, this.CurrentSession.HotKey.Key); })); } else { RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.HotKey.ModifierCode, this.CurrentSession.HotKey.Key); } } } } protected async Task loadFile(string filename) { await Task.Run(() => { if (isBusy) { return; } if (string.IsNullOrWhiteSpace(filename)) { return; } if (!File.Exists(filename)) { return; } string sourceCode = null; try { sessionFilename = filename; sourceCode = File.ReadAllText(sessionFilename); } catch (Exception exc) { MessageBox.Show(exc.Message, "Load session"); return; } if (string.IsNullOrWhiteSpace(sourceCode)) { return; } LauncherSession loadedSession = JsonConvert.DeserializeObject(sourceCode); if (loadedSession == null) { return; } // load options this.CurrentSession = loadedSession.ToSimple(); // load tiles int maxWidth = 0; ThreadControl.Clear(flowLayoutPanel1); if (loadedSession.Groups != null) { foreach (TileGroupModel item in loadedSession.Groups) { TTilePanelLayout panel = new TTilePanelLayout(item); maxWidth = Math.Max(maxWidth, panel.Width); ThreadControl.Add(flowLayoutPanel1, panel); } } // ui ThreadControl.SetSize(this, (maxWidth + SystemInformation.VerticalScrollBarWidth + 20 + flowLayoutPanel1.Left), this.CurrentSession.DefaultHeight); // ThreadControl.SetTopMost(this, this.CurrentSession.AlwaysOnTop); ThreadControl.SetVisible(this, true); if (this.InvokeRequired) { this.Invoke(new MethodInvoker(() => { this.Focus(); })); } else { this.Focus(); } // hotkey invalidateHotKey(); }); } protected void newSession() { int maxWidth = 0; flowLayoutPanel1.Controls.Clear(); TTilePanelLayout panel = new TTilePanelLayout(new TileGroupModel() { Title = "New Group", IsExpanded = true, GridSize = new Size(8, 1) }); maxWidth = Math.Max(maxWidth, panel.Width); flowLayoutPanel1.Controls.Add(panel); this.Width = maxWidth + SystemInformation.VerticalScrollBarWidth + 20 + flowLayoutPanel1.Left; } protected bool saveFile(string filename, bool showNotices = true) { if (isBusy) { return false; } if (string.IsNullOrWhiteSpace(filename)) { return false; } if (flowLayoutPanel1.Controls.Count <= 0) { return true; } isBusy = true; // update session this.CurrentSession.DefaultHeight = this.Height; this.CurrentSession.AlwaysOnTop = this.TopMost; // save LauncherSession saveSession = this.CurrentSession.ToSimple(); saveSession.Groups = new List(); for (int i = 0; i < flowLayoutPanel1.Controls.Count; i++) { if (flowLayoutPanel1.Controls[i].GetType() != typeof(TTilePanelLayout)) { continue; } TTilePanelLayout container = flowLayoutPanel1.Controls[i] as TTilePanelLayout; saveSession.Groups.Add(container.Model); } try { File.WriteAllText(filename, JsonConvert.SerializeObject(saveSession)); if (showNotices) { MessageBox.Show("Session saved!", "Save session", MessageBoxButtons.OK, MessageBoxIcon.Information); } } catch (Exception exc) { MessageBox.Show(exc.Message, "Save session"); return false; } isBusy = false; return true; } protected bool saveAsFile() { if (isBusy) { return false; } if (saveFileDialog1.ShowDialog() == DialogResult.OK) { bool rv = saveFile(saveFileDialog1.FileName); if (rv) { sessionFilename = saveFileDialog1.FileName; } return rv; } return false; } private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e) { toolStripMenuItem1.Checked = this.TopMost; toolStripMenuItem6.Enabled = !string.IsNullOrWhiteSpace(sessionFilename); } private void viewHelpToolStripMenuItem_Click(object sender, EventArgs e) { try { System.Diagnostics.Process.Start("https://www.hiimray.co.uk/software-fizzy-launcher"); } catch { // do nothing } } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) => MessageBox.Show(Application.ProductName + " v" + Application.ProductVersion, "About", MessageBoxButtons.OK, MessageBoxIcon.Information); } }