Fix active/save Profile

Fix SingleInstance
MainForm Refactors
This commit is contained in:
ChsBuffer
2021-11-06 19:04:42 +08:00
parent 6b1c1cfc37
commit a13b83fd9f
5 changed files with 85 additions and 97 deletions

View File

@@ -32,7 +32,7 @@ namespace Netch.Controllers
{
using var releaser = await Lock.EnterAsync();
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.Remark}");
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.i18NRemark}");
if (await DnsUtils.LookupAsync(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));

View File

@@ -66,13 +66,20 @@ namespace Netch.Forms
_parent.LocationChanged += Parent_Move;
_parent.SizeChanged += Parent_Move;
_parent.Activated += Parent_Activated;
_parent.VisibleChanged += Parent_VisibleChanged;
}
private void Parent_VisibleChanged(object? sender, EventArgs e)
{
Visible = _parent.Visible;
}
protected override void OnClosing(CancelEventArgs? e)
{
_parent.Activated -= Parent_Activated;
_parent.LocationChanged -= Parent_Move;
_parent.SizeChanged -= Parent_Move;
_parent.Activated -= Parent_Activated;
_parent.VisibleChanged -= Parent_VisibleChanged;
base.OnClosing(e!);
}
}

View File

@@ -884,83 +884,54 @@ namespace Netch.Forms
}
}
private void ActiveProfile(Profile profile)
{
ProfileNameText.Text = profile.ProfileName;
var server = ServerComboBox.Items.Cast<Server>().FirstOrDefault(s => s.Remark.Equals(profile.ServerRemark));
var mode = ModeComboBox.Items.Cast<Mode>().FirstOrDefault(m => m.Remark.Equals(profile.ModeRemark));
if (server == null)
throw new Exception("Server not found.");
if (mode == null)
throw new Exception("Mode not found.");
ServerComboBox.SelectedItem = server;
ModeComboBox.SelectedItem = mode;
}
private Profile CreateProfileAtIndex(int index)
{
var server = (Server)ServerComboBox.SelectedItem;
var mode = (Mode)ModeComboBox.SelectedItem;
var name = ProfileNameText.Text;
Profile? profile;
if ((profile = Global.Settings.Profiles.SingleOrDefault(p => p.Index == index)) != null)
Global.Settings.Profiles.Remove(profile);
profile = new Profile(server, mode, name, index);
Global.Settings.Profiles.Add(profile);
return profile;
}
private async void ProfileButton_Click([NotNull] object? sender, EventArgs? e)
{
if (sender == null)
throw new ArgumentNullException(nameof(sender));
throw new InvalidOperationException();
var profileButton = (Button)sender;
var profile = (Profile?)profileButton.Tag;
var index = ProfileTable.Controls.IndexOf(profileButton);
var button = (Button)sender;
var profile = (Profile?)button.Tag;
var index = ProfileTable.Controls.IndexOf(button);
switch (ModifierKeys)
{
case Keys.Control:
if (ServerComboBox.SelectedIndex == -1)
// Save Profile
if (ServerComboBox.SelectedItem is not Server server)
{
MessageBoxX.Show(i18N.Translate("Please select a server first"));
return;
}
if (ModeComboBox.SelectedIndex == -1)
if (ModeComboBox.SelectedItem is not Mode mode)
{
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
return;
}
if (ProfileNameText.Text == "")
{
MessageBoxX.Show(i18N.Translate("Please enter a profile name first"));
ProfileNameText.Focus();
return;
}
var name = ProfileNameText.Text;
Global.Settings.Profiles.RemoveAll(p => p.Index == index);
profile = new Profile(server, mode, name, index);
Global.Settings.Profiles.Add(profile);
button.Tag = profile;
button.Text = profile.ProfileName;
profileButton.Tag = profile = CreateProfileAtIndex(index);
profileButton.Text = profile.ProfileName;
ProfileNameText.Clear();
return;
case Keys.Shift:
// Delete Profile
if (profile == null)
return;
Global.Settings.Profiles.Remove(profile);
profileButton.Tag = null;
profileButton.Text = i18N.Translate("None");
button.Tag = null;
button.Text = i18N.Translate("None");
return;
}
// Activate Profile
if (profile == null)
{
MessageBoxX.Show(i18N.Translate("No saved profile here. Save a profile first by Ctrl+Click on the button"));
@@ -969,23 +940,29 @@ namespace Netch.Forms
try
{
ActiveProfile(profile);
ProfileNameText.Text = profile.ProfileName;
var server = ServerComboBox.Items.Cast<Server>().FirstOrDefault(s => s.Remark.Equals(profile.ServerRemark));
var mode = ModeComboBox.Items.Cast<Mode>().FirstOrDefault(m => m.Remark.Any(s => s.Value.Equals(profile.ModeRemark)));
if (server == null)
throw new MessageException("Server not found.");
if (mode == null)
throw new MessageException("Mode not found.");
// set active server and mode
ServerComboBox.SelectedItem = server;
ModeComboBox.SelectedItem = mode;
}
catch (Exception exception)
catch (MessageException exception)
{
MessageBoxX.Show(exception.Message, LogLevel.ERROR);
return;
}
// start the profile
ControlButton_Click(null, null);
if (State == State.Stopping || State == State.Stopped)
{
while (State != State.Stopped)
await Task.Delay(250);
ControlButton_Click(null, null);
}
await StopAsync();
ControlButton.PerformClick();
}
#endregion
@@ -1259,7 +1236,7 @@ namespace Netch.Forms
private bool _resumeFlag;
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
@@ -1268,7 +1245,7 @@ namespace Netch.Forms
{
_resumeFlag = true;
Log.Information("OS Suspend, Stop");
ControlButton_Click(null, null);
await StopAsync();
}
break;
@@ -1277,7 +1254,7 @@ namespace Netch.Forms
{
_resumeFlag = false;
Log.Information("OS Resume, Restart");
ControlButton_Click(null, null);
ControlButton.PerformClick();
}
break;
@@ -1307,7 +1284,7 @@ namespace Netch.Forms
{
MessageBoxX.Show(i18N.Translate("Please press Stop button first"));
NotifyIcon_MouseDoubleClick(null, null);
ShowMainFormToolStripButton.PerformClick();
return;
}
@@ -1417,26 +1394,9 @@ namespace Netch.Forms
#region NotifyIcon
public void ShowMainFormToolStripButton_Click(object sender, EventArgs e)
private void ShowMainFormToolStripButton_Click(object sender, EventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action(() => ShowMainFormToolStripButton_Click(sender, e)));
return;
}
var forms = Application.OpenForms.Cast<Form>().ToList();
var anyWindowOpened = forms.Any(f => f is not (MainForm or LogForm));
forms.ForEach(f =>
{
if (anyWindowOpened && f is MainForm or LogForm)
return;
f.Show();
f.WindowState = FormWindowState.Normal;
f.Activate();
});
Utils.Utils.ActivateVisibleWindows();
}
/// <summary>

