实现原理基本截图的功能主要靠响应主窗体的鼠标按下、鼠标移动、鼠标抬起几个事件的功能来实现的。截取的图片区域使用“label”组件来显示,需要重新实现“label”组件的“paint”方法。
左键单击开始截图,右键单击取消截图,双击鼠标左键完成截图,将截取的图片保存到windows剪贴板中。
添加“label”组件工具箱》公共组件》双击“label”组件,修改组件属性:
name=lbl_cutimage,
autosize=false,
backcolor=transparent,
text = “”
“form1_load”事件添加代码:
this.lbl_cutimage.hide();
定义截图功能依赖的基本变量        #region 截图基本变量
        /// <summary>
        /// 用于判断是否已经开始截图,控制信息框是否显示。
        /// </summary>
        private bool iscuting;
        /// <summary>
        /// 鼠标按下的点
        /// </summary>
        private point beginpoint;
        /// <summary>
        /// 最终确定的绘图基点
        /// </summary>
        private point endpoint;
        /// <summary>
        /// 用于记录截图显示区域的大小(包括调整块的区域,调整区域边框宽度2px)
        /// </summary>
        private rectangle cutimagerect = new rectangle(0, 0, 5, 5);
        #endregion
定义枚举类型:更新ui的模式        /// <summary>
        /// 更新ui的模式,用于标记哪些需要显示,哪些需要隐藏;
        /// </summary>
        [flagsattribute]
        public enum updateuimode : uint
        {
            //值得注意的是,如果要使用组合值,那么就不能用连接的数字表示,必须是几何级增长!
            none = 0,
            showtextpro = 1,
            showpenstyle = 2,
            showtoolbox = 4,
            showinfobox = 8,
            showzoombox = 16,
            showcutimage = 32,
            hidetextpro = 64,
            hidepenstyle = 128,
            hidetoolbox = 256,
            hideinfobox = 512
        }
添加方法:计算并保存截图的区域框的大小        /// <summary>
        /// 计算并保存截图的区域框的大小
        /// </summary>
        private void savecutimagesize(point beginpoint, point endpoint)
        {
            // 保存最终的绘图基点,用于截取选中的区域
            this.endpoint = beginpoint;
            // 计算截取图片的大小
            int imgwidth = math.abs(endpoint.x - beginpoint.x) + 1;
            int imgheight = math.abs(endpoint.y - beginpoint.y) + 1;
            int lblwidth = imgwidth + 4;
            int lblheight = imgheight + 4;
            // 设置截图区域的位置和大小
            this.cutimagerect = new rectangle(beginpoint.x - 2, beginpoint.y - 2, lblwidth, lblheight);
        }
添加方法:执行截图,将选定区域的图片保存到剪贴板        /// <summary>
        /// 执行截图,将选定区域的图片保存到剪贴板
        /// </summary>
        /// <param name="savetodisk">
        /// 是否将图片保存到磁盘
        /// </param>
        private void execcutimage(bool savetodisk, bool uploadimage) //bool savetodisk = false, bool uploadimage = false
        {
            // 如果图片获取区域不可见,则退出保存图片过程
            if (!this.lbl_cutimage.visible) { return; }
            rectangle srcrect = new rectangle();
            srcrect.x = this.lbl_cutimage.location.x + 2;
            srcrect.y = this.lbl_cutimage.location.y + 2;
            srcrect.width = this.lbl_cutimage.width - 4;
            srcrect.height = this.lbl_cutimage.height - 4;
            rectangle destrect = new rectangle(0, 0, srcrect.width, srcrect.height);
            bitmap bmp = new bitmap(srcrect.width, srcrect.height);
            graphics g = graphics.fromimage(bmp);
            g.drawimage(this.screenimage, destrect, srcrect, graphicsunit.pixel);
            clipboard.setimage(bmp);
            exitcutimage(true);
        }
添加方法:退出截图过程       /// <summary>
        /// 退出截图过程
        /// </summary>
        private void exitcutimage(bool hidewindow) //  = true
        {
            this.lbl_cutimage.visible = false;
            this.iscuting = false;
            if (hidewindow)
            {
                this.screenimage.dispose();
                this.hide();
            }
        }
