开发者

C# WinForm实现画笔签名功能

目录
  • 需求
  • 实现效果
  • 开发运行环境
  • 设计实现
    • 界面布局
    • 初始化
    • 画笔绘图
    • 清空画布
    • 导出位图数据
  • 小结

    需求

    我的文章 《C# 结合JavaScript实现手写板签名并上传到服务器》主要介绍了 web 版的需求实现,本文应项目需求介绍如何通过 C# WinForm 通过画布画笔实现手写签名,并在开发过程中解决遇到的一些格式转换的问题,提供一些思路。

    实现效果

    签名功能的显示界面如下图:

    C# WinForm实现画笔签名功能

    该效果主要实现如下功能:

    1、提供画布,设计画笔类,实现画笔签名

    2、点击重签按钮清空画布

    3、点击确认按钮保存画布位图到指定的格式(提供三种保存类型,文件,二进制数据和BASE64编码)

    开发运行环境

    操作系统: Windows Server 2019 DataCenter

    手写触屏设备:Microsoft Surface Pro 9

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

    开发工具:VS2019  C#

    设计实现

    界面布局

    主要在WinForm上放置如下控件,Name 为 canvASPanel 的 System.Windows.Forms.Panel控件,一些Label控件、radioButton控件和两个功能按钮Button控件,如下图:

    C# WinForm实现画笔签名功能

    初始化

    Form1 初始化如下变量: 

          bool isMouseDown = false;      // 判断鼠标或手指是否按下,按下为 true
          Graphics canvas = null;    // 定义绘图画布
          Image bmpData = null;     // 定义 Image 图像,将来导出时使用

    实例化变量的过程中 new Bitmap ,则产生的默认格式为 System.Drawing.Imaging.ImageFormat.MemoryBmp 格式,这会产生一个问题,保存的位图是全黑色。因此一个解决的思路是先临时创建一个白色背景的JPEG图片,图片的大小取决于panel控件的宽度和高度,然后再将画布的图像 bmpData 变量,实例化创建引用这个临时图片的路径。

    示例代码如下:

    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控件创建的画布,首先定义实现一个画笔类,代码如下:

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

    画笔类主要包括 :

    序号属性名类型说明
    1LastPointPoint记录最后一次画笔的坐标点,并结合 DrawLine 方法画出想要的线段
    2ColorColor画笔的颜色,默认为黑色
    3Widthint画笔的粗线,默认为2,1为最细

    实现绘图,主要是通过画笔类,在canvasPanel 的鼠标按下、鼠标移动、和鼠标抬起事件定义相关操作。

    序号事件名说明
    1canvasPanel_MouseDown记住鼠标是否按下,将 bool isMouseDown 置为true,另一个关键功能是将按下的点(Point),赋值到画笔的 LastPoint 属性,以备后续绘制线条使用
    2CanvasPanel_MouseMove判断 isMouseDown 标志,如果为 true 则引入画布图像,从最后一次的Point结合当前鼠标的Point 进行 DrawLine 操作,并形成新的位图数据
    3CanvasPanel_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, ImageFojavascriptrmat.Jpeg);
                }
     
                bmpData = new Bitmap(tmpJpg);
               编程 canvas.DrawImage(bmpData, 0,0);
    

    导出位图数据

    绘制完成,我们就需要将 bmpData  位图变量数据导出我们想要的格式,为了便于演示,我们设置了一组 radioButton 选项,可以导出三种类型的形式数据,如下表:

    序号事件名说明
    1radioButton1直接导出成文件(jpeg类型)
    2radioButton2导出二进制数据 (byte[])
    3radioButton3导出 base64 数据 (string类型)

    假设“确定”按钮 Name 为 “Button13”,并假设输出到D盘根目录下,示例代码如下:

            private void Button13_Click(object sendeandroidr, 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
                {
                    
             www.devze.com   }
            }        
     
            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;
                    }
               android     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 创建的位图,我们还可以使用 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#画笔签名的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