【WinForm】截屏工具窗口简单实现原理,附详细代码

准备

  • Visual Studio 开发环境
  • 会写C#语言
  • 建立一个 WinForm 窗体项目
  1. 创建一个窗体,如Form4.cs,用于放置全屏下的截图,默认最大化,具体代码如下
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using WindowsFormsApp2.lib;

namespace WindowsFormsApp2
{
    public partial class Form4 : Form
    {
        // 定义存放返回的截图
        public Image returnImg = null;

        public Form4()
        {
            InitializeComponent();
        }


        private void Form4_Load(object sender, EventArgs e)
        {
            //默认最大化,推荐在设计模式下修改此属性
            //WindowState = FormWindowState.Maximized;
            Text = "屏幕区域";

            //截屏前隐藏本窗口
            Hide();
            //开始截屏
            var bmp = GetScreenFullImage();
            BackgroundImage = bmp;
            //显示本窗口
            Show();

            //打开对话框,选取区域
            var f5 = new Form5(bmp);
            var res = f5.ShowDialog();
            if (res == DialogResult.OK)
            {
                DialogResult = DialogResult.OK;
                //选好保留的图片
                returnImg = f5.returnImg;
                //var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "screen.png");
                //保存图片用  Image 转 Bitmap
                //Save(new Bitmap(returnImg), path);
            }
            //关闭
            //Close();
        }