主窗口鼠标按下事件处理程序        /// <summary>
        /// 截图窗口鼠标按下事件处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void form1_mousedown(object sender, mouseeventargs e)
        {
            // 左键单击事件
            if (e.button == mousebuttons.left && e.clicks == 1)
            {
                if (!this.lbl_cutimage.visible)
                {
                    this.iscuting = true;
                    this.beginpoint = e.location;
                    this.endpoint = e.location;
                    savecutimagesize(e.location, e.location);
                    updatecutinfolabel(updateuimode.showcutimage | updateuimode.showinfobox);
                }
            }
            // 左键双击事件
            if (e.button == mousebuttons.left && e.clicks == 2)
            {
                if (this.lbl_cutimage.visible)
                {
                    execcutimage(false, false);
                }
            }
            // 右键单击事件
            if (e.button == mousebuttons.right)
            {
                exitcutimage(!this.lbl_cutimage.visible);
            }
        }
主窗口鼠标移动事件处理程序        /// <summary>
        /// 截图窗口鼠标移动事件处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void form1_mousemove(object sender, mouseeventargs e)
        {
            // 如果截取区域不可见,则退出处理过程
            if (!this.lbl_cutimage.visible)
            {
                updatecutinfolabel(updateuimode.none);
                return;
            }
            point pntbgn = this.beginpoint;
            point pntend = e.location;
            // 如果是反向拖动,重新设置起始点
            if (e.location.x < this.beginpoint.x && e.location.y < this.beginpoint.y)
            {
                pntbgn = e.location;
                pntend = this.beginpoint;
            }
            else
            {
                if (e.location.x < this.beginpoint.x)
                {
                    pntbgn = new point(e.location.x, this.beginpoint.y);
                    pntend = new point(this.beginpoint.x, e.location.y);
                }
                else
                {
                    if (e.location.y < this.beginpoint.y)
                    {
                        pntbgn = new point(this.beginpoint.x, e.location.y);
                        pntend = new point(e.location.x, this.beginpoint.y);
                    }
                }
            }
            if (this.iscuting)
            {
                savecutimagesize(pntbgn, pntend);
            }
            updatecutinfolabel(updateuimode.none);
        }
主窗口鼠标抬起事件处理程序        /// <summary>
        /// 截图窗口鼠标抬起事件处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void form1_mouseup(object sender, mouseeventargs e)
        {
            if (e.button == mousebuttons.left)
            {
                if (this.iscuting)
                {
                    this.iscuting = false;
                    updatecutinfolabel(updateuimode.none);
                }
            }
        }
