截图工具——涂鸦

具有椭圆、矩形、箭头、画笔、文字涂鸦功能的截图工具,效果如图:
这里写图片描述
思路:
用泛型集合存储涂鸦的数据,每一次涂鸦后都存储进去,最后在OnPaint中遍历该集合,通过GDI绘出。

重点讲涂鸦部分:
1、椭圆、矩形、箭头,都只需确定起点和终点。
2、画笔需要确定点集合。
3、文字涂鸦通过透明Richtextbox写上内容后将该控件转成一个bitmap。

实现方法:
涂鸦通过GDI画图实现:

 private void DrawTools(Graphics g, DrawToolData data)
 {          
    Point beginPoint = data.beginPoint;
    Point endPoint = data.endPoint;
    ColorToolChose();
    Rectangle rect = GetToolRect(beginPoint, endPoint);
    Pen pen = new Pen(data.penColor, data.penWidth);
    g.SmoothingMode = SmoothingMode.AntiAlias;
    switch (data.Type)
    {
       case 1://椭圆
           using (pen)
           {
              g.DrawEllipse(pen, rect);
           }
           break;
       case 2://矩形
           using (pen)
           {
              g.DrawRectangle(pen, rect);
           }
           break;
       case 3://箭头
           using (pen)
           {
             pen.EndCap = LineCap.ArrowAnchor;
                        pen.EndCap = LineCap.Custom;
                        pen.CustomEndCap = new AdjustableArrowCap(4, 4, true);
             g.DrawLine(pen, beginPoint, endPoint);
           }
           break;
       case 4://画笔
           if (data.pointList.Count < 2) return;
                    Point[] points = data.pointList.ToArray();
           using (pen)
           {
              g.DrawLines(new Pen(data.penColor, data.penWidth), points);

           }
           break;
       case 5://文字                   
           if (data.textBmp.Width < 2) return;
           g.DrawImage(data.textBmp, data.beginPoint);
           break;
           }
        }

写一个类用来存储涂鸦数据,然后用“List<>” 把每一次涂鸦的数据存起来。

//存储画笔工具 所有线段的 点集合、画笔颜色宽度的类 的集合
private List<DrawToolData> drawData = new List<DrawToolData>(); 

    /// <summary>
    /// 存储画图信息
    /// </summary>
public class DrawToolData
    {
        public int Type { get; set; } = 0;
        /// <summary>
        /// 画笔工具线段点集合
        /// </summary>
        public List<Point> pointList { get; set; } = new List<Point>();
        public Color penColor { get; set; }

        public int penWidth { get; set; }

        public Point beginPoint { get; set; } = Point.Empty;

        public Point endPoint { get; set; } = Point.Empty;

        public float textSize { get; set; } = 16;
        //存文字分割后的字符串数组
        public string textInfo { get; set; }

        public Bitmap textBmp { get; set; } = new Bitmap(1, 1);
    }

每次画完一个图形后都调用存储数据的方法,存储到数据集合的末尾。

 private void addDrawData()
        {
            if (drawData.Count == 0) drawData.Add(new DrawToolData());
            drawData[drawData.Count - 1].Type = clickType;
            drawData[drawData.Count - 1].penColor = selectedColor;
            drawData[drawData.Count - 1].penWidth = penWidth;
            switch (clickType)
            {
                case 1:
                case 2:
                case 3:
                    drawData[drawData.Count - 1].beginPoint = BeginPoint;
                    drawData[drawData.Count - 1].endPoint = EndPoint;
                    break;
                case 4:
                    (drawData[drawData.Count - 1].pointList).Add(EndPoint);
                    break;
                case 5:
                    drawData[drawData.Count - 1].beginPoint = BeginPoint;
                    drawData[drawData.Count - 1].textSize = colorWithText1.textSize;
                    drawData[drawData.Count - 1].textInfo = drawTextTool1.Text;
                    drawData[drawData.Count - 1].textBmp = GetTextBmp();
                    break;
            }

最后在OnPaint中遍历数据画出图形。

foreach (DrawToolData data in drawData)
                    {
                        DrawTools(g, data);
                    }

文字涂鸦:做一个透明的RichtextBox控件:

 public class DrawTextTool:RichTextBox
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr LoadLibrary(string lpFileName);
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams prams = base.CreateParams;
                if (LoadLibrary("msftedit.dll") != IntPtr.Zero)
                {
                    prams.ExStyle |= 0x020; // transparent   
                    prams.ClassName = "RICHEDIT50W";
                    this.BorderStyle = BorderStyle.None;               
                }
                return prams;
            }
        }


    }

然后用“gdi32.dll”得到该控件的bitmap。

 private const Int32 SRCCOPY = 0xCC0020;

        [DllImport("gdi32.dll")]
        internal static extern bool BitBlt(
            IntPtr hdcDest, // handle to destination DC
            int nXDest, // x-coord of destination upper-left corner
            int nYDest, // y-coord of destination upper-left corner
            int nWidth, // width of destination rectangle
            int nHeight, // height of destination rectangle
            IntPtr hdcSrc, // handle to source DC
            int nXSrc, // x-coordinate of source upper-left corner
            int nYSrc, // y-coordinate of source upper-left corner
            Int32 dwRop // raster operation code
            );


        public static Bitmap GetImageOfControl(Control control)
        {

            var w = control.Size.Width;
            var h = control.Size.Height;

            Graphics gOfCtrl = control.CreateGraphics();
            var bmp = new Bitmap(w, h, gOfCtrl);

            Graphics gOfBmp = Graphics.FromImage(bmp);

            IntPtr dc1 = gOfCtrl.GetHdc();
            IntPtr dc2 = gOfBmp.GetHdc();

            BitBlt(dc2, 0, 0, w, h, dc1, 0, 0, SRCCOPY);

            gOfCtrl.ReleaseHdc(dc1);
            gOfBmp.ReleaseHdc(dc2);

            gOfCtrl.Dispose();
            gOfBmp.Dispose();


            return bmp;
        }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值