using FizzyLauncher.Models; using RyzStudio.Drawing; using RyzStudio.Text.Json; using RyzStudio.Windows.Forms; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text.Json; using System.Threading.Tasks; using System.Windows.Forms; namespace FizzyLauncher { public partial class MainForm : Form { [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 const int WM_QUERYENDSESSION = 0x0011; protected OptionsForm optionsForm = null; protected string sessionFilename = null; protected bool isBusy = false; protected bool requestExit = false; public MainForm() : base() { InitializeComponent(); tileContainer1.OnColumnSizeChanged += tileContainer1_OnSizeChanged; notifyIcon1.Text = Application.ProductName; this.AutoScaleMode = AutoScaleMode.None; this.StartPosition = FormStartPosition.WindowsDefaultBounds; this.Visible = false; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.AutoScaleMode = AutoScaleMode.None; UIControl.SetVisible(this, false); UIControl.SetSize(this, this.MinimumSize); } protected async override void OnShown(EventArgs e) { base.OnShown(e); UIControl.SetVisible(this, false); string[] commandLineArgs = Environment.GetCommandLineArgs(); string jsonfigFilename = null; if (string.IsNullOrWhiteSpace(jsonfigFilename)) jsonfigFilename = parseOpenFile_FromCMD(commandLineArgs); if (string.IsNullOrWhiteSpace(jsonfigFilename)) jsonfigFilename = Path.ChangeExtension(Application.ExecutablePath, "jsonfig"); if (!string.IsNullOrWhiteSpace(jsonfigFilename) && File.Exists(jsonfigFilename)) { await loadFile(jsonfigFilename); } else { this.CurrentSession = new LauncherSession(); UIControl.SetVisible(this, true); } } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); if (this.CurrentSession == null) this.CurrentSession = new LauncherSession(); if (this.CurrentSession.HideOnClose && !requestExit) { this.Visible = !this.Visible; e.Cancel = true; return; } requestExit = false; 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) { #if !DEBUG UnregisterHotKey((IntPtr)Handle, 1); #endif } } } protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_HOTKEY: if (m.WParam.ToInt32() == 1) { this.Visible = !this.Visible; } break; case WM_QUERYENDSESSION: requestExit = true; //this.Close(); Application.Exit(); break; default: break; } base.WndProc(ref m); } public LauncherSession CurrentSession { get; set; } = null; public void Clear(int columnCount) { tileContainer1.Clear(); tileContainer1.Add(columnCount); sessionFilename = null; } protected async Task collapseWindow(int width, int increment = 6) { await Task.Run(() => { while (this.Width > width) { UIControl.SetWidth(this, (this.Width - increment)); Application.DoEvents(); } UIControl.SetWidth(this, width); }); } protected async Task expandWindow(int width, int increment = 8) { await Task.Run(() => { while (this.Width < width) { UIControl.SetWidth(this, (this.Width + increment)); Application.DoEvents(); } UIControl.SetWidth(this, width); }); } protected void invalidateHotKey() { #if !DEBUG if (this.InvokeRequired) { this.Invoke(new MethodInvoker(() => { UnregisterHotKey((IntPtr)Handle, 1); })); } else { UnregisterHotKey((IntPtr)Handle, 1); } #endif if (this.CurrentSession.HotKey != null) { if (this.CurrentSession.HotKey.KeyCode != Keys.None) { #if !DEBUG 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); } #endif } } } protected string parseOpenFile_FromCMD(string[] args) { if (args.Length <= 1) { return null; } int i = 1; while (true) { if (i > (args.Length - 1)) { break; } switch (args[i].Trim().ToLower()) { case "-o": case "-open": if ((i + 1) > (args.Length - 1)) break; string openFilename = args[(i + 1)]; if (string.IsNullOrWhiteSpace(openFilename)) break; if (!File.Exists(openFilename)) break; return openFilename; //i++; //break; } i++; } return null; } protected void newSession() { NewForm form = new NewForm(this); form.ShowDialog(); } 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; } // load options var options = new JsonSerializerOptions(); options.Converters.Add(new JsonPointConverter()); options.Converters.Add(new JsonSizeConverter()); options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping; try { this.CurrentSession = JsonSerializer.Deserialize(sourceCode, options); } catch (Exception) { MessageBox.Show("Unable to read session", "Load session"); return; } if (this.CurrentSession == null) { this.CurrentSession = new LauncherSession(); } // load tiles tileContainer1.Load(this.CurrentSession.Groups); // reposition if (!this.CurrentSession.StartPosition.IsEmpty) UIControl.SetLocation(this, this.CurrentSession.StartPosition); // UIControl.SetTopMost(this, this.CurrentSession.AlwaysOnTop); UIControl.SetVisible(this, true); UIControl.SetChecked(enableAnimationsToolStripMenuItem, this.CurrentSession.EnableAnimation); UIControl.SetChecked(showBigIconsToolStripMenuItem, this.CurrentSession.EnableBigIconInFolder); UIControl.SetClientHeight(this, this.CurrentSession.DefaultHeight); UIControl.SetFocus(this); // hotkey invalidateHotKey(); }); } protected bool saveFile(string filename, bool showNotices = true) { if (isBusy) { return false; } if (string.IsNullOrWhiteSpace(filename)) { return false; } if (tileContainer1.GroupCount <= 0) { return true; } isBusy = true; // update session if (this.CurrentSession == null) { this.CurrentSession = new LauncherSession(); } this.CurrentSession.DefaultHeight = this.Height; this.CurrentSession.AlwaysOnTop = this.TopMost; this.CurrentSession.StartPosition = this.Location; this.CurrentSession.Groups = tileContainer1.GroupModels?.ToList() ?? new List(); var options = new JsonSerializerOptions(); options.Converters.Add(new JsonPointConverter()); options.Converters.Add(new JsonSizeConverter()); options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping; try { File.WriteAllText(filename, JsonSerializer.Serialize(this.CurrentSession, options)); 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; } #region main menu /// /// New /// /// /// private void newToolStripMenuItem_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(); } } else if (dr == DialogResult.No) { newSession(); } else if (dr == DialogResult.Cancel) { return; } } } /// /// Open /// /// /// private async void openToolStripMenuItem_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 closeToolStripMenuItem_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(sessionFilename)) { tileContainer1.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) { tileContainer1.Clear(); sessionFilename = null; } } else if (dr == DialogResult.No) { tileContainer1.Clear(); sessionFilename = null; } else if (dr == DialogResult.Cancel) { return; } } } /// /// Save /// /// /// private void saveToolStripMenuItem_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(sessionFilename)) { saveAsFile(); } else { saveFile(sessionFilename, true); } } /// /// Save As /// /// /// private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { saveAsFile(); } /// /// Exit /// /// /// private void exitToolStripMenuItem2_Click(object sender, EventArgs e) { requestExit = true; this.Close(); } /// /// Add group /// /// /// private void addGroupToolStripMenuItem_Click(object sender, EventArgs e) { tileContainer1.Add(); } /// /// Show big icons /// /// /// private void showBigIconsToolStripMenuItem_Click(object sender, EventArgs e) { if (this.CurrentSession == null) { return; } this.CurrentSession.EnableBigIconInFolder = !this.CurrentSession.EnableBigIconInFolder; showBigIconsToolStripMenuItem.Checked = this.CurrentSession.EnableBigIconInFolder; } /// /// Enable animations /// /// /// private void enableAnimationsToolStripMenuItem_Click(object sender, EventArgs e) { if (this.CurrentSession == null) { return; } this.CurrentSession.EnableAnimation = !this.CurrentSession.EnableAnimation; enableAnimationsToolStripMenuItem.Checked = this.CurrentSession.EnableAnimation; } /// /// Always on top /// /// /// private void alwaysOnTopToolStripMenuItem_Click(object sender, EventArgs e) { this.TopMost = !this.TopMost; } /// /// Options /// /// /// private void optionsToolStripMenuItem_Click(object sender, EventArgs e) { if (optionsForm == null) optionsForm = new OptionsForm(this); optionsForm.ShowDialog(); invalidateHotKey(); } /// /// View help /// /// /// private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e) { try { System.Diagnostics.Process.Start(new ProcessStartInfo() { FileName = AppResource.AppHelpURL, UseShellExecute = true }); } catch { // do nothing } } /// /// About /// /// /// private void aboutToolStripMenuItem1_Click(object sender, EventArgs e) { MessageBox.Show(Application.ProductName + " v" + Application.ProductVersion, "About", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void menuStrip1_MenuActivate(object sender, EventArgs e) { alwaysOnTopToolStripMenuItem.Checked = this.TopMost; saveAsToolStripMenuItem.Enabled = !string.IsNullOrWhiteSpace(sessionFilename); } #endregion #region notification icon private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { this.Visible = !this.Visible; } } private void exitToolStripMenuItem1_Click(object sender, EventArgs e) { requestExit = true; this.Close(); } #endregion private void tileContainer1_OnSizeChanged(object sender, EventArgs e) { int newWidth = this.Padding.Horizontal + SystemInformation.VerticalScrollBarWidth + tileContainer1.CalcWidth; UIControl.SetClientWidth(this, newWidth); } } }