很简单,就是先全屏截图,然后再按需要裁剪就可以了。
所以,首先要获取桌面的大小,代码如下:
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(); } }
提供源代码给大家玩玩,点这里下载源代码。
您可能感兴趣的文章:
如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!
网友评论