最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# WinForm實(shí)現(xiàn)畫(huà)筆簽名功能

 更新時(shí)間:2024年11月19日 16:16:35   作者:初九之潛龍勿用  
這篇文章主要為大家詳細(xì)介紹了如何通過(guò) C# WinForm 通過(guò)畫(huà)布畫(huà)筆實(shí)現(xiàn)手寫(xiě)簽名,并在開(kāi)發(fā)過(guò)程中解決遇到的一些格式轉(zhuǎn)換的問(wèn)題簽名功能,希望對(duì)大家有所幫助

需求

我的文章 《C# 結(jié)合JavaScript實(shí)現(xiàn)手寫(xiě)板簽名并上傳到服務(wù)器》主要介紹了 web 版的需求實(shí)現(xiàn),本文應(yīng)項(xiàng)目需求介紹如何通過(guò) C# WinForm 通過(guò)畫(huà)布畫(huà)筆實(shí)現(xiàn)手寫(xiě)簽名,并在開(kāi)發(fā)過(guò)程中解決遇到的一些格式轉(zhuǎn)換的問(wèn)題,提供一些思路。

實(shí)現(xiàn)效果

簽名功能的顯示界面如下圖:

該效果主要實(shí)現(xiàn)如下功能:

1、提供畫(huà)布,設(shè)計(jì)畫(huà)筆類(lèi),實(shí)現(xiàn)畫(huà)筆簽名

2、點(diǎn)擊重簽按鈕清空畫(huà)布

3、點(diǎn)擊確認(rèn)按鈕保存畫(huà)布位圖到指定的格式(提供三種保存類(lèi)型,文件,二進(jìn)制數(shù)據(jù)和BASE64編碼)

開(kāi)發(fā)運(yùn)行環(huán)境

操作系統(tǒng): Windows Server 2019 DataCenter

手寫(xiě)觸屏設(shè)備:Microsoft Surface Pro 9

.net版本: .netFramework4.0 或以上

開(kāi)發(fā)工具:VS2019  C#

設(shè)計(jì)實(shí)現(xiàn)

界面布局

主要在WinForm上放置如下控件,Name 為 canvasPanel 的 System.Windows.Forms.Panel控件,一些Label控件、radioButton控件和兩個(gè)功能按鈕Button控件,如下圖:

初始化

Form1 初始化如下變量: 

      bool isMouseDown = false;      // 判斷鼠標(biāo)或手指是否按下,按下為 true
      Graphics canvas = null;    // 定義繪圖畫(huà)布
      Image bmpData = null;     // 定義 Image 圖像,將來(lái)導(dǎo)出時(shí)使用

實(shí)例化變量的過(guò)程中 new Bitmap ,則產(chǎn)生的默認(rèn)格式為 System.Drawing.Imaging.ImageFormat.MemoryBmp 格式,這會(huì)產(chǎn)生一個(gè)問(wèn)題,保存的位圖是全黑色。因此一個(gè)解決的思路是先臨時(shí)創(chuàng)建一個(gè)白色背景的JPEG圖片,圖片的大小取決于panel控件的寬度和高度,然后再將畫(huà)布的圖像 bmpData 變量,實(shí)例化創(chuàng)建引用這個(gè)臨時(shí)圖片的路徑。

示例代碼如下:

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);
            
            
            
        }
 
 
}

畫(huà)筆繪圖

Graphics canvas 為canvasPanel控件創(chuàng)建的畫(huà)布,首先定義實(shí)現(xiàn)一個(gè)畫(huà)筆類(lèi),代碼如下:

        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;
            }
        }

畫(huà)筆類(lèi)主要包括 :

序號(hào)屬性名類(lèi)型說(shuō)明
1LastPointPoint記錄最后一次畫(huà)筆的坐標(biāo)點(diǎn),并結(jié)合 DrawLine 方法畫(huà)出想要的線段
2ColorColor畫(huà)筆的顏色,默認(rèn)為黑色
3Widthint畫(huà)筆的粗線,默認(rèn)為2,1為最細(xì)

實(shí)現(xiàn)繪圖,主要是通過(guò)畫(huà)筆類(lèi),在canvasPanel 的鼠標(biāo)按下、鼠標(biāo)移動(dòng)、和鼠標(biāo)抬起事件定義相關(guān)操作。