        /// <summary>
        /// 保存到图片文件
        /// </summary>
        /// <param name="bm"></param>
        /// <param name="fileName"></param>
        public static void Save(Bitmap bm, string fileName)
        {
            if (fileName.EndsWith(".bmp"))
            {
                bm.Save(fileName, System.Drawing.Imaging.ImageFormat.Bmp);
            }
            else if (fileName.EndsWith(".jpg"))
            {
                bm.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            else if (fileName.EndsWith(".png"))
            {
                bm.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
            }
            bm.Dispose();
        }

        /// <summary>
        /// 打开图片文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static Image Open(string fileName)
        {
            Image originalImg = Image.FromFile(fileName);
            return originalImg;
        }

        /// <summary>
        /// 截取屏幕区域,默认全屏
        /// </summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private Bitmap GetScreenFullImage(int left = 0, int top = 0, int width = 0, int height = 0)
        {
            //屏幕宽度 
            int screenWidth = SystemInformation.VirtualScreen.Width;
            //屏幕高度 
            int screenHeight = SystemInformation.VirtualScreen.Height;

            if (width <= 0)
            {
                width = screenWidth;
            }
            if (height <= 0)
            {
                height = screenHeight;
            }

            Bitmap bmSave = new Bitmap(screenWidth, screenHeight);
            Graphics g = Graphics.FromImage(bmSave);

            g.CopyFromScreen(left, top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);
            g.Dispose();

            return bmSave;
        }

        /// <summary>
        /// 获取当前窗体的截图
        /// </summary>
        /// <returns></returns>
        private Bitmap GetCurrentWindowImage()
        {
            //创建窗体的Graphics对象 
            Graphics gSrc = this.CreateGraphics();
            HandleRef hDcSrc = new HandleRef(null, gSrc.GetHdc());
            //获取宽度 
            int width = this.Width - SystemInformation.FrameBorderSize.Width;
            //获取高度 
            int height = this.Height - SystemInformation.FrameBorderSize.Height;
            //复制图块的光栅操作码 
            const int SRCCOPY = 0xcc0020;
            //用于保存图片的位图对象 
            Bitmap bmSave = new Bitmap(width, height);
            //创建该位图的Graphics对象 
            Graphics gSave = Graphics.FromImage(bmSave);
            //得到句柄 
            HandleRef hDcSave = new HandleRef(null, gSave.GetHdc());
            DllCommon.BitBlt(hDcSave, 0, 0, width, height, hDcSrc, 0, 0, SRCCOPY);
            gSrc.ReleaseHdc();
            gSave.ReleaseHdc();
            gSrc.Dispose();
            gSave.Dispose();
            return bmSave;
        }
    }
}
  1. 还有,再新建一个DllCommon.cs引用,这是一个调用Windows系统的dll库,代码如下,
using System.Runtime.InteropServices;

namespace WindowsFormsApp2.lib
{
    public class DllCommon
    {
        /// <summary>
        /// 屏幕截取[包括桌面与窗口]
        /// </summary>
        /// <param name="hDC"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <param name="hSrcDC"></param>
        /// <param name="xSrc"></param>
        /// <param name="ySrc"></param>
        /// <param name="dwRop"></param>
        /// <returns></returns>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int BitBlt(HandleRef hDC, int x, int y, int nWidth, int nHeight, HandleRef hSrcDC, int xSrc, int ySrc, int dwRop);
    }
}
  1. 在创建一个窗体如Form5.cs,用作对话框,截图部分区域,换成图片返回
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form5 : Form
    {
        
        //定义返回的截图
        public Image returnImg = null;

        private Bitmap bmp = null;

        public Form5(Bitmap bmp)
        {
            this.bmp = bmp;
            InitializeComponent();
        }

        /// <summary>
        /// 窗口加载时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form5_Load(object sender, EventArgs e)
        {
            button1.Text = "确认截取";
            button1.BackColor = Color.White;
            getScreenRectImage();
        }

        /// <summary>
        /// 窗口移动时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form4_Move(object sender, EventArgs e)
        {
            getScreenRectImage();
        }



        private void getScreenRectImage()
        {
            Text = String.Format(@"截取区域:Width:{2}, Height:{3}, 坐标:X:{0}, Y:{1}", Left, Top, Width, Height);

            Bitmap partImg = GetPart(bmp, 0, 0, Width, Height, Left, Top);

            //会闪,效果不好
            //BackgroundImage = partImg;

            //用图片组件,效果好一点
            pictureBox1.Image = partImg;
        }

        private void Form4_Resize(object sender, EventArgs e)
        {
            getScreenRectImage();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
            returnImg = pictureBox1.Image;
            Close();
        }

        /// <summary>
        /// 获取图片指定部分
        /// </summary>
        /// <param name="originalImg">原始图片</param>
        /// <param name="pPartStartPointX">目标图片开始绘制处的坐标X值(通常为0)</param>
        /// <param name="pPartStartPointY">目标图片开始绘制处的坐标Y值(通常为0)</param>
        /// <param name="pPartWidth">目标图片的宽度</param>
        /// <param name="pPartHeight">目标图片的高度</param>
        /// <param name="pOrigStartPointX">原始图片开始截取处的坐标X值</param>
        /// <param name="pOrigStartPointY">原始图片开始截取处的坐标Y值</param>
        private static Bitmap GetPart(Bitmap originalImg, int pPartStartPointX, int pPartStartPointY, int pPartWidth, int pPartHeight, int pOrigStartPointX, int pOrigStartPointY)
        {
            Bitmap partImg = new Bitmap(pPartWidth, pPartHeight);
            Graphics graphics = Graphics.FromImage(partImg);
            Rectangle destRect = new Rectangle(new Point(pPartStartPointX, pPartStartPointY), new Size(pPartWidth, pPartHeight));//目标位置
            Rectangle origRect = new Rectangle(new Point(pOrigStartPointX, pOrigStartPointY), new Size(pPartWidth, pPartHeight));//原图位置(默认从原图中截取的图片大小等于目标图片的大小)

            graphics.DrawImage(originalImg, destRect, origRect, GraphicsUnit.Pixel);

            return partImg;
        }
    }
}

  1. 记录到此,一个截屏工具就这样完成了,调用它的代码如下所示
/// <summary>
/// 打开截屏窗口
/// </summary>
private void OpenScreenshotsDialog() 
{
	var f4 = new Form4();
	var res = f4.ShowDialog();
	if (res == DialogResult.OK && f4.returnImg!= null)
	{
		//保存到图片文件
		rectImg = f4.returnImg;
		var fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "screen.png");
		Form4.Save(new Bitmap(rectImg), fileName);
	}	
}
  1. 最后,附上运行效果图
    在这里插入图片描述

① 小提示:
截图窗口,默认是有最大化和最小化按钮,如果不需要,直接在设计模式下修改窗体属性即可

② 小提示:
笔者知道,WinForm的项目放到现在2022年以后已不再是主流了,对比WPF项目来说,入门时会选它,是因为比较容易上手吧,网上的相关学习资料还是有随着时间沉淀很多的,适合自学入门,笔者不建议花很多时间学会用它,技术更迭,不同往日。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TA远方

谢谢!收到你的爱╮(╯▽╰)╭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值