很簡單,就是先全屏截圖,然後再按需要裁剪就可以了。 所以,首先要獲取桌面的大小,代碼如下: 使用 PrimaryScreen.DESKTOP 就可以獲取桌面解析度的大小了,有了這個大小,就可以開始全屏截圖了,代碼如下: 調用 ImageHelper.GetScreen() 即可以獲取全屏截圖 再然後 ...
很簡單,就是先全屏截圖,然後再按需要裁剪就可以了。
所以,首先要獲取桌面的大小,代碼如下:
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(); } }
提供源代碼給大家玩玩,點這裡下載源代碼。