【C#】C# Winfrom 常用功能整合-2
目录
Winfrom 启动一个外部exe文件,并传入参数
在我们常用的一些软件中,经常有些软件,双击之后根本打不开,这是因为启动时做了限制,我们需要传入一些参数才能打开,在工作中,这个需求也可以用在软件的自动更新上,在Unity里,有XLua,ILruntime 等框架进行热更新,在Winform中,由于Windows的机制,打开软件后,不能做文件替换工作,我们可以利用一个软件启动器,更新本地软件的文件,然后再启动软件,就达到了自动更新的目的,当然,软件本地也不能直接双击打开。
新建一个winform 项目,界面如下,用来做一个软件启动器
只需要添加一个按钮,给按钮添加点击事件,代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace 启动器 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string path = "E:\\CSharp Project\\Test\\Test\\bin\\Debug\\Test.exe"; string[] parameter = {"启动器参数1", "启动器参数2", "启动器参数3", "启动器参数4" }; bool startResult = StartProcess(path, parameter); if (startResult) System.Environment.Exit(0); } /// <summary> /// 启动一个软件,并传入参数 /// </summary> /// <param name="runFilePath"></param> /// <param name="args"></param> /// <returns></returns> public bool StartProcess(string runFilePath, params string[] args) { string s = ""; foreach (string arg in args) { s = s + arg + " "; } s = s.Trim(); Process process = new Process();//创建进程对象 ProcessStartInfo startInfo = new ProcessStartInfo(runFilePath, s); // 括号里是(程序名,参数) process.StartInfo = startInfo; process.Start(); return true; } } }
下面新建第二个项目,用来做软件的本体
新建一个winform项目,里面什么都不用加,先设置软件的输出类型为控制台
然后打开启动脚本 Program.cs ,添加参数的打印,由于软件刚启动时,控制台也刚打开,立马打印会看不见日志,于是我这里加了异步延时操作。
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace Test { static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { Task.Run(async () => { await Task.Delay(TimeSpan.FromSeconds(5)); if (args.Length > 0) { for (int i = 0; i < args.Length; i++) { Console.WriteLine("参数是:" + args[i]); } } else Console.WriteLine("args参数是0"); }); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
现在开始测试,打开软件启动器,点击按钮,5秒后,然后就可以看到控制台的输出
这里就可以对参数做一个限制了,如果参数不正确,直接return,用户就不能直接打开软件了
Winform ListBox用法
在Winform中,ListBox用来显示日志还不错,如图:
用法:
/// <summary> /// 添加普通日志 /// </summary> /// <param name="content">内容</param> public void AddOrdinaryLog(string content) { if (this.InvokeRequired) { //切换到UI线程 this.Invoke(new MethodInvoker(delegate { AddOrdinaryLog_UI(content); })); } else { AddOrdinaryLog_UI(content); } } private void AddOrdinaryLog_UI(string content) { //读取当前ListBox列表长度 int len = ListBox_OrdinaryLogList.Items.Count; //插入新的一行 ListBox_OrdinaryLogList.Items.Insert(len, content); //列表长度大于30,那么就删除第1行的数据 if (len > 30) ListBox_OrdinaryLogList.Items.RemoveAt(0); //插入新的数据后,将滚动条移动到最下面 int visibleItems = ListBox_OrdinaryLogList.ClientSize.Height / ListBox_OrdinaryLogList.ItemHeight; ListBox_OrdinaryLogList.TopIndex = Math.Max(ListBox_OrdinaryLogList.Items.Count - visibleItems + 1, 0); }
这里我加了一个线程的判断,不需要直接复制 AddOrdinaryLog_UI 这个方法即可。
HTTP下载文件(推荐)
代码:
/// <summary> /// Http下载文件 /// </summary> public static string HttpDownloadFile(string url, string path) { // 设置参数 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; //发送请求并获取相应回应数据 HttpWebResponse response = request.GetResponse() as HttpWebResponse; //直到request.GetResponse()程序才开始向目标网页发送Post请求 Stream responseStream = response.GetResponseStream(); //创建本地文件写入流 Stream stream = new FileStream(path, FileMode.Create); long totalBytes = response.ContentLength; Console.WriteLine("请求内容的长度:" + totalBytes); byte[] bArr = new byte[1024]; int size = responseStream.Read(bArr, 0, (int)bArr.Length); long totalDownloadBytes = 0; while (size > 0) { totalDownloadBytes += size; stream.Write(bArr, 0, size); Console.WriteLine("下载进度:" + (int)totalDownloadBytes); size = responseStream.Read(bArr, 0, (int)bArr.Length); } stream.Close(); responseStream.Close(); return path; }
调用:
//下载360压缩的安装包 string url1 = "https://dl.360safe.com/360zip_setup.exe"; //下载到Debug目录下 string url2 = Application.StartupPath + "\\360zip.exe"; string res = HttpDownloadFile(url1, url2); Console.WriteLine("下载完成:" + res);
Winform HTTP下载并显示进度
效果:
HTTPDownManager.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Utils { public class HTTPDownManager { /// <summary> /// 下载实时返回下载进度 /// </summary> /// <param name="URL">下载地址</param> /// <param name="savePath">本地存储地址</param> /// <param name="downAction">委托回调函数</param> public static void DownloadFileData(string URL, string savePath, Action<string, string, int> downAction, Action downEndAction) { try { float percent = 0; string fileName = Path.GetFileName(savePath); System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); long totalBytes = myrp.ContentLength, totalDownloadedByte = 0; System.IO.Stream st = myrp.GetResponseStream(), so = new System.IO.FileStream(savePath, System.IO.FileMode.Create); byte[] by = new byte[1024]; int osize = st.Read(by, 0, (int)by.Length); while (osize > 0) { totalDownloadedByte = osize + totalDownloadedByte; so.Write(by, 0, osize); osize = st.Read(by, 0, (int)by.Length); percent = (float)totalDownloadedByte / (float)totalBytes * 100;//当前位置 //totalBytes 是总字节数 downAction(fileName, GetSize(totalBytes), (int)percent); } if (downEndAction != null) downEndAction(); so.Close(); st.Close(); } catch (System.Exception) { throw; } } /// <summary> /// 获取文件大小 /// </summary> /// <param name="size"></param> /// <returns></returns> private static string GetSize(double size) { String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "PB" }; double mod = 1024.0; int i = 0; while (size >= mod) { size /= mod; i++; } return Math.Round(size) + units[i]; } } }
Winform 界面
Form1.cs
using FileBootUp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Utils; namespace 下载文件1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private string url = "http://localhost/vodo.mp4"; //下载地址 private string loadFilefolder = Application.StartupPath + "//vodo.mp4";//保存位置 private void Form1_Load(object sender, EventArgs e) { Task.Run(() => { HTTPDownManager.DownloadFileData(url, loadFilefolder, DownProgress, DownEnd); }); } private void DownProgress(string fileName, string size, int percent) { FormControlExtensions.InvokeIfRequired(this, () => { this.Label_FileName.Text = string.Format("正在下载:{0}", fileName); this.Label_Size.Text = size; this.Label_DownProgress.Text = string.Format("{0}%", percent); this.ProgressBar_DownProgress.Value = percent; }); } private void DownEnd() { Console.WriteLine("下载完成"); } } }
FormControlExtensions.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace FileBootUp { public static class FormControlExtensions { /// <summary> /// Invokes actions in UI thread. /// </summary> public static void InvokeIfRequired(this Control control, Action action) { if (control.InvokeRequired) { control.Invoke(new MethodInvoker(action)); } else { action(); } } } }
Winform HTTP下载文件
效果:
HttpHeper.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Windows.Forms; using System.Threading.Tasks; using System.Threading; namespace HTTPTool { public class HttpHelper { const int bytebuff = 1024; const int ReadWriteTimeOut = 2 * 1000;//超时等待时间 const int TimeOutWait = 5 * 1000;//超时等待时间 const int MaxTryTime = 12; private double totalSize, curReadSize, speed; private int proc, remainTime; private int totalTime = 0; private bool downLoadWorking = false; private string StrFileName = ""; private string StrUrl = ""; private string outMsg = ""; private string fileName = string.Empty; public HttpHelper(string url, string savePath) { this.StrUrl = url; this.StrFileName = savePath; this.fileName = Path.GetFileName(savePath); } /// <summary> /// 下载数据更新 /// </summary> /// <param name="totalNum">下载文件总大小</param> /// <param name="num">已下载文件大小</param> /// <param name="proc">下载进度百分比</param> /// <param name="speed">下载速度</param> /// <param name="remainTime">剩余下载时间</param> public delegate void delDownFileHandler(string totalNum, string num, int proc, string speed, string remainTime, string outMsg,string fileName); public delDownFileHandler processShow; public delegate void delDownCompleted(); public delDownCompleted processCompleted; public System.Windows.Forms.Timer timer; public void init() { timer.Interval = 50; timer.Tick -= TickEventHandler; timer.Tick += TickEventHandler; timer.Enabled = true; downLoadWorking = true; } /// <summary> /// 获取文件大小 /// </summary> /// <param name="size"></param> /// <returns></returns> private string GetSize(double size) { String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "PB" }; double mod = 1024.0; int i = 0; while (size >= mod) { size /= mod; i++; } return Math.Round(size) + units[i]; } /// <summary> /// 获取时间 /// </summary> /// <param name="second"></param> /// <returns></returns> private string GetTime(int second) { return new DateTime(1970, 01, 01, 00, 00, 00).AddSeconds(second).ToString("HH:mm:ss"); } /// <summary> /// 下载文件(同步) 支持断点续传 /// </summary> public void DowLoadFile() { totalSize = GetFileContentLength(StrUrl); //打开上次下载的文件或新建文件 long lStartPos = 0; System.IO.FileStream fs; if (System.IO.File.Exists(StrFileName)) { fs = System.IO.File.OpenWrite(StrFileName); lStartPos = fs.Length; fs.Seek(lStartPos, System.IO.SeekOrigin.Current); //移动文件流中的当前指针 } else { fs = new System.IO.FileStream(StrFileName, System.IO.FileMode.Create); lStartPos = 0; } curReadSize = lStartPos; if (curReadSize == totalSize) { outMsg = "文件已下载!"; processCompleted?.Invoke(); timer.Enabled = false; return; } //打开网络连接 try { System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl); if (lStartPos > 0) request.AddRange((int)lStartPos); //设置Range值 //向服务器请求,获得服务器回应数据流 System.IO.Stream ns = request.GetResponse().GetResponseStream(); byte[] nbytes = new byte[bytebuff]; int nReadSize = 0; proc = 0; do { nReadSize = ns.Read(nbytes, 0, bytebuff); fs.Write(nbytes, 0, nReadSize); //已下载大小 curReadSize += nReadSize; //进度百分比 proc = (int)((curReadSize / totalSize) * 100); //下载速度 speed = (curReadSize / totalTime) * 10; //剩余时间 remainTime = (int)((totalSize / speed) - (totalTime / 10)); if (downLoadWorking == false) break; } while (nReadSize > 0); fs.Close(); ns.Close(); if (curReadSize == totalSize) { outMsg = "下载完成!"; processCompleted?.Invoke(); downLoadWorking = false; } } catch (Exception ex) { fs.Close(); outMsg = string.Format("下载失败:{0}", ex.ToString()); } } public void DownLoadPause() { outMsg = "下载已暂停"; downLoadWorking = false; } public void DownLoadContinue() { outMsg = "正在下载"; downLoadWorking = true; DownLoadStart(); } public void DownLoadStart() { Task.Run(() => { DowLoadFile(); }); } /// <summary> /// 定时器方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TickEventHandler(object sender, EventArgs e) { processShow?.Invoke(GetSize(totalSize), GetSize(curReadSize), proc, string.Format("{0}/s", GetSize(speed)), GetTime(remainTime), outMsg, fileName ); if (downLoadWorking == true) { totalTime++; } } /// <summary> /// 获取下载文件长度 /// </summary> /// <param name="url"></param> /// <returns></returns> public long GetFileContentLength(string url) { HttpWebRequest request = null; try { request = (HttpWebRequest)HttpWebRequest.Create(url); //request.Timeout = TimeOutWait; //request.ReadWriteTimeout = ReadWriteTimeOut; //向服务器请求,获得服务器回应数据流 WebResponse respone = request.GetResponse(); request.Abort(); return respone.ContentLength; } catch (WebException e) { if (request != null) request.Abort(); return 0; } } } }
winform 界面:
代码:
using HTTPTool; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace 下载文件 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } static string url = "http://localhost/vodo.mp4"; //下载地址 static string loadFilefolder = Application.StartupPath + "//vodo.mp4";//保存位置 HttpHelper httpManager = new HttpHelper(url, loadFilefolder); private void Form1_Load(object sender, EventArgs e) { httpManager.timer = new System.Windows.Forms.Timer(); httpManager.processShow += processSho; httpManager.processCompleted += processComplete; httpManager.init(); } public void processSho(string totalNum, string num, int proc, string speed, string remainTime, string msg, string fileName) { this.label1.Text = string.Format("文件大小:{0}", totalNum); this.label2.Text = string.Format("已下载:{0}", num); this.label3.Text = string.Format("进度:{0}%", proc); this.label4.Text = msg; this.label5.Text = string.Format("速度:{0}", speed); this.label6.Text = string.Format("剩余时间:{0}", remainTime); this.label7.Text = fileName; progressBar1.Value = proc; } private void processComplete() { MessageBox.Show("文件下载完成!", "提示"); } private void button1_Click(object sender, EventArgs e) { httpManager.DownLoadStart(); } private void button2_Click(object sender, EventArgs e) { httpManager.DownLoadPause(); } private void button3_Click(object sender, EventArgs e) { httpManager.DownLoadContinue(); } } }
源码文件:点击下载
Winform 跨线程访问UI组件
this.Invoke 必须运行在winform的代码中,所有下面的代码也只能写在Form 界面代码中。
代码:
var task = Task.Run(async delegate { await Task.Delay(200); this.Invoke(new MethodInvoker(delegate { Label_Log.Text = string.Empty; })); });
如果在其他的线程中,调用UI 相关的控件需要切换线程,否则会报错。
下面方法可以切换到UI 线程并执行 Action
public static class FormControlExtensions { /// <summary> /// Invokes actions in UI thread. /// </summary> public static void InvokeIfRequired(this Control control, Action action) { if (control.InvokeRequired) { control.Invoke(new MethodInvoker(action)); } else { action(); } } }
其实也可以这样写,申请一个线程,执行完成后,再切换到 UI 线程,这样就不会卡界面了
new Thread((ThreadStart)(delegate() { //线程内的计算 //...... //切换回UI线程 this.Dispatcher.BeginInvoke((Action)delegate { //Label1.Text = "执行完成"; }); })).Start();
Winform 改变文字的颜色和大小
代码
label1.Font = new Font("隶书", 20, FontStyle.Bold); //第一个是字体,第二个大小,第三个是样式, label1.ForeColor = Color.Red; //颜色 label2.Font = new Font("华文行楷", 20, FontStyle.Bold); //第一个是字体,第二个大小,第三个是样式, label2.ForeColor = Color.Green; //颜色 label3.Font = new Font("宋体", 20, FontStyle.Bold); //第一个是字体,第二个大小,第三个是样式, label3.ForeColor = Color.Blue; //颜色 label3.Text = DateTime.Now.ToString("yyyy-MM-dd");
end
猜你喜欢
- 【C#】从零开始用C#写一个桌面应用程序(一)基础操作
- 准备winform应用程序编写桌面应用客户端的技术。xaml一种标记语言。winform程序组成。 程序入口: form.cs和它的设计文件: 启动的过程以及涉及的文件:main函数: form1的构造函数和它的设计文件: main-》构造form-》initializeComponent-》 拖入一个 button控件可以看到: 这时我们已经梳理启动过程。使用组件的方法 可以在
- 【C#】C#Windows桌面应用开发实践
- 速览必须功能一览简单下载异步下载如何解决下载文件不完整的问题使用 Downloader 进行 HTTP 多线程下载创建一个下载服务:下载非 HTTP 协议的文件注册表相关的操作(添加与删除)文件占用问题的处理防止重复启动只开一个实例,通用弹窗和提示 使用示例使用 C# 下载文件 (引用自使用 C# 下载文件的十八般武艺)常用接口示例必须功能一览注册表相关的操作(添加与删除) RegistryKey hkm
- 【C#】C#调用win10系统自带软键盘的方法
- 上次做了个笔记是关于调用windows系统自带的触摸键盘的方法:C#调用Windows系统自带触摸键盘的方法_c# 虚拟键盘-CSDN博客除了调用触摸键盘,我们也可以通过调用win10的自带软键盘作为输入途径。方法很简单。1、添加using System.Diagnostics引用。2、创建进程Process Winvirkey = Process.Start("osk.exe");3、打开键盘:Winvirkey = Process.Start("osk.exe&
- 【C#】C# Winform 定时清理日志
- 一、前言在 Winform 开发中经常有这样的需求,在用户执行一些操作不正确时,需要将错误信息反馈给用户,比如:登录密码不正确,无法连接到服务器等,一般常见的用法有两个:1.弹框使用 MessageBox.Show("密码错误"); 这样的方式,弹框后,用户必须点击确定后才能执行下一步操作,给用户的体验并不是特别好。2.在界面中显示错误信息,定时清除如果是输入框,直接用 ErrorProvider 控件就行了。如果只是做一些简单的提示信息,那么就要定时清除
- 【C#】c#开发桌面应用程序用什么框架
- style="text-wrap: wrap;">在C#开发桌面应用程序时,可以使用以下几种常见的框架:</p><ol class=" list-paddingleft-2" style="width: 1529.1px; text-wrap: wrap;"><li><p>Windows Forms:这是一种由.NET Framework提供的GUI框架,它提供了丰富的GUI控件和易于使用的编程模型。Windows Forms在C#开发领域中使用非常广泛,并且已经存在多年,获得了广泛的支持和优化。</p></li></ol
- 【C#】Winform NanUI 0.77版本 清除Cookie等本地缓存
- 目录需求NanUI0.88版本的缓存路径NanUI0.77版本的缓存路径试着实现功能添加扩展出现的问题解决问题结束需求清除web前端保存的一些的数据,或者清除浏览器缓存会用到。NanUI0.88版本的缓存路径在NanUI0.88版本中,只要在Program.cs启动模块中调用app.ClearCacheFile();就可以清除浏览的缓存了。0.88版本的缓存路径:"C:\\Users\\Administrator\\AppData\\Roaming\\Net Dimension Stu
- 【C#】C# 开源框架(整理)
- C# 开源框架(整理)Json.NEThttp://json.codeplex.com/Json.Net 是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单。通过Linq To JSON可以快速的读写Json,通过JsonSerializer可以序列化你的.Net对象。让你轻松实现.Net中所有类型(对象,基本数据类型 等)和Json的转换。Math.NEThttp://www.mathdotnet.com/Math.NET的目标是为提供一款
- 【C#】C# Winform 文本面板带滚动条
- 在PC软件开发中经常有这样的需求,需要在一个固定大小的面板中显示一些内容,并且面板能上下拖动,将所有的内容完整的展示,有点类似网页上看新闻,如果要在 winfrom 中要如何实现的呢,下面就演示如何实现的吧效果:1.新建一个winform 项目,在界面中拖入一个Panel 将 panel1 的 AutoScroll 设置为 True2.再次拖入一个 Panel ,将高度拉长,这时就自动出现了滚动条,只是此时里面还没有任何内容,下面就在 panel2 中加入一点内容。