From 5bdd8a27e2d7fc74491dac7b71926bf9d2c197f9 Mon Sep 17 00:00:00 2001 From: Luca Date: Mon, 4 Sep 2023 14:38:38 +0200 Subject: [PATCH 1/2] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce6477b..70eecb7 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,6 @@ Delete the junction in the old location (this won't delete the content) and move The project is currently being maintained for fixes, but no new features are currently in development or planned. -I wrote the tool alone and I am currently the only developer, at the moment I'm finishing my MSc and I'm too busy with other projects to work on new features. +I wrote the tool alone and I am currently the only developer, at the moment I'm pursuing my PhD and I'm too busy with other projects to work on new features. I'll keep watching the project and managing possible contributions, so, if you are interested in contributing, leave an issue or comment on an open issue and let me know! From 2ef183a458a14e2373ce74a6c6f80d15f24ecbec Mon Sep 17 00:00:00 2001 From: zhu120212 <1138563490@qq.com> Date: Wed, 11 Feb 2026 01:06:14 +0800 Subject: [PATCH 2/2] modified: FreeMove/Form1.Designer.cs modified: FreeMove/Form1.cs modified: FreeMove/FreeMove.csproj modified: FreeMove/Program.cs modified: FreeMove/ProgressDialog.cs modified: FreeMove/Properties/Resources.resx new file: FreeMove/Properties/Resources.zh-Hans.resx modified: FreeMove/Properties/Settings.Designer.cs modified: FreeMove/Settings.cs --- FreeMove/Form1.Designer.cs | 112 +++++-- FreeMove/Form1.cs | 126 ++++++- FreeMove/FreeMove.csproj | 6 +- FreeMove/Program.cs | 49 ++- FreeMove/ProgressDialog.cs | 3 +- FreeMove/Properties/Resources.resx | 187 +++++++++++ FreeMove/Properties/Resources.zh-Hans.resx | 368 +++++++++++++++++++++ FreeMove/Properties/Settings.Designer.cs | 10 +- FreeMove/Settings.cs | 41 ++- 9 files changed, 838 insertions(+), 64 deletions(-) create mode 100644 FreeMove/Properties/Resources.zh-Hans.resx diff --git a/FreeMove/Form1.Designer.cs b/FreeMove/Form1.Designer.cs index 844620c..be48ec6 100644 --- a/FreeMove/Form1.Designer.cs +++ b/FreeMove/Form1.Designer.cs @@ -69,31 +69,35 @@ private void InitializeComponent() this.reportAnIssueToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.gitHubToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.lunguToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.zhToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.chineseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.chkBox_createDest = new System.Windows.Forms.CheckBox(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 34); + this.label1.Location = new System.Drawing.Point(12, 31); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(63, 13); + this.label1.Size = new System.Drawing.Size(65, 12); this.label1.TabIndex = 0; this.label1.Text = "Move From:"; // // textBox_From // - this.textBox_From.Location = new System.Drawing.Point(82, 34); + this.textBox_From.Location = new System.Drawing.Point(82, 31); this.textBox_From.Name = "textBox_From"; - this.textBox_From.Size = new System.Drawing.Size(383, 20); + this.textBox_From.Size = new System.Drawing.Size(383, 21); this.textBox_From.TabIndex = 1; // // button_BrowseFrom // - this.button_BrowseFrom.Location = new System.Drawing.Point(475, 34); + this.button_BrowseFrom.Location = new System.Drawing.Point(475, 31); this.button_BrowseFrom.Name = "button_BrowseFrom"; - this.button_BrowseFrom.Size = new System.Drawing.Size(75, 23); + this.button_BrowseFrom.Size = new System.Drawing.Size(75, 21); this.button_BrowseFrom.TabIndex = 2; this.button_BrowseFrom.Text = "Browse..."; this.button_BrowseFrom.UseVisualStyleBackColor = true; @@ -101,9 +105,9 @@ private void InitializeComponent() // // button_BrowseTo // - this.button_BrowseTo.Location = new System.Drawing.Point(475, 58); + this.button_BrowseTo.Location = new System.Drawing.Point(475, 54); this.button_BrowseTo.Name = "button_BrowseTo"; - this.button_BrowseTo.Size = new System.Drawing.Size(75, 23); + this.button_BrowseTo.Size = new System.Drawing.Size(75, 21); this.button_BrowseTo.TabIndex = 4; this.button_BrowseTo.Text = "Browse..."; this.button_BrowseTo.UseVisualStyleBackColor = true; @@ -111,17 +115,17 @@ private void InitializeComponent() // // textBox_To // - this.textBox_To.Location = new System.Drawing.Point(82, 60); + this.textBox_To.Location = new System.Drawing.Point(82, 55); this.textBox_To.Name = "textBox_To"; - this.textBox_To.Size = new System.Drawing.Size(383, 20); + this.textBox_To.Size = new System.Drawing.Size(383, 21); this.textBox_To.TabIndex = 3; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(12, 60); + this.label2.Location = new System.Drawing.Point(12, 55); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(23, 13); + this.label2.Size = new System.Drawing.Size(23, 12); this.label2.TabIndex = 3; this.label2.Text = "To:"; // @@ -131,9 +135,9 @@ private void InitializeComponent() // // button_Move // - this.button_Move.Location = new System.Drawing.Point(475, 118); + this.button_Move.Location = new System.Drawing.Point(475, 109); this.button_Move.Name = "button_Move"; - this.button_Move.Size = new System.Drawing.Size(75, 23); + this.button_Move.Size = new System.Drawing.Size(75, 21); this.button_Move.TabIndex = 6; this.button_Move.Text = "Move"; this.button_Move.UseVisualStyleBackColor = true; @@ -142,18 +146,18 @@ private void InitializeComponent() // chkBox_originalHidden // this.chkBox_originalHidden.AutoSize = true; - this.chkBox_originalHidden.Location = new System.Drawing.Point(15, 95); + this.chkBox_originalHidden.Location = new System.Drawing.Point(15, 88); this.chkBox_originalHidden.Name = "chkBox_originalHidden"; - this.chkBox_originalHidden.Size = new System.Drawing.Size(154, 17); + this.chkBox_originalHidden.Size = new System.Drawing.Size(198, 16); this.chkBox_originalHidden.TabIndex = 5; this.chkBox_originalHidden.Text = "Set original folder to hidden"; this.chkBox_originalHidden.UseVisualStyleBackColor = true; // // button_Close // - this.button_Close.Location = new System.Drawing.Point(12, 118); + this.button_Close.Location = new System.Drawing.Point(12, 109); this.button_Close.Name = "button_Close"; - this.button_Close.Size = new System.Drawing.Size(75, 23); + this.button_Close.Size = new System.Drawing.Size(75, 21); this.button_Close.TabIndex = 7; this.button_Close.Text = "Close"; this.button_Close.UseVisualStyleBackColor = true; @@ -163,11 +167,12 @@ private void InitializeComponent() // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.settingsToolStripMenuItem, + this.lunguToolStripMenuItem, this.infoToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - this.menuStrip1.Size = new System.Drawing.Size(565, 24); + this.menuStrip1.Size = new System.Drawing.Size(565, 25); this.menuStrip1.TabIndex = 8; this.menuStrip1.Text = "menuStrip1"; // @@ -178,7 +183,7 @@ private void InitializeComponent() this.PermissionCheckToolStripMenuItem, this.safeModeToolStripMenuItem}); this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; - this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(66, 21); this.settingsToolStripMenuItem.Text = "Settings"; // // checkForUpdateToolStripMenuItem @@ -187,20 +192,20 @@ private void InitializeComponent() this.checkNowToolStripMenuItem, this.checkOnProgramStartToolStripMenuItem}); this.checkForUpdateToolStripMenuItem.Name = "checkForUpdateToolStripMenuItem"; - this.checkForUpdateToolStripMenuItem.Size = new System.Drawing.Size(166, 22); + this.checkForUpdateToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.checkForUpdateToolStripMenuItem.Text = "Check for update"; // // checkNowToolStripMenuItem // this.checkNowToolStripMenuItem.Name = "checkNowToolStripMenuItem"; - this.checkNowToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.checkNowToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.checkNowToolStripMenuItem.Text = "Check now"; this.checkNowToolStripMenuItem.Click += new System.EventHandler(this.CheckNowToolStripMenuItem_Click); // // checkOnProgramStartToolStripMenuItem // this.checkOnProgramStartToolStripMenuItem.Name = "checkOnProgramStartToolStripMenuItem"; - this.checkOnProgramStartToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.checkOnProgramStartToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.checkOnProgramStartToolStripMenuItem.Text = "Check on program start"; this.checkOnProgramStartToolStripMenuItem.Click += new System.EventHandler(this.CheckOnProgramStartToolStripMenuItem_Click); // @@ -211,13 +216,13 @@ private void InitializeComponent() this.fastToolStripMenuItem, this.fullToolStripMenuItem}); this.PermissionCheckToolStripMenuItem.Name = "PermissionCheckToolStripMenuItem"; - this.PermissionCheckToolStripMenuItem.Size = new System.Drawing.Size(166, 22); + this.PermissionCheckToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.PermissionCheckToolStripMenuItem.Text = "Permission check"; // // noneToolStripMenuItem // this.noneToolStripMenuItem.Name = "noneToolStripMenuItem"; - this.noneToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.noneToolStripMenuItem.Size = new System.Drawing.Size(108, 22); this.noneToolStripMenuItem.Text = "None"; this.noneToolStripMenuItem.ToolTipText = "Don\'t check any file before moving"; this.noneToolStripMenuItem.Click += new System.EventHandler(this.NoneToolStripMenuItem_Click); @@ -227,7 +232,7 @@ private void InitializeComponent() this.fastToolStripMenuItem.Checked = true; this.fastToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.fastToolStripMenuItem.Name = "fastToolStripMenuItem"; - this.fastToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.fastToolStripMenuItem.Size = new System.Drawing.Size(108, 22); this.fastToolStripMenuItem.Text = "Fast"; this.fastToolStripMenuItem.ToolTipText = "Check all .exe and .dll files before moving"; this.fastToolStripMenuItem.Click += new System.EventHandler(this.FastToolStripMenuItem_Click); @@ -235,7 +240,7 @@ private void InitializeComponent() // fullToolStripMenuItem // this.fullToolStripMenuItem.Name = "fullToolStripMenuItem"; - this.fullToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.fullToolStripMenuItem.Size = new System.Drawing.Size(108, 22); this.fullToolStripMenuItem.Text = "Full"; this.fullToolStripMenuItem.ToolTipText = "Check all files before moving"; this.fullToolStripMenuItem.Click += new System.EventHandler(this.FullToolStripMenuItem_Click); @@ -245,7 +250,7 @@ private void InitializeComponent() this.safeModeToolStripMenuItem.Checked = true; this.safeModeToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.safeModeToolStripMenuItem.Name = "safeModeToolStripMenuItem"; - this.safeModeToolStripMenuItem.Size = new System.Drawing.Size(166, 22); + this.safeModeToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.safeModeToolStripMenuItem.Text = "Safe mode"; this.safeModeToolStripMenuItem.Click += new System.EventHandler(this.SafeModeToolStripMenuItem_Click); // @@ -254,50 +259,81 @@ private void InitializeComponent() this.infoToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.reportAnIssueToolStripMenuItem, this.gitHubToolStripMenuItem, + this.helpToolStripMenuItem, this.aboutToolStripMenuItem}); this.infoToolStripMenuItem.Name = "infoToolStripMenuItem"; this.infoToolStripMenuItem.RightToLeft = System.Windows.Forms.RightToLeft.No; - this.infoToolStripMenuItem.Size = new System.Drawing.Size(40, 20); + this.infoToolStripMenuItem.Size = new System.Drawing.Size(43, 21); this.infoToolStripMenuItem.Text = "Info"; // // reportAnIssueToolStripMenuItem // this.reportAnIssueToolStripMenuItem.Name = "reportAnIssueToolStripMenuItem"; - this.reportAnIssueToolStripMenuItem.Size = new System.Drawing.Size(154, 22); + this.reportAnIssueToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.reportAnIssueToolStripMenuItem.Text = "Report an Issue"; this.reportAnIssueToolStripMenuItem.Click += new System.EventHandler(this.ReportAnIssueToolStripMenuItem_Click); // // gitHubToolStripMenuItem // this.gitHubToolStripMenuItem.Name = "gitHubToolStripMenuItem"; - this.gitHubToolStripMenuItem.Size = new System.Drawing.Size(154, 22); + this.gitHubToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.gitHubToolStripMenuItem.Text = "GitHub"; this.gitHubToolStripMenuItem.Click += new System.EventHandler(this.GitHubToolStripMenuItem_Click); // // aboutToolStripMenuItem // this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; - this.aboutToolStripMenuItem.Size = new System.Drawing.Size(154, 22); + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.aboutToolStripMenuItem.Text = "About"; this.aboutToolStripMenuItem.Click += new System.EventHandler(this.AboutToolStripMenuItem_Click); // + // lunguToolStripMenuItem + // + this.lunguToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.zhToolStripMenuItem, + this.chineseToolStripMenuItem}); + this.lunguToolStripMenuItem.Name = "lunguToolStripMenuItem"; + this.lunguToolStripMenuItem.Size = new System.Drawing.Size(77, 21); + this.lunguToolStripMenuItem.Text = "Language"; + // + // zhToolStripMenuItem + // + this.zhToolStripMenuItem.Name = "zhToolStripMenuItem"; + this.zhToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.zhToolStripMenuItem.Text = "English"; + this.zhToolStripMenuItem.Click += new System.EventHandler(this.zhToolStripMenuItem_Click); + // + // chineseToolStripMenuItem + // + this.chineseToolStripMenuItem.Name = "chineseToolStripMenuItem"; + this.chineseToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.chineseToolStripMenuItem.Text = "Chinese"; + this.chineseToolStripMenuItem.Click += new System.EventHandler(this.chineseToolStripMenuItem_Click); + // // chkBox_createDest // this.chkBox_createDest.AutoSize = true; this.chkBox_createDest.Checked = true; this.chkBox_createDest.CheckState = System.Windows.Forms.CheckState.Checked; - this.chkBox_createDest.Location = new System.Drawing.Point(175, 95); + this.chkBox_createDest.Location = new System.Drawing.Point(219, 88); this.chkBox_createDest.Name = "chkBox_createDest"; - this.chkBox_createDest.Size = new System.Drawing.Size(140, 17); + this.chkBox_createDest.Size = new System.Drawing.Size(174, 16); this.chkBox_createDest.TabIndex = 9; this.chkBox_createDest.Text = "Create destination folder"; this.chkBox_createDest.UseVisualStyleBackColor = true; // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.helpToolStripMenuItem.Text = "Help"; + this.helpToolStripMenuItem.Click += new System.EventHandler(this.HelpToolStripMenuItem_Click); + // // Form1 // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(565, 150); + this.ClientSize = new System.Drawing.Size(565, 138); this.Controls.Add(this.chkBox_createDest); this.Controls.Add(this.button_Close); this.Controls.Add(this.chkBox_originalHidden); @@ -350,6 +386,10 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem fastToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem fullToolStripMenuItem; public System.Windows.Forms.CheckBox chkBox_createDest; + private System.Windows.Forms.ToolStripMenuItem lunguToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem zhToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem chineseToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; } } diff --git a/FreeMove/Form1.cs b/FreeMove/Form1.cs index 242a1d8..8d6e7b9 100644 --- a/FreeMove/Form1.cs +++ b/FreeMove/Form1.cs @@ -43,8 +43,12 @@ public Form1() private async void Form1_Load(object sender, EventArgs e) { + ApplyLanguage(); SetToolTips(); + + + //Check whether the program is set to update on its start if (Settings.AutoUpdate) { @@ -77,6 +81,57 @@ private async void Form1_Load(object sender, EventArgs e) #endregion + /// + /// 根据当前 UI 语言刷新界面上的文本(按钮/菜单/标签等) + /// + private void ApplyLanguage() + { + // 窗口标题 + Text = Properties.Resources.ResourceManager.GetString("Form_Title"); + + // 标签和按钮 + label1.Text = Properties.Resources.ResourceManager.GetString("Label_From"); + label2.Text = Properties.Resources.ResourceManager.GetString("Label_To"); + button_BrowseFrom.Text = Properties.Resources.ResourceManager.GetString("Button_Browse"); + button_BrowseTo.Text = Properties.Resources.ResourceManager.GetString("Button_Browse"); + button_Move.Text = Properties.Resources.ResourceManager.GetString("Button_Move"); + button_Close.Text = Properties.Resources.ResourceManager.GetString("Button_Close"); + chkBox_originalHidden.Text = Properties.Resources.ResourceManager.GetString("Checkbox_OriginalHidden"); + chkBox_createDest.Text = Properties.Resources.ResourceManager.GetString("Checkbox_CreateDest"); + + // 菜单 + settingsToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Settings"); + infoToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Info"); + lunguToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Language"); + + checkForUpdateToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_CheckForUpdate"); + checkNowToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_CheckNow"); + checkOnProgramStartToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_CheckOnStart"); + + PermissionCheckToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_PermissionCheck"); + safeModeToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_SafeMode"); + + noneToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_None"); + fastToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Fast"); + fullToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Full"); + + reportAnIssueToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_ReportIssue"); + gitHubToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_GitHub"); + aboutToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_About"); + helpToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("HelpButtonText"); + + zhToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Lang_English"); + chineseToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Lang_Chinese"); + + // 语言菜单打勾状态 + string lang = Settings.Language; + // lang 为空时:跟随系统,这里根据当前 Culture 判定 + string current = System.Globalization.CultureInfo.CurrentUICulture.Name; + bool isChinese = (!string.IsNullOrEmpty(lang) ? lang : current).StartsWith("zh", StringComparison.OrdinalIgnoreCase); + zhToolStripMenuItem.Checked = !isChinese; + chineseToolStripMenuItem.Checked = isChinese; + } + private bool PreliminaryCheck(string source, string destination) { //Check for errors before copying @@ -84,14 +139,14 @@ private bool PreliminaryCheck(string source, string destination) { IOHelper.CheckDirectories(source, destination, safeMode); } - catch(AggregateException ae) + catch (AggregateException ae) { var msg = ""; foreach (var ex in ae.InnerExceptions) { msg += ex.Message + "\n"; } - MessageBox.Show(msg, "Error"); + MessageBox.Show(msg, Properties.Resources.ResourceManager.GetString("ErrorTitle")); return false; } return true; @@ -117,11 +172,12 @@ private async void Begin() olddir.Attributes = attrib | FileAttributes.Hidden; } - MessageBox.Show(this, "Done!"); + MessageBox.Show(this, Properties.Resources.ResourceManager.GetString("DoneMessage")); } catch (IO.MoveOperation.CopyFailedException ex) { - switch (MessageBox.Show(this, string.Format($"Do you want to undo the changes?\n\nDetails:\n{ex.InnerException.Message}"), ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) + string question = string.Format(Properties.Resources.ResourceManager.GetString("UndoChangesDetailsQuestion"), ex.InnerException.Message); + switch (MessageBox.Show(this, question, ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) { case DialogResult.Yes: try @@ -130,7 +186,7 @@ private async void Begin() } catch (Exception ie) { - MessageBox.Show(this, ie.Message, "Could not remove copied contents. Try removing manually"); + MessageBox.Show(this, ie.Message, Properties.Resources.ResourceManager.GetString("RemoveCopiedContentsFailed")); } break; case DialogResult.No: @@ -140,7 +196,8 @@ private async void Begin() } catch (IO.MoveOperation.DeleteFailedException ex) { - switch (MessageBox.Show(this, string.Format($"Do you want to undo the changes?\n\nDetails:\n{ex.InnerException.Message}"), ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) + string question = string.Format(Properties.Resources.ResourceManager.GetString("UndoChangesDetailsQuestion"), ex.InnerException.Message); + switch (MessageBox.Show(this, question, ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) { case DialogResult.Yes: try @@ -149,7 +206,7 @@ private async void Begin() } catch (Exception ie) { - MessageBox.Show(this, ie.Message, "Could not move back contents. Try moving manually"); + MessageBox.Show(this, ie.Message, Properties.Resources.ResourceManager.GetString("MoveBackFailedMessage")); } break; case DialogResult.No: @@ -159,11 +216,14 @@ private async void Begin() } catch (IO.MoveOperation.MoveFailedException ex) { - MessageBox.Show(this, string.Format($"Details:\n{ex.InnerException.Message}"), ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); + string details = string.Format(Properties.Resources.ResourceManager.GetString("MoveFailedDetailsFormat"), ex.InnerException.Message); + MessageBox.Show(this, details, ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (OperationCanceledException) { - switch (MessageBox.Show(this, string.Format($"Do you want to undo the changes?"), "Cancelled", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)) + string question = Properties.Resources.ResourceManager.GetString("UndoChangesSimpleQuestion"); + string title = Properties.Resources.ResourceManager.GetString("CancelledTitle"); + switch (MessageBox.Show(this, question, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)) { case DialogResult.Yes: try @@ -185,7 +245,7 @@ private async void Begin() private async Task BeginMove(string source, string destination) { //Move files - using (ProgressDialog progressDialog = new ProgressDialog("Moving files...")) + using (ProgressDialog progressDialog = new ProgressDialog(Properties.Resources.ResourceManager.GetString("MovingFilesTitle"))) { IO.MoveOperation moveOp = IOHelper.MoveDir(source, destination); @@ -194,7 +254,9 @@ private async Task BeginMove(string source, string destination) progressDialog.CancelRequested += (sender, e) => { - if (DialogResult.Yes == MessageBox.Show(this, "Are you sure you want to cancel?", "Cancel confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)) + string message = Properties.Resources.ResourceManager.GetString("CancelConfirmationMessage"); + string title = Properties.Resources.ResourceManager.GetString("CancelConfirmationTitle"); + if (DialogResult.Yes == MessageBox.Show(this, message, title, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)) { moveOp.Cancel(); progressDialog.BeginInvoke(new Action(() => progressDialog.Cancellable = false)); @@ -230,9 +292,9 @@ private void SetToolTips() InitialDelay = 600, ReshowDelay = 500 }; - Tip.SetToolTip(this.textBox_From, "Select the folder you want to move"); - Tip.SetToolTip(this.textBox_To, "Select where you want to move the folder"); - Tip.SetToolTip(this.chkBox_originalHidden, "Select whether you want to hide the shortcut which is created in the old location or not"); + Tip.SetToolTip(this.textBox_From, Properties.Resources.ResourceManager.GetString("TooltipFrom")); + Tip.SetToolTip(this.textBox_To, Properties.Resources.ResourceManager.GetString("TooltipTo")); + Tip.SetToolTip(this.chkBox_originalHidden, Properties.Resources.ResourceManager.GetString("TooltipHidden")); } private void Reset() @@ -244,7 +306,8 @@ private void Reset() public static void Unauthorized(Exception ex) { - MessageBox.Show(Properties.Resources.ErrorUnauthorizedMoveDetails + ex.Message, "Error details"); + string title = Properties.Resources.ResourceManager.GetString("ErrorDetailsTitle"); + MessageBox.Show(Properties.Resources.ErrorUnauthorizedMoveDetails + ex.Message, title); } #region Event Handlers @@ -327,12 +390,14 @@ private void CheckOnProgramStartToolStripMenuItem_Click(object sender, EventArgs private void AboutToolStripMenuItem_Click(object sender, EventArgs e) { string msg = String.Format(Properties.Resources.AboutContent, System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion); - MessageBox.Show(msg, "About FreeMove"); + string title = Properties.Resources.ResourceManager.GetString("AboutTitle"); + MessageBox.Show(msg, title); } private void SafeModeToolStripMenuItem_Click(object sender, EventArgs e) { - if (MessageBox.Show(Properties.Resources.DisableSafeModeMessage, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) + string title = Properties.Resources.ResourceManager.GetString("WarningTitle"); + if (MessageBox.Show(Properties.Resources.DisableSafeModeMessage, title, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { safeMode = false; safeModeToolStripMenuItem.Checked = false; @@ -363,5 +428,32 @@ private void FullToolStripMenuItem_Click(object sender, EventArgs e) fastToolStripMenuItem.Checked = false; fullToolStripMenuItem.Checked = true; } + + private void zhToolStripMenuItem_Click(object sender, EventArgs e) + { + // 切换为英文界面 + Settings.Language = "en"; + string msg = Properties.Resources.ResourceManager.GetString("LanguageChangedRestartMessage"); + string title = Properties.Resources.ResourceManager.GetString("LanguageChangedTitle"); + MessageBox.Show(msg, title); + Application.Restart(); + } + + private void chineseToolStripMenuItem_Click(object sender, EventArgs e) + { + // 切换为简体中文界面 + Settings.Language = "zh-Hans"; + string msg = Properties.Resources.ResourceManager.GetString("LanguageChangedRestartMessage"); + string title = Properties.Resources.ResourceManager.GetString("LanguageChangedTitle"); + MessageBox.Show(msg, title); + Application.Restart(); + } + + private void HelpToolStripMenuItem_Click(object sender, EventArgs e) + { + string help = Properties.Resources.ResourceManager.GetString("HelpContent"); + string title = Properties.Resources.ResourceManager.GetString("HelpButtonText"); + MessageBox.Show(this, help, title, MessageBoxButtons.OK, MessageBoxIcon.Information); + } } } diff --git a/FreeMove/FreeMove.csproj b/FreeMove/FreeMove.csproj index 4411525..5744d7a 100644 --- a/FreeMove/FreeMove.csproj +++ b/FreeMove/FreeMove.csproj @@ -1,6 +1,7 @@ net48 + 9.0 WinExe publish\ true @@ -39,11 +40,14 @@ + + + - + diff --git a/FreeMove/Program.cs b/FreeMove/Program.cs index bfedf00..b3165f1 100644 --- a/FreeMove/Program.cs +++ b/FreeMove/Program.cs @@ -19,6 +19,9 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; +using System.Globalization; +using System.Threading; +using System.Security.Principal; namespace FreeMove { @@ -30,8 +33,52 @@ static class Program [STAThread] static void Main() { + // 如非管理员权限,提示并退出 + try + { + using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) + { + WindowsPrincipal principal = new WindowsPrincipal(identity); + if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) + { + string msg = Properties.Resources.ResourceManager.GetString("AdminRequiredMessage"); + string title = Properties.Resources.ResourceManager.GetString("AdminRequiredTitle"); + MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + } + } + catch + { + // 如果检查失败,出于安全考虑也直接退出 + string msg = Properties.Resources.ResourceManager.GetString("AdminRequiredMessage"); + string title = Properties.Resources.ResourceManager.GetString("AdminRequiredTitle"); + MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + // 设置全局语言:优先使用用户在设置中选择的语言,否则跟随系统 + try + { + string lang = Settings.Language; + CultureInfo culture; + if (!string.IsNullOrEmpty(lang)) + { + culture = new CultureInfo(lang); + } + else + { + culture = CultureInfo.InstalledUICulture; + } + Thread.CurrentThread.CurrentCulture = culture; + Thread.CurrentThread.CurrentUICulture = culture; + } + catch + { + // 如果设置中的语言代码无效,忽略并使用系统默认 + } + Application.EnableVisualStyles(); - Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } diff --git a/FreeMove/ProgressDialog.cs b/FreeMove/ProgressDialog.cs index ab2282b..205063b 100644 --- a/FreeMove/ProgressDialog.cs +++ b/FreeMove/ProgressDialog.cs @@ -69,7 +69,8 @@ public void UpdateProgress(IO.IOOperation.ProgressChangedEventArgs e) label_Progress?.BeginInvoke(new Action(() => { float percentage = ((float)e.Progress / e.Max); - label_Progress.Text = e.Progress == e.Max ? "Finishing..." : $"{e.Progress}/{e.Max}"; + string finishing = Properties.Resources.ResourceManager.GetString("ProgressFinishingText"); + label_Progress.Text = e.Progress == e.Max ? finishing : $"{e.Progress}/{e.Max}"; if (e.Progress == e.Max) Cancellable = false; // label_Progress.Text = $"{percentage*100f, 3:0.0}%"; diff --git a/FreeMove/Properties/Resources.resx b/FreeMove/Properties/Resources.resx index f52b321..9e41610 100644 --- a/FreeMove/Properties/Resources.resx +++ b/FreeMove/Properties/Resources.resx @@ -183,4 +183,191 @@ If this text file was useful or if you would have preferred it wasn't created le ImDema-FreeMove-Updater + + Done! + + + Error + + + Could not remove copied contents. Try removing manually + + + Could not move back contents. Try moving manually + + + Details: +{0} + + + Do you want to undo the changes? + +Details: +{0} + + + Do you want to undo the changes? + + + Cancelled + + + Are you sure you want to cancel? + + + Cancel confirmation + + + Select the folder you want to move + + + Select where you want to move the folder + + + Select whether you want to hide the shortcut which is created in the old location or not + + + Error details + + + About FreeMove + + + Warning + + + Moving files... + + + Finishing... + + + Language has been changed. The application will restart to apply the new language. + + + Language + + + Free Move + + + Move From: + + + To: + + + Browse... + + + Move + + + Close + + + Set original folder to hidden + + + Create destination folder + + + Settings + + + Info + + + Language + + + Check for update + + + Check now + + + Check on program start + + + Permission check + + + Safe mode + + + None + + + Fast + + + Full + + + Report an Issue + + + GitHub + + + About + + + English + + + Chinese + + + This application must be run as administrator in order to move folders and create junctions. + +Please right-click the executable and choose "Run as administrator". + + + Administrator required + + + Help + + + FreeMove - Help + +Move From: Select the folder you want to move (for example, a program folder under Program Files). +To: Select the target location (for example, another drive) where you want to move the folder. +Browse... Open a folder picker dialog to choose the source or target folder. + +Move: Start moving the selected folder to the target location and create a junction at the original path. +Close: Close the application window. + +Set original folder to hidden: + After moving, set the junction at the original location to Hidden so it is not visible in Explorer. + +Create destination folder: + If checked, FreeMove will create the target folder automatically when needed. + +Settings → Check for update: + - Check now: Manually check GitHub for a newer version. + - Check on program start: If enabled, FreeMove will automatically check for updates when it starts. + +Settings → Permission check: + - None: Don't check any file before moving (fastest, but may fail later if permissions are missing). + - Fast: Check .exe and .dll files before moving (default). + - Full: Check all files before moving (slowest, but most thorough). + +Settings → Safe mode: + Prevents moving critical system folders (such as Program Files). It is strongly recommended to keep this enabled. + +Info → Report an Issue: + Open the GitHub page to report a bug or request a feature. + +Info → GitHub: + Open the project page on GitHub. + +Info → About: + Show information about FreeMove and its license. + +Language: + - English / Chinese: Switch the user interface language (the application will restart to apply the change). + \ No newline at end of file diff --git a/FreeMove/Properties/Resources.zh-Hans.resx b/FreeMove/Properties/Resources.zh-Hans.resx new file mode 100644 index 0000000..d8fd074 --- /dev/null +++ b/FreeMove/Properties/Resources.zh-Hans.resx @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + imDema/FreeMove {0} —— 移动目录而不破坏快捷方式或安装 +版权所有 (C) 2020 Luca De Martini + +本程序是自由软件:您可以在 GNU 通用公共许可证(GPL)第 3 版或(由您选择)任何更新版本的条款下重新分发和/或修改本程序。 + +本程序的发布希望它能带来帮助,但不提供任何担保;甚至不包括适销性或适用于特定目的的默示担保。 + +您应已随本程序一起收到 GNU 通用公共许可证的副本;如果没有,请参见 <http://www.gnu.org/licenses/>。 + +https://github.com/imDema + + + + 强烈不建议移动 “Program Files” 或 “Program Files (x86)” 目录,否则可能导致系统行为异常。 +推荐只移动这些目录中的具体程序文件夹。 + +确定要关闭安全模式吗? + + + + 创建符号链接时出错。 +文件夹已经移动到新位置,但无法创建链接。 +请尝试以管理员身份运行程序。 + +要把文件移回原位置吗? + + + + 移动文件时发生错误,某些文件可能正在被占用,或者您没有足够的权限。 + +请尝试以管理员身份运行本程序,并关闭正在使用该文件的其他程序。 + +详细信息: + + + + 错误:{0} + +如何继续? +“中止” 将撤销更改 +“忽略” 将停止程序 + + + + 无法从 GitHub 服务器获取版本信息 + + + + 确定要继续吗? + +如果选择忽略,文件将保持当前状态:部分文件已经在新位置,且在旧位置中缺失! + + + + 在 {0} 使用 FreeMove 移动文件时发生错误,并且您选择了“忽略”。 +此目录的其余内容可在 “{1}” 中找到(除非已经被再次移动)。 +下次在发生错误时,请使用 “中止” 将文件移回,或使用 “重试” 再试一次。 + +如果这个文本文件对您有帮助,或者您希望它不要被创建,请告诉我。 + + + + ImDema-FreeMove-Updater + + + + + + 完成! + + + + 错误 + + + + 无法删除已复制的内容,请尝试手动删除。 + + + + 无法将内容移回原位置,请尝试手动移动。 + + + + 详细信息: +{0} + + + + 要撤销这些更改吗? + +详细信息: +{0} + + + + 要撤销这些更改吗? + + + + 已取消 + + + + 确定要取消正在进行的操作吗? + + + + 取消确认 + + + + 选择要移动的文件夹 + + + + 选择目标位置 + + + + 选择是否隐藏在原位置创建的快捷方式(链接) + + + + 错误详情 + + + + 关于 FreeMove + + + + 警告 + + + + 正在移动文件... + + + + 正在完成... + + + + 语言已更改,程序将重新启动以应用新的语言设置。 + + + + 语言 + + + + Free Move + + + + 源文件夹: + + + + 目标位置: + + + + 浏览... + + + + 开始移动 + + + + 关闭 + + + + 将原位置的文件夹设为隐藏 + + + + 自动创建目标文件夹 + + + + 设置 + + + + 信息 + + + + 语言 + + + + 检查更新 + + + + 立即检查 + + + + 启动时检查 + + + + 权限检查 + + + + 安全模式 + + + + 不检查 + + + + 快速 + + + + 完全 + + + + 反馈问题 + + + + GitHub + + + + 关于 + + + + 英文 + + + + 简体中文 + + + + 本程序需要以管理员身份运行才能移动文件夹并创建链接。 + +请右键单击可执行文件,选择“以管理员身份运行”。 + + + + 需要管理员权限 + + + + 帮助 + + + + FreeMove 使用说明 + +源文件夹: 选择你要移动的文件夹(例如 Program Files 下的某个程序目录)。 +目标位置: 选择要把该文件夹移动到的目标路径(例如另一块磁盘)。 +浏览...: 打开文件夹选择对话框,用来选择源或目标文件夹。 + +开始移动: 开始将所选文件夹移动到目标位置,并在原路径创建一个目录链接(junction)。 +关闭: 关闭程序窗口。 + +将原位置的文件夹设为隐藏: + 移动完成后,把原位置创建的链接设为“隐藏”,在资源管理器中不明显显示。 + +自动创建目标文件夹: + 如果勾选,在需要时自动创建目标文件夹。 + +设置 → 检查更新: + - 立即检查: 立刻连接 GitHub 检查是否有新版本。 + - 启动时检查: 每次启动 FreeMove 时自动检查是否有新版本。 + +设置 → 权限检查: + - 不检查: 不预先检查任何文件权限(速度最快,但可能在后面操作时才失败)。 + - 快速: 只预检查 .exe 和 .dll 文件的权限(默认)。 + - 完全: 预检查所有文件的权限(最慢,但最安全)。 + +设置 → 安全模式: + 阻止移动关键系统目录(例如 Program Files)。强烈建议保持开启。 + +信息 → 反馈问题: + 打开 GitHub 的 Issue 页面,用于反馈 Bug 或提出建议。 + +信息 → GitHub: + 打开本项目的 GitHub 主页。 + +信息 → 关于: + 显示 FreeMove 的版本和授权信息。 + +语言: + - 英文 / 简体中文:切换界面语言(程序将重启以应用新的语言)。 + + + + diff --git a/FreeMove/Properties/Settings.Designer.cs b/FreeMove/Properties/Settings.Designer.cs index 84c6380..f2f2af5 100644 --- a/FreeMove/Properties/Settings.Designer.cs +++ b/FreeMove/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace FreeMove.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/FreeMove/Settings.cs b/FreeMove/Settings.cs index 9f2cb54..bf32b33 100644 --- a/FreeMove/Settings.cs +++ b/FreeMove/Settings.cs @@ -39,6 +39,9 @@ public enum PermissionCheckLevel public PermissionCheckLevel PermissionCheck = PermissionCheckLevel.Fast; + // UI language code, e.g. "en", "zh-Hans". null/empty = follow system language + public string LanguageCode = null; + public static bool AutoUpdate { set @@ -69,6 +72,21 @@ public static PermissionCheckLevel PermCheck } } + public static string Language + { + get + { + var LSett = Load(); + return LSett.LanguageCode; + } + set + { + var LSett = Load(); + LSett.LanguageCode = value; + Save(LSett); + } + } + private static void Save(Settings set) { XmlSerializer ser = new XmlSerializer(typeof(Settings)); @@ -86,10 +104,27 @@ private static Settings Load() if (File.Exists(GetSavePath())) { - using (FileStream fs = File.OpenRead(GetSavePath())) + try + { + using (FileStream fs = File.OpenRead(GetSavePath())) + { + XmlSerializer ser = new XmlSerializer(typeof(Settings)); + LoadedSettings = ser.Deserialize(fs) as Settings; + } + } + catch (InvalidOperationException) { - XmlSerializer ser = new XmlSerializer(typeof(Settings)); - LoadedSettings = ser.Deserialize(fs) as Settings; + // 配置文件格式与当前 Settings 不兼容(例如旧版本保存为 bool 的值现在改成了枚举) + // 删除损坏/旧格式配置文件,回退到默认设置 + try + { + File.Delete(GetSavePath()); + } + catch + { + // 忽略删除失败,使用默认设置继续运行 + } + LoadedSettings = null; } }