View File

@@ -27,24 +27,29 @@ namespace Netch
{
public static class Program
{
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Program)}");
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Netch)}");
internal static HWND ConsoleHwnd { get; private set; }
/// <summary>
/// 应用程序的主入口点
/// </summary>
#pragma warning disable VSTHRD002
// VSTHRD002: Avoid problematic synchronous waits
// Main never re-called, so we can ignore this
[STAThread]
public static void Main(string[] args)
{
// handle arguments
if (args.Contains(Constants.Parameter.ForceUpdate))
Flags.AlwaysShowNewVersionFound = true;
// 设置当前目录
// set working directory
Directory.SetCurrentDirectory(Global.NetchDir);
// append .\bin to PATH
var binPath = Path.Combine(Global.NetchDir, "bin");
Environment.SetEnvironmentVariable("PATH", $"{Environment.GetEnvironmentVariable("PATH")};{binPath}");
// check if .\bin directory exists
if (!Directory.Exists("bin") || !Directory.EnumerateFileSystemEntries("bin").Any())
{
i18N.Load("System");
@@ -52,19 +57,19 @@ namespace Netch
Environment.Exit(2);
}
// clean up old files
Updater.CleanOld(Global.NetchDir);
// 预创建目录
// pre-create directories
var directories = new[] { "mode\\Custom", "data", "i18n", "logging" };
foreach (var item in directories)
if (!Directory.Exists(item))
Directory.CreateDirectory(item);
// 加载配置
#pragma warning disable VSTHRD002
// load configuration
Configuration.LoadAsync().Wait();
#pragma warning restore VSTHRD002
// check if the program is already running
if (!SingleInstance.IsFirstInstance)
{
SingleInstance.PassArgumentsToFirstInstance(args.Append(Constants.Parameter.Show));
@@ -74,7 +79,7 @@ namespace Netch
SingleInstance.ArgumentsReceived.Subscribe(SingleInstance_ArgumentsReceived);
// 清理上一次的日志文件,防止淤积占用磁盘空间
// clean up old logs
if (Directory.Exists("logging"))
{
var directory = new DirectoryInfo("logging");
@@ -90,14 +95,15 @@ namespace Netch
CreateLogger();
// 加载语言
// load i18n
i18N.Load(Global.Settings.Language);
// log environment information
Task.Run(LogEnvironment).Forget();
CheckClr();
CheckOS();
// 绑定错误捕获
// handle exceptions
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += Application_OnException;
Application.ApplicationExit += Application_OnExit;
@@ -108,6 +114,8 @@ namespace Netch
Application.Run(Global.MainForm);
}
#pragma warning restore VSTHRD002
private static void LogEnvironment()
{
Log.Information("Netch Version: {Version}", $"{UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
@@ -167,6 +175,7 @@ namespace Netch
ConsoleHwnd = PInvoke.GetConsoleWindow();
#if RELEASE
// hide console window
PInvoke.ShowWindow(ConsoleHwnd, SHOW_WINDOW_CMD.SW_HIDE);
#endif
}
@@ -202,7 +211,7 @@ namespace Netch
{
if (args.Contains(Constants.Parameter.Show))
{
Global.MainForm.ShowMainFormToolStripButton_Click(null!, null!);
Utils.Utils.ActivateVisibleWindows();
}
}
}

View File

@@ -255,5 +255,17 @@ namespace Netch.Utils
var endIndex = str.IndexOf(':');
return endIndex == -1 ? str : str[..endIndex];
}
public static void ActivateVisibleWindows()
{
foreach (var f in Application.OpenForms.Cast<Form>())
{
if (!f.Visible)
continue;
f.WindowState = FormWindowState.Normal;
f.Activate();
}
}
}
}