序號(hào)事件名說(shuō)明
1canvasPanel_MouseDown記住鼠標(biāo)是否按下,將 bool isMouseDown 置為true,另一個(gè)關(guān)鍵功能是將按下的點(diǎn)(Point),賦值到畫(huà)筆的 LastPoint 屬性,以備后續(xù)繪制線條使用
2CanvasPanel_MouseMove判斷 isMouseDown 標(biāo)志,如果為 true 則引入畫(huà)布圖像,從最后一次的Point結(jié)合當(dāng)前鼠標(biāo)的Point 進(jìn)行 DrawLine 操作,并形成新的位圖數(shù)據(jù)
3CanvasPanel_MouseUp將 bool isMouseDown 置為 false,不再進(jìn)行繪制

示例代碼如下:

        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);
           
            //設(shè)置高質(zhì)量插值法
            gf.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            //設(shè)置高質(zhì)量,低速度呈現(xiàn)平滑程度 
            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;
        }

清空畫(huà)布

可通過(guò)點(diǎn)擊“重簽” 按鈕,清空畫(huà)布,實(shí)現(xiàn)如初始化功能,代碼如下:

            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);

導(dǎo)出位圖數(shù)據(jù)

繪制完成,我們就需要將 bmpData  位圖變量數(shù)據(jù)導(dǎo)出我們想要的格式,為了便于演示,我們?cè)O(shè)置了一組 radioButton 選項(xiàng),可以導(dǎo)出三種類(lèi)型的形式數(shù)據(jù),如下表:

序號(hào)事件名說(shuō)明
1radioButton1直接導(dǎo)出成文件(jpeg類(lèi)型)
2radioButton2導(dǎo)出二進(jìn)制數(shù)據(jù) (byte[])
3radioButton3導(dǎo)出 base64 數(shù)據(jù) (string類(lèi)型)

假設(shè)“確定”按鈕 Name 為 “Button13”,并假設(shè)輸出到D盤(pán)根目錄下,示例代碼如下:

        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("已成功保存為二進(jìn)制數(shù)據(jù),長(zhǎng)度{0}。", bytes2.Length));
            }
            if (radioButton3.Checked == true)
            {
                string base64str = ImgToBase64String(jpgFilename, false);
                MessageBox.Show(string.Format("已成功保存為BASE64,長(zhǎng)度{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;
            }
        }

小結(jié)

對(duì)于 new Bitmap 創(chuàng)建的位圖,我們還可以使用 Png 格式,以防止“黑圖”的出現(xiàn),我們?cè)趹?yīng)用中可以靈活掌握,如下代碼:

    Bitmap newimg = new Bitmap(100,100);
    newimg.Save("d:\\test.jpg", System.Drawing.Imaging.ImageFormat.Png);

保存的數(shù)據(jù),顯示在畫(huà)布上可采取如下方法:

1、文件型

            System.Drawing.Image img2 = new Bitmap(你的文件地址);
 
                canvas.DrawImage(img2, 0, 0);
                MessageBox.Show("顯示文件到畫(huà)布成功!");

2、二進(jìn)制型

                byte[] bytes = 你的二進(jìn)制數(shù)據(jù);
                MemoryStream ms = new MemoryStream(bytes);
                System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
                canvas.DrawImage(img, 0, 0);
                MessageBox.Show("顯示二進(jìn)制到畫(huà)布成功!");

3、base64型

string base64 = 你的base64數(shù)據(jù);
                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到畫(huà)布成功!");

