• C# Winfrom 常用功能整合-2


    目录

    Winfrom 启动一个外部exe文件,并传入参数

    Winform ListBox用法

    HTTP下载文件(推荐)

    Winform HTTP下载并显示进度

    Winform HTTP下载文件

    Winform 跨线程访问UI组件

    Winform 改变文字的颜色和大小


    Winfrom 启动一个外部exe文件,并传入参数

    在我们常用的一些软件中,经常有些软件,双击之后根本打不开,这是因为启动时做了限制,我们需要传入一些参数才能打开,在工作中,这个需求也可以用在软件的自动更新上,在Unity里,有XLua,ILruntime 等框架进行热更新,在Winform中,由于Windows的机制,打开软件后,不能做文件替换工作,我们可以利用一个软件启动器,更新本地软件的文件,然后再启动软件,就达到了自动更新的目的,当然,软件本地也不能直接双击打开。

    新建一个winform 项目,界面如下,用来做一个软件启动器

    只需要添加一个按钮,给按钮添加点击事件,代码如下:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Diagnostics;
    6. using System.Drawing;
    7. using System.Linq;
    8. using System.Text;
    9. using System.Threading.Tasks;
    10. using System.Windows.Forms;
    11. namespace 启动器
    12. {
    13. public partial class Form1 : Form
    14. {
    15. public Form1()
    16. {
    17. InitializeComponent();
    18. }
    19. private void button1_Click(object sender, EventArgs e)
    20. {
    21. string path = "E:\\CSharp Project\\Test\\Test\\bin\\Debug\\Test.exe";
    22. string[] parameter = {"启动器参数1", "启动器参数2", "启动器参数3", "启动器参数4" };
    23. bool startResult = StartProcess(path, parameter);
    24. if (startResult)
    25. System.Environment.Exit(0);
    26. }
    27. ///
    28. /// 启动一个软件,并传入参数
    29. ///
    30. ///
    31. ///
    32. ///
    33. public bool StartProcess(string runFilePath, params string[] args)
    34. {
    35. string s = "";
    36. foreach (string arg in args)
    37. {
    38. s = s + arg + " ";
    39. }
    40. s = s.Trim();
    41. Process process = new Process();//创建进程对象
    42. ProcessStartInfo startInfo = new ProcessStartInfo(runFilePath, s); // 括号里是(程序名,参数)
    43. process.StartInfo = startInfo;
    44. process.Start();
    45. return true;
    46. }
    47. }
    48. }

    下面新建第二个项目,用来做软件的本体

    新建一个winform项目,里面什么都不用加,先设置软件的输出类型为控制台

    然后打开启动脚本 Program.cs ,添加参数的打印,由于软件刚启动时,控制台也刚打开,立马打印会看不见日志,于是我这里加了异步延时操作。

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Threading.Tasks;
    5. using System.Windows.Forms;
    6. namespace Test
    7. {
    8. static class Program
    9. {
    10. ///
    11. /// 应用程序的主入口点。
    12. ///
    13. [STAThread]
    14. static void Main(string[] args)
    15. {
    16. Task.Run(async () =>
    17. {
    18. await Task.Delay(TimeSpan.FromSeconds(5));
    19. if (args.Length > 0)
    20. {
    21. for (int i = 0; i < args.Length; i++)
    22. {
    23. Console.WriteLine("参数是:" + args[i]);
    24. }
    25. }
    26. else
    27. Console.WriteLine("args参数是0");
    28. });
    29. Application.EnableVisualStyles();
    30. Application.SetCompatibleTextRenderingDefault(false);
    31. Application.Run(new Form1());
    32. }
    33. }
    34. }

     现在开始测试,打开软件启动器,点击按钮,5秒后,然后就可以看到控制台的输出

    这里就可以对参数做一个限制了,如果参数不正确,直接return,用户就不能直接打开软件了 

    Winform ListBox用法

    在Winform中,ListBox用来显示日志还不错,如图:

    用法:

    1. ///
    2. /// 添加普通日志
    3. ///
    4. /// 内容
    5. public void AddOrdinaryLog(string content)
    6. {
    7. if (this.InvokeRequired)
    8. {
    9. //切换到UI线程
    10. this.Invoke(new MethodInvoker(delegate
    11. {
    12. AddOrdinaryLog_UI(content);
    13. }));
    14. }
    15. else
    16. {
    17. AddOrdinaryLog_UI(content);
    18. }
    19. }
    20. private void AddOrdinaryLog_UI(string content)
    21. {
    22. //读取当前ListBox列表长度
    23. int len = ListBox_OrdinaryLogList.Items.Count;
    24. //插入新的一行
    25. ListBox_OrdinaryLogList.Items.Insert(len, content);
    26. //列表长度大于30,那么就删除第1行的数据
    27. if (len > 30)
    28. ListBox_OrdinaryLogList.Items.RemoveAt(0);
    29. //插入新的数据后,将滚动条移动到最下面
    30. int visibleItems = ListBox_OrdinaryLogList.ClientSize.Height / ListBox_OrdinaryLogList.ItemHeight;
    31. ListBox_OrdinaryLogList.TopIndex = Math.Max(ListBox_OrdinaryLogList.Items.Count - visibleItems + 1, 0);
    32. }

    这里我加了一个线程的判断,不需要直接复制 AddOrdinaryLog_UI 这个方法即可。

    HTTP下载文件(推荐)

    代码:

    1. ///
    2. /// Http下载文件
    3. ///
    4. public static string HttpDownloadFile(string url, string path)
    5. {
    6. // 设置参数
    7. HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    8. //发送请求并获取相应回应数据
    9. HttpWebResponse response = request.GetResponse() as HttpWebResponse;
    10. //直到request.GetResponse()程序才开始向目标网页发送Post请求
    11. Stream responseStream = response.GetResponseStream();
    12. //创建本地文件写入流
    13. Stream stream = new FileStream(path, FileMode.Create);
    14. long totalBytes = response.ContentLength;
    15. Console.WriteLine("请求内容的长度:" + totalBytes);
    16. byte[] bArr = new byte[1024];
    17. int size = responseStream.Read(bArr, 0, (int)bArr.Length);
    18. long totalDownloadBytes = 0;
    19. while (size > 0)
    20. {
    21. totalDownloadBytes += size;
    22. stream.Write(bArr, 0, size);
    23. Console.WriteLine("下载进度:" + (int)totalDownloadBytes);
    24. size = responseStream.Read(bArr, 0, (int)bArr.Length);
    25. }
    26. stream.Close();
    27. responseStream.Close();
    28. return path;
    29. }

    调用:

    1. //下载360压缩的安装包
    2. string url1 = "https://dl.360safe.com/360zip_setup.exe";
    3. //下载到Debug目录下
    4. string url2 = Application.StartupPath + "\\360zip.exe";
    5. string res = HttpDownloadFile(url1, url2);
    6. Console.WriteLine("下载完成:" + res);

    Winform HTTP下载并显示进度

    效果:

    HTTPDownManager.cs

    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.Linq;
    5. using System.Text;
    6. using System.Threading.Tasks;
    7. namespace Utils
    8. {
    9. public class HTTPDownManager
    10. {
    11. ///
    12. /// 下载实时返回下载进度
    13. ///
    14. /// 下载地址
    15. /// 本地存储地址
    16. /// 委托回调函数
    17. public static void DownloadFileData(string URL, string savePath, Action<string, string, int> downAction, Action downEndAction)
    18. {
    19. try
    20. {
    21. float percent = 0;
    22. string fileName = Path.GetFileName(savePath);
    23. System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL);
    24. System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse();
    25. long totalBytes = myrp.ContentLength, totalDownloadedByte = 0;
    26. System.IO.Stream st = myrp.GetResponseStream(), so = new System.IO.FileStream(savePath, System.IO.FileMode.Create);
    27. byte[] by = new byte[1024];
    28. int osize = st.Read(by, 0, (int)by.Length);
    29. while (osize > 0)
    30. {
    31. totalDownloadedByte = osize + totalDownloadedByte;
    32. so.Write(by, 0, osize);
    33. osize = st.Read(by, 0, (int)by.Length);
    34. percent = (float)totalDownloadedByte / (float)totalBytes * 100;//当前位置
    35. //totalBytes 是总字节数
    36. downAction(fileName, GetSize(totalBytes), (int)percent);
    37. }
    38. if (downEndAction != null) downEndAction();
    39. so.Close();
    40. st.Close();
    41. }
    42. catch (System.Exception)
    43. {
    44. throw;
    45. }
    46. }
    47. ///
    48. /// 获取文件大小
    49. ///
    50. ///
    51. ///
    52. private static string GetSize(double size)
    53. {
    54. String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "PB" };
    55. double mod = 1024.0;
    56. int i = 0;
    57. while (size >= mod)
    58. {
    59. size /= mod;
    60. i++;
    61. }
    62. return Math.Round(size) + units[i];
    63. }
    64. }
    65. }

    Winform 界面

    Form1.cs

    1. using FileBootUp;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.ComponentModel;
    5. using System.Data;
    6. using System.Drawing;
    7. using System.IO;
    8. using System.Linq;
    9. using System.Net;
    10. using System.Text;
    11. using System.Threading.Tasks;
    12. using System.Windows.Forms;
    13. using Utils;
    14. namespace 下载文件1
    15. {
    16. public partial class Form1 : Form
    17. {
    18. public Form1()
    19. {
    20. InitializeComponent();
    21. }
    22. private string url = "http://localhost/vodo.mp4"; //下载地址
    23. private string loadFilefolder = Application.StartupPath + "//vodo.mp4";//保存位置
    24. private void Form1_Load(object sender, EventArgs e)
    25. {
    26. Task.Run(() =>
    27. {
    28. HTTPDownManager.DownloadFileData(url, loadFilefolder, DownProgress, DownEnd);
    29. });
    30. }
    31. private void DownProgress(string fileName, string size, int percent)
    32. {
    33. FormControlExtensions.InvokeIfRequired(this, () =>
    34. {
    35. this.Label_FileName.Text = string.Format("正在下载:{0}", fileName);
    36. this.Label_Size.Text = size;
    37. this.Label_DownProgress.Text = string.Format("{0}%", percent);
    38. this.ProgressBar_DownProgress.Value = percent;
    39. });
    40. }
    41. private void DownEnd()
    42. {
    43. Console.WriteLine("下载完成");
    44. }
    45. }
    46. }

    FormControlExtensions.cs

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. using System.Windows.Forms;
    7. namespace FileBootUp
    8. {
    9. public static class FormControlExtensions
    10. {
    11. ///
    12. /// Invokes actions in UI thread.
    13. ///
    14. public static void InvokeIfRequired(this Control control, Action action)
    15. {
    16. if (control.InvokeRequired)
    17. {
    18. control.Invoke(new MethodInvoker(action));
    19. }
    20. else
    21. {
    22. action();
    23. }
    24. }
    25. }
    26. }

    Winform HTTP下载文件

    效果:

    HttpHeper.cs

    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.Linq;
    5. using System.Net;
    6. using System.Text;
    7. using System.Windows.Forms;
    8. using System.Threading.Tasks;
    9. using System.Threading;
    10. namespace HTTPTool
    11. {
    12. public class HttpHelper
    13. {
    14. const int bytebuff = 1024;
    15. const int ReadWriteTimeOut = 2 * 1000;//超时等待时间
    16. const int TimeOutWait = 5 * 1000;//超时等待时间
    17. const int MaxTryTime = 12;
    18. private double totalSize, curReadSize, speed;
    19. private int proc, remainTime;
    20. private int totalTime = 0;
    21. private bool downLoadWorking = false;
    22. private string StrFileName = "";
    23. private string StrUrl = "";
    24. private string outMsg = "";
    25. private string fileName = string.Empty;
    26. public HttpHelper(string url, string savePath)
    27. {
    28. this.StrUrl = url;
    29. this.StrFileName = savePath;
    30. this.fileName = Path.GetFileName(savePath);
    31. }
    32. ///
    33. /// 下载数据更新
    34. ///
    35. /// 下载文件总大小
    36. /// 已下载文件大小
    37. /// 下载进度百分比
    38. /// 下载速度
    39. /// 剩余下载时间
    40. public delegate void delDownFileHandler(string totalNum, string num, int proc, string speed, string remainTime, string outMsg,string fileName);
    41. public delDownFileHandler processShow;
    42. public delegate void delDownCompleted();
    43. public delDownCompleted processCompleted;
    44. public System.Windows.Forms.Timer timer;
    45. public void init()
    46. {
    47. timer.Interval = 50;
    48. timer.Tick -= TickEventHandler;
    49. timer.Tick += TickEventHandler;
    50. timer.Enabled = true;
    51. downLoadWorking = true;
    52. }
    53. ///
    54. /// 获取文件大小
    55. ///
    56. ///
    57. ///
    58. private string GetSize(double size)
    59. {
    60. String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "PB" };
    61. double mod = 1024.0;
    62. int i = 0;
    63. while (size >= mod)
    64. {
    65. size /= mod;
    66. i++;
    67. }
    68. return Math.Round(size) + units[i];
    69. }
    70. ///
    71. /// 获取时间
    72. ///
    73. ///
    74. ///
    75. private string GetTime(int second)
    76. {
    77. return new DateTime(1970, 01, 01, 00, 00, 00).AddSeconds(second).ToString("HH:mm:ss");
    78. }
    79. ///
    80. /// 下载文件(同步) 支持断点续传
    81. ///
    82. public void DowLoadFile()
    83. {
    84. totalSize = GetFileContentLength(StrUrl);
    85. //打开上次下载的文件或新建文件
    86. long lStartPos = 0;
    87. System.IO.FileStream fs;
    88. if (System.IO.File.Exists(StrFileName))
    89. {
    90. fs = System.IO.File.OpenWrite(StrFileName);
    91. lStartPos = fs.Length;
    92. fs.Seek(lStartPos, System.IO.SeekOrigin.Current); //移动文件流中的当前指针
    93. }
    94. else
    95. {
    96. fs = new System.IO.FileStream(StrFileName, System.IO.FileMode.Create);
    97. lStartPos = 0;
    98. }
    99. curReadSize = lStartPos;
    100. if (curReadSize == totalSize)
    101. {
    102. outMsg = "文件已下载!";
    103. processCompleted?.Invoke();
    104. timer.Enabled = false;
    105. return;
    106. }
    107. //打开网络连接
    108. try
    109. {
    110. System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl);
    111. if (lStartPos > 0)
    112. request.AddRange((int)lStartPos); //设置Range值
    113. //向服务器请求,获得服务器回应数据流
    114. System.IO.Stream ns = request.GetResponse().GetResponseStream();
    115. byte[] nbytes = new byte[bytebuff];
    116. int nReadSize = 0;
    117. proc = 0;
    118. do
    119. {
    120. nReadSize = ns.Read(nbytes, 0, bytebuff);
    121. fs.Write(nbytes, 0, nReadSize);
    122. //已下载大小
    123. curReadSize += nReadSize;
    124. //进度百分比
    125. proc = (int)((curReadSize / totalSize) * 100);
    126. //下载速度
    127. speed = (curReadSize / totalTime) * 10;
    128. //剩余时间
    129. remainTime = (int)((totalSize / speed) - (totalTime / 10));
    130. if (downLoadWorking == false)
    131. break;
    132. } while (nReadSize > 0);
    133. fs.Close();
    134. ns.Close();
    135. if (curReadSize == totalSize)
    136. {
    137. outMsg = "下载完成!";
    138. processCompleted?.Invoke();
    139. downLoadWorking = false;
    140. }
    141. }
    142. catch (Exception ex)
    143. {
    144. fs.Close();
    145. outMsg = string.Format("下载失败:{0}", ex.ToString());
    146. }
    147. }
    148. public void DownLoadPause()
    149. {
    150. outMsg = "下载已暂停";
    151. downLoadWorking = false;
    152. }
    153. public void DownLoadContinue()
    154. {
    155. outMsg = "正在下载";
    156. downLoadWorking = true;
    157. DownLoadStart();
    158. }
    159. public void DownLoadStart()
    160. {
    161. Task.Run(() =>
    162. {
    163. DowLoadFile();
    164. });
    165. }
    166. ///
    167. /// 定时器方法
    168. ///
    169. ///
    170. ///
    171. private void TickEventHandler(object sender, EventArgs e)
    172. {
    173. processShow?.Invoke(GetSize(totalSize),
    174. GetSize(curReadSize),
    175. proc,
    176. string.Format("{0}/s", GetSize(speed)),
    177. GetTime(remainTime),
    178. outMsg,
    179. fileName
    180. );
    181. if (downLoadWorking == true)
    182. {
    183. totalTime++;
    184. }
    185. }
    186. ///
    187. /// 获取下载文件长度
    188. ///
    189. ///
    190. ///
    191. public long GetFileContentLength(string url)
    192. {
    193. HttpWebRequest request = null;
    194. try
    195. {
    196. request = (HttpWebRequest)HttpWebRequest.Create(url);
    197. //request.Timeout = TimeOutWait;
    198. //request.ReadWriteTimeout = ReadWriteTimeOut;
    199. //向服务器请求,获得服务器回应数据流
    200. WebResponse respone = request.GetResponse();
    201. request.Abort();
    202. return respone.ContentLength;
    203. }
    204. catch (WebException e)
    205. {
    206. if (request != null)
    207. request.Abort();
    208. return 0;
    209. }
    210. }
    211. }
    212. }

    winform 界面:

    代码:

    1. using HTTPTool;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.ComponentModel;
    5. using System.Data;
    6. using System.Drawing;
    7. using System.Linq;
    8. using System.Text;
    9. using System.Threading.Tasks;
    10. using System.Windows.Forms;
    11. namespace 下载文件
    12. {
    13. public partial class Form1 : Form
    14. {
    15. public Form1()
    16. {
    17. InitializeComponent();
    18. }
    19. static string url = "http://localhost/vodo.mp4"; //下载地址
    20. static string loadFilefolder = Application.StartupPath + "//vodo.mp4";//保存位置
    21. HttpHelper httpManager = new HttpHelper(url, loadFilefolder);
    22. private void Form1_Load(object sender, EventArgs e)
    23. {
    24. httpManager.timer = new System.Windows.Forms.Timer();
    25. httpManager.processShow += processSho;
    26. httpManager.processCompleted += processComplete;
    27. httpManager.init();
    28. }
    29. public void processSho(string totalNum, string num, int proc, string speed, string remainTime, string msg, string fileName)
    30. {
    31. this.label1.Text = string.Format("文件大小:{0}", totalNum);
    32. this.label2.Text = string.Format("已下载:{0}", num);
    33. this.label3.Text = string.Format("进度:{0}%", proc);
    34. this.label4.Text = msg;
    35. this.label5.Text = string.Format("速度:{0}", speed);
    36. this.label6.Text = string.Format("剩余时间:{0}", remainTime);
    37. this.label7.Text = fileName;
    38. progressBar1.Value = proc;
    39. }
    40. private void processComplete()
    41. {
    42. MessageBox.Show("文件下载完成!", "提示");
    43. }
    44. private void button1_Click(object sender, EventArgs e)
    45. {
    46. httpManager.DownLoadStart();
    47. }
    48. private void button2_Click(object sender, EventArgs e)
    49. {
    50. httpManager.DownLoadPause();
    51. }
    52. private void button3_Click(object sender, EventArgs e)
    53. {
    54. httpManager.DownLoadContinue();
    55. }
    56. }
    57. }

    源码文件:点击下载

    Winform 跨线程访问UI组件

    this.Invoke 必须运行在winform的代码中,所有下面的代码也只能写在Form 界面代码中。

    代码:

    1. var task = Task.Run(async delegate
    2. {
    3. await Task.Delay(200);
    4. this.Invoke(new MethodInvoker(delegate {
    5. Label_Log.Text = string.Empty;
    6. }));
    7. });

    如果在其他的线程中,调用UI 相关的控件需要切换线程,否则会报错。

    下面方法可以切换到UI 线程并执行 Action

    1. public static class FormControlExtensions
    2. {
    3. ///
    4. /// Invokes actions in UI thread.
    5. ///
    6. public static void InvokeIfRequired(this Control control, Action action)
    7. {
    8. if (control.InvokeRequired)
    9. {
    10. control.Invoke(new MethodInvoker(action));
    11. }
    12. else
    13. {
    14. action();
    15. }
    16. }
    17. }

    其实也可以这样写,申请一个线程,执行完成后,再切换到 UI 线程,这样就不会卡界面了

    1. new Thread((ThreadStart)(delegate()
    2. {
    3. //线程内的计算
    4. //......
    5. //切换回UI线程
    6. this.Dispatcher.BeginInvoke((Action)delegate
    7. {
    8. //Label1.Text = "执行完成";
    9. });
    10. })).Start();

    Winform 改变文字的颜色和大小

    代码

    1. label1.Font = new Font("隶书", 20, FontStyle.Bold); //第一个是字体,第二个大小,第三个是样式,
    2. label1.ForeColor = Color.Red; //颜色
    3. label2.Font = new Font("华文行楷", 20, FontStyle.Bold); //第一个是字体,第二个大小,第三个是样式,
    4. label2.ForeColor = Color.Green; //颜色
    5. label3.Font = new Font("宋体", 20, FontStyle.Bold); //第一个是字体,第二个大小,第三个是样式,
    6. label3.ForeColor = Color.Blue; //颜色
    7. label3.Text = DateTime.Now.ToString("yyyy-MM-dd");

    end

  • 相关阅读:
    RuoYi-Vue Spring Security 配置介绍
    手把手教会将 Windows 窗体桌面应用从.NET Framework迁移到 .NET SDK/.NET 6 格式
    【SQL刷题】Day2----SQL语法基础查询
    聚观早报 |中国企业成世界杯最大金主;马斯克恐失去世界首富位置
    Qt之实现支持多选的QCombobox
    液晶显示计算器(按键程序)
    交叉编译器环境配置与boa嵌入式web服务器移植问题
    深度强化学习中利用Q-Learngin和期望Sarsa算法确定机器人最优策略实战(超详细 附源码)
    PostgreSQL解决死锁
    大数据错误
  • 原文地址:https://blog.csdn.net/qq_38693757/article/details/125996731