一. C#使用場景介紹 C#是微軟公司發佈的一種由C和C++衍生出來的面向對象的編程語言、運行於.NET Framework和.NET Core(完全開源,跨平臺)之上的高級程式設計語言。 二. 開發流程 1. 創建項目:打開Visual Studio後右側選擇“創建新項目”,然後選擇“C# Win ...
一. C#使用場景介紹
C#是微軟公司發佈的一種由C和C++衍生出來的面向對象的編程語言、運行於.NET Framework和.NET Core(完全開源,跨平臺)之上的高級程式設計語言。
二. 開發流程
1. 創建項目:打開Visual Studio後右側選擇“創建新項目”,然後選擇“C# Windows窗體應用”即可創建桌面程式
2. 創建窗體:創建後會自動創建一個Form窗體作為主視窗,可以採用拖拽方式進行項目開發,通過導航欄的《視圖》-->《工具欄》打開內置的工具箱功能
3. 啟動開發:開發時有兩種模式,可視化開發和編寫代碼。可視化開發選中窗體或者元素右側會彈出屬性欄可以設置樣式以及定義事件;代碼開發可以通過對應的映射文件進行邏輯開發。
4. 運行程式:開發完成後點擊屏幕上方的綠色箭頭按鈕,“啟動”按鈕運行程式同時進入Debug模式,支持功能調試,“開始運行”按鈕只運行程式,沒有進入Debug模式。
5. 生成解決方案:點擊導航欄上的“生成”->“生成解決方案”就可以生成項目文件
三. 常用功能
1. 彈出框和自動關閉彈框:項目開發中經常需要彈出框以及關閉彈出框,建議根據不同的等級封裝統一組件進行調用
// 提示彈框 public static void PopWarning(string tip, string title = "提示") { MessageBox.Show(tip, title); } // 錯誤彈框 public static void PopError(string tip, string title = "錯誤") { MessageBox.Show(tip, title); } // 自動關閉彈框 public void BoxAutoClose(string tip, int time = 3000) { Form msg = new Form(); Task.Run(new Action(() => { Thread.Sleep(time); msg.Invoke((Action)(() => { msg.Close(); })); })); MessageBox.Show(msg, tip, "提示"); }
2. 串口的使用和指令的封裝:項目開發中需要和固件通過串口進行數據交互,C#內置Serialport組件可以使用,但是建議不要拖拽,最好是new一個,然後將發送指令、接收指令以及超時機制結合在一起使用
// 命令類,存儲指令和時間對象 class Command { // 存儲指令數據集 public Dictionary<string, Hashtable> data = new Dictionary<string, Hashtable>(); // 預設超時時間是7秒 public void Set(string id, int timeUpper = 7) { if (data.ContainsKey(id)) { data[id]["time"] = DateTime.Now; } else { Hashtable ht = new Hashtable(); ht.Add("time", DateTime.Now); ht.Add("timeUpper", timeUpper); data[id] = ht; } } public void Delete(string id) { data.Remove(id); } public void DeleteAll() { data.Clear(); } /** * 識別超時的命令 */ public string[] CheckOverTime() { if (data == null) { return new string[0] { }; } string[] coms = new string[data.Count]; for (int i = 0; i < data.Count; i++) { DateTime val = (DateTime)data.ElementAt(i).Value["time"]; int timeUpper = (int)data.ElementAt(i).Value["timeUpper"]; if (new TimeSpan(DateTime.Now.Ticks - val.Ticks).TotalSeconds > timeUpper) { coms[i] = data.ElementAt(i).Key; } } return coms.Where(e => e != null).ToArray(); } }創建一個Command類,主要存儲發送指令集以及判斷指令是否超時
class Serial { private SerialPort port; Form main; Command cmd; public Serial(Form main) { this.main = main; cmd = new Command(); this.Init(); this.CreateTimer(); } /** * 創建定時器,每秒查詢一次是否有超時的命令 */ public void CreateTimer() { System.Timers.Timer cTimer = new System.Timers.Timer(); cTimer.Interval = 1000; cTimer.Enabled = true; cTimer.AutoReset = true; cTimer.Elapsed += new System.Timers.ElapsedEventHandler((Object source, ElapsedEventArgs e) => { string[] cmds = cmd.CheckOverTime(); for (int i = 0; i < cmds.Length; i++) { cmd.Delete(cmds[i]); if (cmds[i] != "FF") { // 返回主視窗超時標識 main.DealRes(new byte[] { (byte)Convert.ToInt32(cmds[i], 16) }, 1); } } }); } /** * 初始化創建串口組件 */ void Init() { port = new SerialPort(); port.BaudRate = 9600; port.Parity = Parity.None; port.StopBits = StopBits.One; port.DataBits = 8; port.DataReceived += new SerialDataReceivedEventHandler(ReceiveData); } /** * 將字元數組轉換成字元串 */ public static string ByteToStr(byte[] data) { string str = ""; for (int i = 0; i < data.Length; i++) { str += data[i].ToString("X2"); } return str; } /** * 接收數據並解析,將解析結果返回主視窗 */ public void ReceiveData(object sender, SerialDataReceivedEventArgs e) { // 接受數據時建議保留延時200毫秒,否則會存在由於接收不及時,一包數據被分成兩段返回的情況 System.Threading.Thread.Sleep(200); main.BeginInvoke((EventHandler)delegate { if (port.IsOpen) { int readLength = port.BytesToRead; byte[] buff = new byte[readLength]; port.Read(buff, 0, buff.Length); if (buff.Length != 0) { cmd.Delete(ByteToStr(new byte[] { buff[0] })); main.DealRes(buff); } } }); } }創建一個串口類,主要用於發送指令和接收返回的數據
3. 監測串口的插拔狀態:框架內置了方法可以監控串口的變化,只需要重寫該方法即可
protected override void WndProc(ref Message m) { try { // Windows消息編號 if (m.Msg == 0x219) { if ((bool)portButton1.Tag && !port1.IsOpen && (bool)portButton2.Tag && !port2.IsOpen) { PopError("串口1和串口2狀態有更新"); } else if ((bool)portButton1.Tag && !port1.IsOpen) { PopError("串口1狀態有更新"); } else if ((bool)portButton2.Tag && !port2.IsOpen) { PopError("串口2狀態有更新"); } } } catch { Util.PopError("監控串口狀態錯誤"); } base.WndProc(ref m); } 監控串口狀態監控串口狀態
4. 安裝NPOI組件實現Excel的讀寫功能:Excel的讀寫依賴三方件nuget。
安裝NPOI有兩種辦法:
第一種利用Visual Studio導航欄的“工具”->“NuGet包管理器”進行下載,這種比較簡單方便,下載後項目可以直接引用使用
第二種則是手動安裝,解決無法線上安裝的情況,比如網路受限等:
a. Nuget下載:可以從官方https://www.nuget.org/downloads進行下載,將下載的nuget.exe拷貝到某個目錄,同時在該目錄下打開命令視窗。
b. NPOI安裝:在目錄A打開命令視窗,執行命令nuget install NPOI -SolutionDirectory 項目根目錄 -PackageSaveMode nupkg,安裝後會生成一個packages文件
c. 還需要在項目根目錄下的.csproj目錄下手動添加引入文件,同時註意packages需要和安裝後的目錄對應,否則引用無效,安裝完成後返回VS工具會提示“全部刷新引用”,同意即可。
<Reference Include="BouncyCastle.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=072edcf4a5328938, processorArchitecture=MSIL"> <HintPath>.\packages\BouncyCastle.Cryptography.2.2.1\lib\net461\BouncyCastle.Cryptography.dll</HintPath> </Reference> <Reference Include="Enums.NET, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7ea1c1650d506225, processorArchitecture=MSIL"> <HintPath>.\packages\Enums.NET.4.0.1\lib\net45\Enums.NET.dll</HintPath> </Reference> <Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL"> <HintPath>.\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath> </Reference> <Reference Include="MathNet.Numerics, Version=4.15.0.0, Culture=neutral, PublicKeyToken=cd8b63ad3d691a37, processorArchitecture=MSIL"> <HintPath>.\packages\MathNet.Numerics.Signed.4.15.0\lib\net461\MathNet.Numerics.dll</HintPath> </Reference> <Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=2.3.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>.\packages\Microsoft.IO.RecyclableMemoryStream.2.3.2\lib\net462\Microsoft.IO.RecyclableMemoryStream.dll</HintPath> </Reference> <Reference Include="NPOI.Core, Version=2.6.2.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> <HintPath>.\packages\NPOI.2.6.2\lib\net472\NPOI.Core.dll</HintPath> </Reference> <Reference Include="NPOI.OOXML, Version=2.6.2.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> <HintPath>.\packages\NPOI.2.6.2\lib\net472\NPOI.OOXML.dll</HintPath> </Reference> <Reference Include="NPOI.OpenXml4Net, Version=2.6.2.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> <HintPath>.\packages\NPOI.2.6.2\lib\net472\NPOI.OpenXml4Net.dll</HintPath> </Reference> <Reference Include="NPOI.OpenXmlFormats, Version=2.6.2.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> <HintPath>.\packages\NPOI.2.6.2\lib\net472\NPOI.OpenXmlFormats.dll</HintPath> </Reference> <Reference Include="SixLabors.Fonts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d998eea7b14cab13, processorArchitecture=MSIL"> <HintPath>.\packages\SixLabors.Fonts.1.0.0\lib\netstandard2.0\SixLabors.Fonts.dll</HintPath> </Reference> <Reference Include="SixLabors.ImageSharp, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d998eea7b14cab13, processorArchitecture=MSIL"> <HintPath>.\packages\SixLabors.ImageSharp.2.1.4\lib\net472\SixLabors.ImageSharp.dll</HintPath> </Reference> <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Configuration" /> <Reference Include="System.Core" /> <Reference Include="System.DirectoryServices" /> <Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>.\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath> </Reference> <Reference Include="System.Numerics" /> <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>.\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> </Reference> <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>.\NPOISystem.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath> </Reference> <Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Security" /> <Reference Include="System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>.\packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll</HintPath> </Reference> <Reference Include="System.Security.Cryptography.Xml, Version=6.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>.\packages\System.Security.Cryptography.Xml.6.0.1\lib\net461\System.Security.Cryptography.Xml.dll</HintPath> </Reference> <Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>.\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath> </Reference> <Reference Include="System.Text.Encoding.CodePages, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>.\packages\System.Text.Encoding.CodePages.5.0.0\lib\net461\System.Text.Encoding.CodePages.dll</HintPath> </Reference>配置引用內容
d. 導出Excel和讀取Excel網上案列較多你再擴展。