以上就是C# WinForm實(shí)現(xiàn)畫(huà)筆簽名功能的詳細(xì)內(nèi)容,更多關(guān)于C#畫(huà)筆簽名的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Unity的OnOpenAsset實(shí)用案例深入解析

    Unity的OnOpenAsset實(shí)用案例深入解析

    這篇文章主要為大家介紹了Unity的OnOpenAsset實(shí)用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • C#通過(guò)WIN32 API實(shí)現(xiàn)嵌入程序窗體

    C#通過(guò)WIN32 API實(shí)現(xiàn)嵌入程序窗體

    這篇文章主要介紹了C#通過(guò)WIN32 API實(shí)現(xiàn)嵌入程序窗體的方法,涉及WIN32 API的調(diào)用及窗體的設(shè)計(jì),具有很好的借鑒價(jià)值,需要的朋友可以參考下
    2014-09-09
  • Unity?UGUI?按鈕綁定事件的?4?種方式匯總

    Unity?UGUI?按鈕綁定事件的?4?種方式匯總

    UGUI?可視化創(chuàng)建以及關(guān)聯(lián)事件很方便,?動(dòng)態(tài)創(chuàng)建可以利用創(chuàng)建好的?Prefab?進(jìn)行實(shí)例化,?只是在關(guān)聯(lián)事件上有些復(fù)雜,這篇文章主要介紹了Unity?UGUI?按鈕綁定事件的?4?種方式,需要的朋友可以參考下
    2022-01-01
  • 在C#項(xiàng)目中調(diào)用C++編寫(xiě)的動(dòng)態(tài)庫(kù)的三種方式

    在C#項(xiàng)目中調(diào)用C++編寫(xiě)的動(dòng)態(tài)庫(kù)的三種方式

    這篇文章給大家介紹了三種方式詳解如何在C#項(xiàng)目中調(diào)用C++編寫(xiě)的動(dòng)態(tài)庫(kù),文中通過(guò)代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-01-01
  • c#實(shí)現(xiàn)pdf的另存為功能

    c#實(shí)現(xiàn)pdf的另存為功能

    今天跟大家分享一個(gè)實(shí)現(xiàn)PDF另存為的效果,是調(diào)用Acrobat SDK的JavaScript實(shí)現(xiàn)的,需要的朋友可以參考下
    2014-03-03
  • C#采用mouse_event函數(shù)實(shí)現(xiàn)模擬鼠標(biāo)功能

    C#采用mouse_event函數(shù)實(shí)現(xiàn)模擬鼠標(biāo)功能

    這篇文章主要介紹了C#模擬鼠標(biāo)點(diǎn)擊小功能,通過(guò)代碼向大家做分析,需要的朋友可以參考下
    2015-07-07
  • c#使用微信接口開(kāi)發(fā)微信門(mén)戶應(yīng)用

    c#使用微信接口開(kāi)發(fā)微信門(mén)戶應(yīng)用

    本系列文章希望從一個(gè)循序漸進(jìn)的角度上,全面介紹微信的相關(guān)開(kāi)發(fā)過(guò)程和相關(guān)經(jīng)驗(yàn)總結(jié),希望給大家了解一下相關(guān)的開(kāi)發(fā)歷程。
    2014-03-03
  • modbus rtu通訊發(fā)送數(shù)據(jù)優(yōu)化方式

    modbus rtu通訊發(fā)送數(shù)據(jù)優(yōu)化方式

    使用NModbus4庫(kù)發(fā)送數(shù)據(jù)時(shí)出現(xiàn)IO操作中止,可能因串口參數(shù)不一致、RS485收發(fā)切換未正確配置或超時(shí)設(shè)置不當(dāng)導(dǎo)致,建議檢查通信參數(shù)一致性、添加收發(fā)控制代碼并適當(dāng)調(diào)整超時(shí)時(shí)間以解決沖突
    2025-07-07
  • C#利用Refit實(shí)現(xiàn)JWT自動(dòng)續(xù)期詳解

    C#利用Refit實(shí)現(xiàn)JWT自動(dòng)續(xù)期詳解

    Refit?是一個(gè)受到Square的Retrofit庫(kù)(Java)啟發(fā)的自動(dòng)類(lèi)型安全REST庫(kù),這篇文章主要為大家介紹了C#如何利用Refit實(shí)現(xiàn)JWT自動(dòng)續(xù)期,感興趣的可以了解下
    2023-08-08
  • C#編寫(xiě)DES加密、解密類(lèi)

    C#編寫(xiě)DES加密、解密類(lèi)

    本文給大家匯總了一下使用C#實(shí)現(xiàn)的DES加密、解密類(lèi)的代碼,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下
    2015-05-05

最新評(píng)論

台前县| 株洲县| 清新县| 安宁市| 嘉峪关市| 南通市| 嘉义市| 苏尼特右旗| 石门县| 青川县| 东平县| 惠州市| 仁寿县| 利辛县| 天津市| 关岭| 正阳县| 棋牌| 德惠市| 措美县| 龙陵县| 延吉市| 海安县| 准格尔旗| 教育| 苏州市| 桐柏县| 阿坝| 佳木斯市| 荥阳市| 开封市| 马关县| 浙江省| 阳高县| 体育| 当雄县| 安乡县| 防城港市| 安平县| 麟游县| 嘉黎县|