From 52ce8400bad17ef21d07144dee7e67c13e62f631 Mon Sep 17 00:00:00 2001 From: Dong <1278815766@qq.com> Date: Wed, 7 May 2025 13:58:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=9B=B4=E6=96=B0=E7=AA=97=E4=BD=93):=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9B=B4=E6=96=B0=E6=B5=81=E7=A8=8B=E5=92=8C?= =?UTF-8?q?=E7=AA=97=E4=BD=93=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加进度条更新逻辑,确保进度显示准确 - 设置窗体位置到屏幕右下角并置顶显示 - 移除窗体边框,优化视觉效果 - 添加总文件数统计,完善下载进度显示 - 优化状态更新逻辑,确保UI实时刷新 --- Form1.Designer.cs | 2 + Form1.cs | 191 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 173 insertions(+), 20 deletions(-) diff --git a/Form1.Designer.cs b/Form1.Designer.cs index f1b63fd..765bee1 100644 --- a/Form1.Designer.cs +++ b/Form1.Designer.cs @@ -67,10 +67,12 @@ this.Controls.Add(this.Status_Box); this.Controls.Add(this.Update_Pro); this.Controls.Add(this.Update_Text); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "Update"; this.Text = "自动更新"; + this.TopMost = true; this.Load += new System.EventHandler(this.Update_Load); this.ResumeLayout(false); this.PerformLayout(); diff --git a/Form1.cs b/Form1.cs index 82ce4e7..4e8ab56 100644 --- a/Form1.cs +++ b/Form1.cs @@ -38,6 +38,8 @@ namespace CheckDownload private Dictionary _downloadedFiles = new Dictionary(); /// 已完成下载的文件数 private int _completedFiles = 0; + /// 需要下载的总文件数 + private int _totalFilesToDownload = 0; /// /// 构造函数,初始化更新窗体 @@ -58,6 +60,49 @@ namespace CheckDownload Update_Pro.Value = 0; // 设置初始值 Update_Pro.Step = 1; // 设置步进值 } + + /// + /// 更新进度条值 + /// + /// 进度百分比(0-100) + private void UpdateProgressValue(int percentage) + { + // 确保百分比在有效范围内 + if (percentage < 0) percentage = 0; + if (percentage > 100) percentage = 100; + + // 在UI线程上更新进度条值 + if (this.InvokeRequired) + { + this.Invoke((MethodInvoker)delegate + { + // 确保进度条值不超出范围 + if (percentage >= Update_Pro.Minimum && percentage <= Update_Pro.Maximum) + { + Update_Pro.Value = percentage; + } + else + { + // 如果超出范围,则设置为最大或最小值 + Update_Pro.Value = Math.Min(Math.Max(percentage, Update_Pro.Minimum), Update_Pro.Maximum); + } + // 添加Application.DoEvents()调用,确保消息队列被处理 + Application.DoEvents(); + }); + } + else + { + if (percentage >= Update_Pro.Minimum && percentage <= Update_Pro.Maximum) + { + Update_Pro.Value = percentage; + } + else + { + Update_Pro.Value = Math.Min(Math.Max(percentage, Update_Pro.Minimum), Update_Pro.Maximum); + } + Application.DoEvents(); + } + } /// /// 窗体加载事件处理方法,启动更新流程 @@ -66,8 +111,27 @@ namespace CheckDownload /// 事件参数 public async void Update_Load(object sender, EventArgs e) { + // 设置窗体位置到屏幕右下角 + PositionFormToBottomRight(); + await UpdateFile(); // 执行更新流程 - this.Close(); // 更新完成后关闭窗体 + // 注意:窗体关闭逻辑已移至UpdateFile方法中,确保显示完成消息后再关闭 + } + + /// + /// 设置窗体位置到屏幕右下角 + /// + private void PositionFormToBottomRight() + { + // 获取当前屏幕的工作区域(排除任务栏等系统元素) + Rectangle workingArea = Screen.GetWorkingArea(this); + + // 计算窗体在右下角的位置 + int x = workingArea.Right - this.Width; + int y = workingArea.Bottom - this.Height; + + // 设置窗体位置 + this.Location = new Point(x, y); } /// @@ -78,31 +142,67 @@ namespace CheckDownload { try { - // 读取本地MD5文件信息 + // 定义更新流程的总步骤数和当前步骤 + const int totalSteps = 6; // 总共6个主要步骤 + int currentStep = 0; + + // 更新进度条初始状态 + UpdateProgressValue(0); + + // 步骤1: 读取本地MD5文件信息 + UpdateStatus("读取本地MD5文件..."); var localData = await ReadLocalMd5File(); if (!ValidateLocalData(localData.Version, localData.Md5, localData.Data)) return; + UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为16% - // 获取在线MD5文件信息 + // 步骤2: 获取在线MD5文件信息 + UpdateStatus("获取在线MD5文件信息..."); var onlineData = await GetOnlineMd5File(); if (!ValidateOnlineData(onlineData.Version, onlineData.Md5)) return; + UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为33% - // 比较版本,判断是否需要更新 - if (!ShouldUpdate(localData.Version, onlineData.Version)) return; + // 步骤3: 比较版本,判断是否需要更新 + UpdateStatus("比较版本信息..."); + if (!ShouldUpdate(localData.Version, onlineData.Version)) + { + UpdateStatus("当前已是最新版本,无需更新"); + UpdateProgressValue(100); // 完成进度 + return; + } + UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为50% - // 下载在线MD5文件 + // 步骤4: 下载在线MD5文件 + UpdateStatus("下载在线MD5文件..."); var onlineFileData = await DownloadOnlineMd5File(); if (onlineFileData == null) return; + UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为66% - // 比较文件差异 + // 步骤5: 比较文件差异 + UpdateStatus("比较文件差异..."); var differences = CompareDataDifferences(localData.Data, onlineFileData); + UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为83% + + // 步骤6: 下载和更新文件 if (differences.Count > 0) { // 下载需要更新的文件 await DownloadUpdatedFiles(differences); } + else + { + UpdateStatus("无文件需要更新"); + } // 替换本地MD5文件 ReplaceLocalMd5File(); + UpdateProgressValue(100); // 完成进度 + + // 显示更新完成消息 + UpdateStatus("更新完成"); + + // 等待1秒后关闭窗体 + await Task.Delay(1000); + this.Close(); } catch (Exception ex) { @@ -351,9 +451,13 @@ namespace CheckDownload // 重置下载状态 _completedFiles = 0; _downloadedFiles.Clear(); - Update_Pro.Maximum = differences.Count; - Update_Pro.Value = 0; - + + // 设置总文件数 + _totalFilesToDownload = differences.Count; + + // 更新状态信息 + UpdateStatus($"开始下载更新文件,共{differences.Count}个文件..."); + // 创建信号量控制并发下载数量 var semaphore = new SemaphoreSlim(MaxConcurrentDownloads); var downloadTasks = new List(); @@ -368,6 +472,7 @@ namespace CheckDownload await Task.WhenAll(downloadTasks); // 所有文件下载完成后统一校验和保存 + UpdateStatus("所有文件下载完成,开始校验和保存..."); VerifyAndSaveAllFiles(); } @@ -399,8 +504,7 @@ namespace CheckDownload { // 更新状态显示当前下载进度 int current = Interlocked.Increment(ref _completedFiles); - UpdateStatus($"正在下载 ({Update_Pro.Value + 1}/{Update_Pro.Maximum}): {expectedMd5}"); - + // 下载文件到内存 using (var client = new HttpClient()) { @@ -436,6 +540,8 @@ namespace CheckDownload // 创建失败文件列表 var failedFiles = new List(); + int processedCount = 0; + int totalFiles = _downloadedFiles.Count; foreach (var item in _downloadedFiles) { @@ -445,6 +551,10 @@ namespace CheckDownload try { + // 更新状态信息 + processedCount++; + UpdateStatus($"正在校验和保存文件 ({processedCount}/{totalFiles}): {relativePath}"); + // 计算内存中数据的MD5 string actualMd5; using (var md5 = MD5.Create()) @@ -465,6 +575,16 @@ namespace CheckDownload // 保存文件 File.WriteAllBytes(localPath, data); + + // 更新进度条 - 从95%到98% + // 确保即使在totalFiles为0的情况下也不会出现除零错误,并且百分比不会超过98 + int percentage = 95; + if (totalFiles > 0) + { + // 计算进度时确保不会超过98% + percentage = 95 + Math.Min(3, (int)(processedCount * 3.0 / totalFiles)); + } + UpdateProgressValue(percentage); } catch (Exception ex) { @@ -483,6 +603,10 @@ namespace CheckDownload { throw new Exception($"{failedFiles.Count}个文件校验失败"); } + else + { + UpdateStatus("所有文件校验和保存成功"); + } } /// @@ -547,14 +671,28 @@ namespace CheckDownload } /// - /// 更新进度条 + /// 更新文件下载进度 /// private void UpdateProgress() { - // 在UI线程上更新进度条值 - this.Invoke((MethodInvoker)delegate + // 计算下载进度百分比,避免除零错误 + int percentage = 0; + if (_totalFilesToDownload > 0) { - Update_Pro.Value++; + percentage = (int)(_completedFiles * 100.0 / _totalFilesToDownload); + } + + // 更新状态信息 + UpdateStatus($"正在下载文件 ({_completedFiles}/{_totalFilesToDownload})..."); + + // 在UI线程上更新进度条值 + this.BeginInvoke((MethodInvoker)delegate + { + // 在下载阶段,进度从83%到95%之间变化 + // 确保不会超过95% + int overallPercentage = 83 + Math.Min(12, (int)(percentage * 12.0 / 100)); + // 使用UpdateProgressValue方法确保值在有效范围内 + UpdateProgressValue(overallPercentage); }); } @@ -572,7 +710,7 @@ namespace CheckDownload } // 将下载的在线MD5文件移动到本地MD5文件位置 File.Move(_onlineMd5File, LocalMd5File); - UpdateStatus("已更新本地版本信息"); + UpdateStatus("更新完成"); } catch (Exception ex) { @@ -586,11 +724,24 @@ namespace CheckDownload /// 要显示的状态信息 private void UpdateStatus(string message) { - // 在UI线程上更新状态文本框 - this.Invoke((MethodInvoker)delegate + // 使用Invoke而不是BeginInvoke,确保UI更新完成 + if (this.InvokeRequired) + { + this.Invoke((MethodInvoker)delegate + { + Status_Box.Text = message; + // 立即刷新控件,确保状态实时显示 + Status_Box.Update(); + // 添加Application.DoEvents()调用,确保消息队列被处理 + Application.DoEvents(); + }); + } + else { Status_Box.Text = message; - }); + Status_Box.Update(); + Application.DoEvents(); + } } ///