view ServerMonitor/Forms/SettingsForm.cs @ 29:f6235dc0a8ec

Add ability to play a sound on check failure.
author Brad Greco <brad@bgreco.net>
date Fri, 14 Jun 2019 21:01:55 -0400
parents 7626b099aefd
children 7645122aa7a9
line wrap: on
line source

using Microsoft.Win32;
using ServerMonitorApp.Properties;
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace ServerMonitorApp
{
    /// <summary>Application settings form.</summary>
    public partial class SettingsForm : Form
    {
        private readonly string autorunKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
        private readonly string autorunName = "ServerMonitor";
        private readonly string[] soundOptions = { "None", "Windows error", "Custom sound..." };
        private readonly int customSoundIndex = 2;

        public SettingsForm()
        {
            InitializeComponent();
        }

        private void SettingsForm_Load(object sender, EventArgs e)
        {
            Icon = Resources.icon;
            // Populate each action combo box with the available actions to perform on failure.
            foreach (ComboBox comboBox in new object[] { ErrorComboBox, WarningComboBox, InformationComboBox })
            {
                comboBox.DataSource = Enum.GetValues(typeof(FailAction));
                comboBox.Format += FailActionComboBox_Format;
            }
            // Populate the sound options combo boxes.
            foreach (ComboBox comboBox in new object[] { ErrorSoundComboBox, WarningSoundComboBox, InformationSoundComboBox })
            {
                comboBox.Items.AddRange(soundOptions);
                // Add the already-selected custom sound, if any.
                if (getSoundSettingIndex(comboBox) == customSoundIndex)
                    comboBox.Items.Insert(customSoundIndex, getSoundSetting(comboBox));
            }
            // Initialize controls with current settings.
            AutorunCheckBox.Checked = GetAutorun();
            KeepRunningCheckBox.Checked = Settings.Default.HideToNotificationArea;
            KeepLogDaysInput.Value = Settings.Default.KeepLogDays;
            ErrorComboBox.SelectedItem = Settings.Default.ErrorAction;
            WarningComboBox.SelectedItem = Settings.Default.WarningAction;
            InformationComboBox.SelectedItem = Settings.Default.InformationAction;
            ErrorSoundComboBox.SelectedIndex = getSoundSettingIndex(ErrorSoundComboBox);
            WarningSoundComboBox.SelectedIndex = getSoundSettingIndex(WarningSoundComboBox);
            InformationSoundComboBox.SelectedIndex = getSoundSettingIndex(InformationSoundComboBox);
        }

        /// <summary>Gets whether an autorun registry key for this program exists.</summary>
        /// <returns>Whether an autorun registry key for this program exists</returns>
        private bool GetAutorun()
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey(autorunKey, false);
            string value = (string)key.GetValue(autorunName, string.Empty);
            return value.StartsWith(Application.ExecutablePath);
        }

        /// <summary>Sets whether this program should automatically start with Windows.</summary>
        /// <param name="autorun">Whether autorun should be enabled or disabled.</param>
        private void SetAutorun(bool autorun)
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey(autorunKey, true);
            if (autorun)
                key.SetValue(autorunName, Application.ExecutablePath.ToString());
            else
                key.DeleteValue(autorunName, false);
        }

        /// <summary>Shows a human readable description of possible check failure actions in the combo box.</summary>
        private void FailActionComboBox_Format(object sender, ListControlConvertEventArgs e)
        {
            // Transform the "CamelCase" enum name in to a "Camel case" name, adding
            // spaces and making all characters besides the first lower case.
            e.Value = e.Value.ToString().Substring(0, 1) + Regex.Replace(e.Value.ToString(), "(\\B[A-Z])", " $1").ToLower().Substring(1);
        }

        /// <summary>Saves the user settings and closes the form.</summary>
        private void OkButton_Click(object sender, EventArgs e)
        {
            Settings.Default.HideToNotificationArea = KeepRunningCheckBox.Checked;
            Settings.Default.KeepLogDays = (int)KeepLogDaysInput.Value;
            Settings.Default.ErrorAction = (FailAction)ErrorComboBox.SelectedItem;
            Settings.Default.WarningAction = (FailAction)WarningComboBox.SelectedItem;
            Settings.Default.InformationAction = (FailAction)InformationComboBox.SelectedItem;
            Settings.Default.ErrorSound = getSelectedSound(ErrorSoundComboBox);
            Settings.Default.WarningSound = getSelectedSound(WarningSoundComboBox);
            Settings.Default.InformationSound = getSelectedSound(InformationSoundComboBox);
            Settings.Default.Save();
            SetAutorun(AutorunCheckBox.Checked);
            Close();
        }

        /// <summary>Closes the form without saving settings.</summary>
        private void CancelSettingsButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>Shows a file browser when "Custom cound..." is selected.</summary>
        private void SoundComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox comboBox = (ComboBox)sender;
            // Show the dialog if the last item is selected.
            if (comboBox.SelectedIndex == comboBox.Items.Count - 1)
            {
                OpenFileDialog dialog = new OpenFileDialog()
                {
                    Title = "Select audio file",
                    Filter = "Audio files (*.wav;*.mp3;*.wma,*.aif,*.aiff,*.asf,*.aac,*.m4a)|*.wav;*.mp3;*.wma,*.aif,*.aiff,*.asf,*.aac,*.m4a|All files (*.*)|*.*"
                };
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    // Remove the previous custom sound, if any.
                    if (comboBox.Items.Count > soundOptions.Length)
                        comboBox.Items.RemoveAt(customSoundIndex);
                    // Add the custom sound and mark it as selected.
                    comboBox.Items.Insert(customSoundIndex, dialog.FileName);
                    comboBox.SelectedIndex = customSoundIndex;
                }
                else
                {
                    // Restore the existing setting if the dialog was cancelled.
                    comboBox.SelectedIndex = getSoundSettingIndex(comboBox);
                }
            }
        }

        /// <summary>Shows only the filename of the custom sound.</summary>
        private void SoundComboBox_Format(object sender, ListControlConvertEventArgs e)
        {
            ComboBox comboBox = (ComboBox)sender;
            if (!soundOptions.Contains(e.Value))
                e.Value = Path.GetFileName(e.Value.ToString());
        }

        /// <summary>Returns the selected sound for a combo box as stored in program settings.</summary>
        /// <param name="comboBox">The combo box to read from.</param>
        /// <returns>
        /// The index ("0" or "1") of the selected option, or the
        /// path to the custom sound if a custom sound is selected.
        /// </returns>
        private string getSelectedSound(ComboBox comboBox)
        {
            return comboBox.SelectedIndex == customSoundIndex ? comboBox.SelectedItem.ToString() : comboBox.SelectedIndex.ToString();
        }

        /// <summary>Reads the sound setting for a combobox from program settings.</summary>
        /// <param name="comboBox">The combo box to read data for.</param>
        /// <returns>
        /// The index ("0" or "1") of the selected option, or the
        /// path to the custom sound if a custom sound is selected.
        /// </returns>
        private string getSoundSetting(ComboBox comboBox)
        {
            string setting = string.Empty;
            if (comboBox == ErrorSoundComboBox)
                setting = Settings.Default.ErrorSound;
            if (comboBox == WarningSoundComboBox)
                setting = Settings.Default.WarningSound;
            if (comboBox == InformationSoundComboBox)
                setting = Settings.Default.InformationSound;
            return setting;
        }

        /// <summary>Gets the index of the combo box item that corresponds to its program sound setting.</summary>
        /// <param name="comboBox">The combo box to read data for.</param>
        /// <returns>The index of the combo box item that corresponds to its program sound setting.</returns>
        private int getSoundSettingIndex(ComboBox comboBox)
        {
            // If the string is not numeric, it contains the path to the custom sound.
            return int.TryParse(getSoundSetting(comboBox), out int index) ? index : customSoundIndex;
        }

    }
}