C# WinForm實現畫筆簽名功能
需求
我的文章 《C# 結合JavaScript實現手寫板簽名并上傳到服務器》主要介紹了 web 版的需求實現,本文應項目需求介紹如何通過 C# WinForm 通過畫布畫筆實現手寫簽名,并在開發(fā)過程中解決遇到的一些格式轉換的問題,提供一些思路。
實現效果
簽名功能的顯示界面如下圖:
該效果主要實現如下功能:
1、提供畫布,設計畫筆類,實現畫筆簽名
2、點擊重簽按鈕清空畫布
3、點擊確認按鈕保存畫布位圖到指定的格式(提供三種保存類型,文件,二進制數據和BASE64編碼)
開發(fā)運行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
手寫觸屏設備:Microsoft Surface Pro 9
.net版本: .netFramework4.0 或以上
開發(fā)工具:VS2019 C#
設計實現
界面布局
主要在WinForm上放置如下控件,Name 為 canvasPanel 的 System.Windows.Forms.Panel控件,一些Label控件、radioButton控件和兩個功能按鈕Button控件,如下圖:
初始化
Form1 初始化如下變量:
bool isMouseDown = false; // 判斷鼠標或手指是否按下,按下為 true Graphics canvas = null; // 定義繪圖畫布 Image bmpData = null; // 定義 Image 圖像,將來導出時使用
實例化變量的過程中 new Bitmap ,則產生的默認格式為 System.Drawing.Imaging.ImageFormat.MemoryBmp 格式,這會產生一個問題,保存的位圖是全黑色。因此一個解決的思路是先臨時創(chuàng)建一個白色背景的JPEG圖片,圖片的大小取決于panel控件的寬度和高度,然后再將畫布的圖像 bmpData 變量,實例化創(chuàng)建引用這個臨時圖片的路徑。
示例代碼如下:
public partial class Form1 : Form { bool isMouseDown = false; Graphics canvas = null; Image bmpData = null; public Form1() { InitializeComponent(); canvas = canvasPanel.CreateGraphics(); string tmpJpg = Application.StartupPath + "\\tmpimg\\" + System.Guid.NewGuid().ToString() + ".jpg"; using (Bitmap bitmap = new Bitmap(canvasPanel.Width, canvasPanel.Height)) { using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.Clear(Color.White); } bitmap.Save(tmpJpg, ImageFormat.Jpeg); } bmpData = new Bitmap(tmpJpg); } }
畫筆繪圖
Graphics canvas 為canvasPanel控件創(chuàng)建的畫布,首先定義實現一個畫筆類,代碼如下:
public static class signPen { public static Point LastPoint { get; set; } public static Color Color { get; set; } public static int Width { get; set; } static signPen() { Color = Color.Black; Width = 2; } }
畫筆類主要包括 :
序號 | 屬性名 | 類型 | 說明 |
---|---|---|---|
1 | LastPoint | Point | 記錄最后一次畫筆的坐標點,并結合 DrawLine 方法畫出想要的線段 |
2 | Color | Color | 畫筆的顏色,默認為黑色 |
3 | Width | int | 畫筆的粗線,默認為2,1為最細 |
實現繪圖,主要是通過畫筆類,在canvasPanel 的鼠標按下、鼠標移動、和鼠標抬起事件定義相關操作。
序號 | 事件名 | 說明 |
---|---|---|
1 | canvasPanel_MouseDown | 記住鼠標是否按下,將 bool isMouseDown 置為true,另一個關鍵功能是將按下的點(Point),賦值到畫筆的 LastPoint 屬性,以備后續(xù)繪制線條使用 |
2 | CanvasPanel_MouseMove | 判斷 isMouseDown 標志,如果為 true 則引入畫布圖像,從最后一次的Point結合當前鼠標的Point 進行 DrawLine 操作,并形成新的位圖數據 |
3 | CanvasPanel_MouseUp | 將 bool isMouseDown 置為 false,不再進行繪制 |
示例代碼如下:
private void canvasPanel_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { isMouseDown = true; signPen.LastPoint = new Point(e.X, e.Y); } } private void CanvasPanel_MouseMove(object sender, MouseEventArgs e) { if (isMouseDown == true) { Graphics gf = Graphics.FromImage(bmpData); //設置高質量插值法 gf.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; //設置高質量,低速度呈現平滑程度 gf.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; Pen pen = new Pen(signPen.Color, signPen.Width); Point curPoint = new Point(e.X, e.Y); gf.DrawLine(pen, signPen.LastPoint, curPoint); signPen.LastPoint = curPoint; canvas.DrawImage(bmpData, 0,0); } } private void CanvasPanel_MouseUp(object sender, MouseEventArgs e) { isMouseDown = false; }
清空畫布
可通過點擊“重簽” 按鈕,清空畫布,實現如初始化功能,代碼如下:
string tmpJpg = Application.StartupPath + "\\tmpimg\\" + System.Guid.NewGuid().ToString() + ".jpg"; using (Bitmap bitmap = new Bitmap(canvasPanel.Width, canvasPanel.Height)) { using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.Clear(Color.White); } bitmap.Save(tmpJpg, ImageFormat.Jpeg); } bmpData = new Bitmap(tmpJpg); canvas.DrawImage(bmpData, 0,0);
導出位圖數據
繪制完成,我們就需要將 bmpData 位圖變量數據導出我們想要的格式,為了便于演示,我們設置了一組 radioButton 選項,可以導出三種類型的形式數據,如下表:
序號 | 事件名 | 說明 |
---|---|---|
1 | radioButton1 | 直接導出成文件(jpeg類型) |
2 | radioButton2 | 導出二進制數據 (byte[]) |
3 | radioButton3 | 導出 base64 數據 (string類型) |
假設“確定”按鈕 Name 為 “Button13”,并假設輸出到D盤根目錄下,示例代碼如下:
private void Button13_Click(object sender, EventArgs e) { string jpgFilename = "d:\\" + System.Guid.NewGuid().ToString() + ".jpg"; bmpData.Save(jpgFilename,ImageFormat.Jpeg); if (File.Exists(jpgFilename) == false) { MessageBox.Show(string.Format("保存文件至{0}失敗。", jpgFilename)); return; } if (radioButton1.Checked == true) { MessageBox.Show(string.Format("已成功保存至{0}。", jpgFilename)); } if (radioButton2.Checked == true) { byte[] bytes2=fe.GetBinaryData(jpgFilename); MessageBox.Show(string.Format("已成功保存為二進制數據,長度{0}。", bytes2.Length)); } if (radioButton3.Checked == true) { string base64str = ImgToBase64String(jpgFilename, false); MessageBox.Show(string.Format("已成功保存為BASE64,長度{0}。", base64str.Length)); } } public byte[] GetBinaryData(string filename) { if(!File.Exists(filename)) { return null; } try { FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); byte[] imageData = new Byte[fs.Length]; fs.Read( imageData, 0,Convert.ToInt32(fs.Length)); fs.Close(); return imageData; } catch(Exception) { return null; } finally { } } public string ImgToBase64String(string Imagefilename, bool outFullString = false) { try { System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(Imagefilename); MemoryStream ms = new MemoryStream(); // bmp.Save(ms,ImageFormat.Jpeg) System.Drawing.Imaging.ImageFormat iformat = System.Drawing.Imaging.ImageFormat.Jpeg; string extension = System.IO.Path.GetExtension(Imagefilename).Replace(".", "").ToLower(); if (extension == "bmp") { iformat = System.Drawing.Imaging.ImageFormat.Bmp; } else if (extension == "emf") { iformat = System.Drawing.Imaging.ImageFormat.Emf; } else if (extension == "exif") { iformat = System.Drawing.Imaging.ImageFormat.Exif; } else if (extension == "gif") { iformat = System.Drawing.Imaging.ImageFormat.Gif; } else if (extension == "icon") { iformat = System.Drawing.Imaging.ImageFormat.Icon; } else if (extension == "png") { iformat = System.Drawing.Imaging.ImageFormat.Png; } else if (extension == "tiff") { iformat = System.Drawing.Imaging.ImageFormat.Tiff; } else if (extension == "wmf") { iformat = System.Drawing.Imaging.ImageFormat.Wmf; } bmp.Save(ms, iformat); byte[] arr = new byte[ms.Length]; ms.Position = 0; ms.Read(arr, 0, (int)ms.Length); ms.Close(); bmp.Dispose(); string rv = Convert.ToBase64String(arr); if (outFullString == true) { rv = "data:image/" + extension + ";base64," + rv; } return rv; } catch (Exception ex) { return null; } }
小結
對于 new Bitmap 創(chuàng)建的位圖,我們還可以使用 Png 格式,以防止“黑圖”的出現,我們在應用中可以靈活掌握,如下代碼:
Bitmap newimg = new Bitmap(100,100); newimg.Save("d:\\test.jpg", System.Drawing.Imaging.ImageFormat.Png);
保存的數據,顯示在畫布上可采取如下方法:
1、文件型
System.Drawing.Image img2 = new Bitmap(你的文件地址); canvas.DrawImage(img2, 0, 0); MessageBox.Show("顯示文件到畫布成功!");
2、二進制型
byte[] bytes = 你的二進制數據; MemoryStream ms = new MemoryStream(bytes); System.Drawing.Image img = System.Drawing.Image.FromStream(ms); canvas.DrawImage(img, 0, 0); MessageBox.Show("顯示二進制到畫布成功!");
3、base64型
string base64 = 你的base64數據; byte[] arr = Convert.FromBase64String(base64); MemoryStream ms2 = new MemoryStream(arr); System.Drawing.Image img2 = System.Drawing.Image.FromStream(ms2); canvas.DrawImage(img2, 0, 0); MessageBox.Show("顯示base64到畫布成功!");
以上就是C# WinForm實現畫筆簽名功能的詳細內容,更多關于C#畫筆簽名的資料請關注腳本之家其它相關文章!
相關文章
C#使用DateTime.Now靜態(tài)屬性動態(tài)獲得系統(tǒng)當前日期和時間
本文主要介紹了C#使用DateTime.Now靜態(tài)屬性動態(tài)獲得系統(tǒng)當前日期和時間,DateTime結構的Now靜態(tài)屬性只是得到一個系統(tǒng)時間對象,該時間對象不會隨著系統(tǒng)時間的變化而變化,如果要動態(tài)顯示系統(tǒng)時間,可以使用計時器間隔地獲取系統(tǒng)時間對象并顯示,感興趣的可以了解一下2024-01-01