准备
- Visual Studio 开发环境
- 会写C#语言
- 建立一个 WinForm 窗体项目
- 创建一个窗体,如
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;
}
}
}
- 还有,再新建一个
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);
}
}
- 在创建一个窗体如
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;
}
}
}
- 记录到此,一个截屏工具就这样完成了,调用它的代码如下所示
/// <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);
}
}
- 最后,附上运行效果图
① 小提示:
截图窗口,默认是有最大化和最小化按钮,如果不需要,直接在设计模式下修改窗体属性即可
② 小提示:
笔者知道,WinForm
的项目放到现在2022年以后已不再是主流了,对比WPF
项目来说,入门时会选它,是因为比较容易上手吧,网上的相关学习资料还是有随着时间沉淀很多的,适合自学入门,笔者不建议花很多时间学会用它,技术更迭,不同往日。