很简单,就是先全屏截图,然后再按需要裁剪就可以了。
所以,首先要获取桌面的大小,代码如下:
public class PrimaryScreen
{
#region Win32 API
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr ptr);
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(
IntPtr hdc, // handle to DC
int nIndex // index of capability
);
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
#endregion
#region DeviceCaps常量
const int HORZRES = 8;
const int VERTRES = 10;
const int LOGPIXELSX = 88;
const int LOGPIXELSY = 90;
const int DESKTOPVERTRES = 117;
const int DESKTOPHORZRES = 118;
#endregion
#region 属性
/// <summary>
/// 获取屏幕分辨率当前物理大小
/// </summary>
public static Size WorkingArea
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
Size size = new Size();
size.Width = GetDeviceCaps(hdc, HORZRES);
size.Height = GetDeviceCaps(hdc, VERTRES);
ReleaseDC(IntPtr.Zero, hdc);
return size;
}
}
/// <summary>
/// 当前系统DPI_X 大小 一般为96
/// </summary>
public static int DpiX
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
int DpiX = GetDeviceCaps(hdc, LOGPIXELSX);
ReleaseDC(IntPtr.Zero, hdc);
return DpiX;
}
}
/// <summary>
/// 当前系统DPI_Y 大小 一般为96
/// </summary>
public static int DpiY
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
int DpiX = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(IntPtr.Zero, hdc);
return DpiX;
}
}
/// <summary>
/// 获取真实设置的桌面分辨率大小
/// </summary>
public static Size DESKTOP
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
Size size = new Size();
size.Width = GetDeviceCaps(hdc, DESKTOPHORZRES);
size.Height = GetDeviceCaps(hdc, DESKTOPVERTRES);
ReleaseDC(IntPtr.Zero, hdc);
return size;
}
}
/// <summary>
/// 获取宽度缩放百分比
/// </summary>
public static float ScaleX
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
int t = GetDeviceCaps(hdc, DESKTOPHORZRES);
int d = GetDeviceCaps(hdc, HORZRES);
float ScaleX = (float)GetDeviceCaps(hdc, DESKTOPHORZRES) / (float)GetDeviceCaps(hdc, HORZRES);
ReleaseDC(IntPtr.Zero, hdc);
return ScaleX;
}
}
/// <summary>
/// 获取高度缩放百分比
/// </summary>
public static float ScaleY
{
get
{
IntPtr hdc = GetDC(IntPtr.Zero);
float ScaleY = (float)(float)GetDeviceCaps(hdc, DESKTOPVERTRES) / (float)GetDeviceCaps(hdc, VERTRES);
ReleaseDC(IntPtr.Zero, hdc);
return ScaleY;
}
}
#endregion
}
使用 PrimaryScreen.DESKTOP 就可以获取桌面分辨率的大小了,有了这个大小,就可以开始全屏截图了,代码如下:
public class ImageHelper
{
/// <summary>
/// 截取全屏
/// </summary>
/// <returns></returns>
public static Bitmap GetScreen()
{
Size ScreenSize = PrimaryScreen.DESKTOP;
Bitmap bmp = new Bitmap(ScreenSize.Width, ScreenSize.Height);
using (Graphics g = Graphics.FromImage(bmp))
g.CopyFromScreen(0, 0, 0, 0, new Size(ScreenSize.Width, ScreenSize.Height));
return bmp;
}
/// <summary>
/// 图像明暗调整
/// </summary>
/// <param name="b">原始图</param>
/// <param name="degree">亮度[-255, 255]</param>
public static void Lighten(Bitmap b, int degree)
{
if (b == null)
{
//return null;
return;
}
if (degree < -255) degree = -255;
if (degree > 255) degree = 255;
try
{
int width = b.Width;
int height = b.Height;
int pix = 0;
BitmapData data = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
byte* p = (byte*)data.Scan0;
int offset = data.Stride - width * 3;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 处理指定位置像素的亮度
for (int i = 0; i < 3; i++)
{
pix = p[i] + degree;
if (degree < 0) p[i] = (byte)Math.Max(0, pix);
if (degree > 0) p[i] = (byte)Math.Min(255, pix);
} // i
p += 3;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
//return b;
}
catch
{
//return null;
}
} // end of Lighten
}
调用 ImageHelper.GetScreen() 即可以获取全屏截图
再然后,为了实现区域截图,我们需要把全屏截图放到一个窗体里面进行裁剪,弹出裁剪窗体的代码如下:
private void button1_Click(object sender, EventArgs e)
{
this.Opacity = 0; //先隐藏自己
Bitmap bitmap = ImageHelper.GetScreen(); //截取全屏
GetScreenForm frm = new GetScreenForm(bitmap); //准备区域截图
frm.ShowDialog(); //弹出区域截图界面
this.Opacity = 1; //显示自己
}
区域截图的代码有点多,无非就是鼠标按下、移动、松开的相关处理,以对全屏截图进行裁剪处理,代码如下:
public partial class GetScreenForm : Form
{
/// <summary>
/// 亮图(原图)
/// </summary>
public Bitmap bitmap { get; set; }
/// <summary>
/// 暗图
/// </summary>
public Bitmap bitmap2 { get; set; }
/// <summary>
/// 屏幕的宽
/// </summary>
public int W { get; set; }
/// <summary>
/// 屏幕的高
/// </summary>
public int H { get; set; }
/// <summary>
/// 适用于高DPI的宽度
/// </summary>
public int W2 { get; set; }
/// <summary>
/// 适用于高DPI的高度
/// </summary>
public int H2 { get; set; }
Graphics g;
Bitmap cache;
Graphics gMain;
/// <summary>
/// 构造方法
/// </summary>
public GetScreenForm(Bitmap bitmap)
{
//亮图 (也就是原图)
this.bitmap = bitmap;
this.W = bitmap.Width;
this.H = bitmap.Height;
//暗图
this.bitmap2 = new Bitmap(bitmap.Width, bitmap.Height);
using (Graphics g = Graphics.FromImage(bitmap2))
g.DrawImage(bitmap, 0, 0);
ImageHelper.Lighten(bitmap2, -100);
//求出适用于高DPI的宽和高
W2 = (int)(bitmap2.Width * PrimaryScreen.ScaleX);
H2 = (int)(bitmap2.Height * PrimaryScreen.ScaleY);
//初始化
InitializeComponent();
this.Width = (int)(this.W / PrimaryScreen.ScaleX);
this.Height = (int)(this.H / PrimaryScreen.ScaleY);
//绘图相关
cache = new Bitmap(this.W, this.H);
gMain = this.CreateGraphics();
g = Graphics.FromImage(cache);
}
/// <summary>
/// 双击关闭
/// </summary>
protected override void OnDoubleClick(EventArgs e)
{
//获取截图
if (SX > int.MinValue && SY > int.MinValue)
{
//获取区域
int x1 = SX, x2 = SX + SW;
if (x1 > x2) { x2 = x1 + x2; x1 = x2 - x1; x2 = x2 - x1; };
int y1 = SY, y2 = SY + SH;
if (y1 > y2) { y2 = y1 + y2; y1 = y2 - y1; y2 = y2 - y1; };
//截图
Bitmap bmp = new Bitmap(x2 - x1, y2 - y1);
Graphics g6 = Graphics.FromImage(bmp);
g6.DrawImage(bitmap,
new Rectangle(0, 0, bmp.Width, bmp.Height),
new Rectangle((int)(x1 * PrimaryScreen.ScaleX), (int)(y1 * PrimaryScreen.ScaleY), (int)((x2 - x1) * PrimaryScreen.ScaleX), (int)((y2 - y1) * PrimaryScreen.ScaleY)),
GraphicsUnit.Pixel);
bmp.Save("x.jpg", ImageFormat.Jpeg);
}
this.Close();
}
private void GetScreenForm_Load(object sender, EventArgs e)
{
}
protected override void OnShown(EventArgs e)
{
DrawForm();
}
void DrawForm()
{
//画暗图
g.DrawImage(bitmap2,
new Rectangle(0, 0, W, H), //目标
new Rectangle(0, 0, W2, H2), //源
GraphicsUnit.Pixel);
//画亮图
if (SX > int.MinValue && SY > int.MinValue)
{
g.DrawImage(bitmap,
new Rectangle(SX, SY, SW, SH),
new Rectangle((int)(SX * PrimaryScreen.ScaleX), (int)(SY * PrimaryScreen.ScaleY), (int)(SW * PrimaryScreen.ScaleX), (int)(SH * PrimaryScreen.ScaleY)),
GraphicsUnit.Pixel);
//new Rectangle(SX, SY, SW, SH), //目标
//new Rectangle(SX, SY, SW, SH), //源
//GraphicsUnit.Pixel);
}
//翻转
gMain.DrawImage(cache, 0, 0);
}
/// <summary>
/// 选择的区域
/// </summary>
public int SX { get; set; } = int.MinValue;
public int SY { get; set; } = int.MinValue;
public int SW { get; set; }
public int SH { get; set; }
/// <summary>
/// 工作类型 0未工作 1画框 2移框
/// </summary>
public int WorkType { get; set; }
/// <summary>
/// 移动的起点
/// </summary>
public int MoveX { get; set; }
public int MoveY { get; set; }
protected override void OnMouseDown(MouseEventArgs e)
{
//判断是不是点击在框里
bool inside = false;
if (SX > int.MinValue && SY > int.MinValue)
{
int x1 = SX, x2 = SX + SW;
if (x1 > x2) { x2 = x1 + x2; x1 = x2 - x1; x2 = x2 - x1; };
int y1 = SY, y2 = SY + SH;
if (y1 > y2) { y2 = y1 + y2; y1 = y2 - y1; y2 = y2 - y1; };
if (e.X > x1 && e.X < x2
&& e.Y > y1 && e.Y < y2)
{
inside = true;
}
}
if (inside)
{
//在框里,则进行移框
this.MoveX = e.X;
this.MoveY = e.Y;
this.WorkType = 2;
DrawForm();
}
else
{
//在框外,则重新画框
this.SX = e.X;
this.SY = e.Y;
this.SW = 0;
this.SH = 0;
this.WorkType = 1;
DrawForm();
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (this.WorkType == 1)
{
//画框
this.SW = e.X - this.SX;
this.SH = e.Y - this.SY;
}
else
{
//移框
this.SX += e.X - this.MoveX;
this.SY += e.Y - this.MoveY;
this.MoveX = e.X;
this.MoveY = e.Y;
}
DrawForm();
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (this.WorkType == 1)
{
this.SW = e.X - this.SX;
this.SH = e.Y - this.SY;
}
this.WorkType = 0;
DrawForm();
}
}
提供源代码给大家玩玩,点这里下载源代码。
来源:https://www.cnblogs.com/zhouyou96/archive/2020/01/08/12164774.html