截取区域图片绘制        /// <summary>
        /// 截取区域图片的绘制事件处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbl_cutimage_paint(object sender, painteventargs e)
        {
            int imgwidth = this.lbl_cutimage.width - 4;
            int imgheight = this.lbl_cutimage.height - 4;
            if (imgwidth < 1) { imgwidth = 1; }
            if (imgheight < 1) { imgheight = 1; }
            // 创建缓存图像,先将要绘制的内容全部绘制到缓存中,最后再一次性绘制到 label 上,
            // 这样可以提高性能,并且可以防止屏幕闪烁的问题
            bitmap bmp_lbl = new bitmap(this.lbl_cutimage.width, this.lbl_cutimage.height);
            graphics g = graphics.fromimage(bmp_lbl);
            // 将要截取的部分绘制到缓存
            rectangle destrect = new rectangle(2, 2, imgwidth, imgheight);
            point srcpoint = this.lbl_cutimage.location;
            srcpoint.offset(2, 2);
            rectangle srcrect = new rectangle(srcpoint, new system.drawing.size(imgwidth, imgheight));
            g.drawimage(this.screenimage, destrect, srcrect, graphicsunit.pixel);
            solidbrush brush = new solidbrush(color.fromargb(10, 124, 202));
            pen pen = new pen(brush, 1.0f);
            //以下部分(边框和调整块)的绘制放在(编辑内容)的后面,是解决绘制编辑内容会覆盖(边框和调整块)的问题
            // 绘制边框外的区域,解决会被编辑内容覆盖的问题
            // 上边
            destrect = new rectangle(0, 0, this.lbl_cutimage.width, 2);
            srcpoint = this.lbl_cutimage.location;
            //srcpoint.offset(2, 2);
            srcrect = new rectangle(srcpoint, new system.drawing.size(this.lbl_cutimage.width, 2));
            g.drawimage(this.backgroundimage, destrect, srcrect, graphicsunit.pixel);
            // 下边
            destrect = new rectangle(0, this.lbl_cutimage.height - 2, this.lbl_cutimage.width, 2);
            srcpoint = this.lbl_cutimage.location;
            srcpoint.offset(0, this.lbl_cutimage.height - 2);
            srcrect = new rectangle(srcpoint, new system.drawing.size(this.lbl_cutimage.width, 2));
            g.drawimage(this.backgroundimage, destrect, srcrect, graphicsunit.pixel);
            // 左边
            destrect = new rectangle(0, 2, 2, this.lbl_cutimage.height - 4);
            srcpoint = this.lbl_cutimage.location;
            srcpoint.offset(0, 2);
            srcrect = new rectangle(srcpoint, new system.drawing.size(2, this.lbl_cutimage.height - 4));
            g.drawimage(this.backgroundimage, destrect, srcrect, graphicsunit.pixel);
            // 右边
            destrect = new rectangle(this.lbl_cutimage.width - 2, 2, 2, this.lbl_cutimage.height - 4);
            srcpoint = this.lbl_cutimage.location;
            srcpoint.offset(this.lbl_cutimage.width - 2, 2);
            srcrect = new rectangle(srcpoint, new system.drawing.size(2, this.lbl_cutimage.height - 4));
            g.drawimage(this.backgroundimage, destrect, srcrect, graphicsunit.pixel);
            // 绘制边框
            g.drawline(pen, 2, 2, this.lbl_cutimage.width - 3, 2);
            g.drawline(pen, 2, 2, 2, this.lbl_cutimage.height - 3);
            g.drawline(pen, this.lbl_cutimage.width - 3, 2, this.lbl_cutimage.width - 3, this.lbl_cutimage.height - 3);
            g.drawline(pen, 2, this.lbl_cutimage.height - 3, this.lbl_cutimage.width - 3, this.lbl_cutimage.height - 3);
            // 绘制四个角的调整块
            g.fillrectangle(brush, 0, 0, 4, 5);
            g.fillrectangle(brush, this.lbl_cutimage.width - 4, 0, 4, 5);
            g.fillrectangle(brush, 0, this.lbl_cutimage.height - 5, 4, 5);
            g.fillrectangle(brush, this.lbl_cutimage.width - 4, this.lbl_cutimage.height - 5, 4, 5);
            // 绘制中间的四个调整块
            int blockx = this.lbl_cutimage.width / 2 - 2;
            int blocky = this.lbl_cutimage.height / 2 - 2;
            g.fillrectangle(brush, blockx, 0, 4, 5);
            g.fillrectangle(brush, 0, blocky, 4, 5);
            g.fillrectangle(brush, blockx, this.lbl_cutimage.height - 5, 4, 5);
            g.fillrectangle(brush, this.lbl_cutimage.width - 4, blocky, 4, 5);
            // 绘制到 label 上
            e.graphics.drawimage(bmp_lbl, 0, 0);
            bmp_lbl.dispose();
        }
双击鼠标左键完成截图功能        /// <summary>
        /// 截取区域图片的鼠标按下事件处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbl_cutimage_mousedown(object sender, mouseeventargs e)
        {
            // 左键双击事件
            if (e.button == mousebuttons.left && e.clicks == 2)
            {
                if (this.lbl_cutimage.visible)
                {
                    execcutimage(false, false);
                }
            }
        }
注意:代码都贴完了,别忘了为窗体或组件绑定事件处理程序;
例如:截取区域图片的鼠标按下事件处理程序“lbl_cutimage_mousedown”,就是“lbl_cutimage”组件的“mousedown”事件的处理程序,绑定方法参考下图:
到此,基本截图的功能实现已经实现,赶快去截取一张图片,粘贴到qq的聊天窗口看看吧。
以上就是c#开发实例-订制屏幕截图工具(四)基本截图功能实现代码的详细内容。
   
 
   