屏幕截圖是一個比較常用的功能,在項目中出現的比例也比較高,至少我做過的每個項目都有屏幕截圖這個功能,從全屏截圖到區域截圖都有出現過。當然區域截圖已然包含了全屏截圖。
全屏截圖方式有好幾種,調用API截圖、調用操作系統的截圖然后到剪切板去取(當然這種方式幾乎沒人會去用)、用Graphics去畫屏幕等等。
下面上Graphics畫屏幕的代碼,畢竟這種方式代碼量最少。
//截取屏幕 Bitmap myImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics g = Graphics.FromImage(myImage); g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)); g.Dispose();
上面的代碼即可截取當前屏幕的圖像。注:由於WPF是使用DirectX進行渲染的,此方式截圖在部分系統會截圖不到wpf的窗體。(win7,windows server2008,windows vista均能截取到wpf窗體,windows XP無法截取到WPF窗體,原因可能是windows xp出現時還沒有WPF呢)
實現區域截圖,主要有四個步驟,一截取全屏,彈出遮罩層,畫選擇區,截取選擇區域
一、截取全屏可用上面代碼實現,這里就不寫了。
二、彈出遮罩層
遮罩層的目的是用來畫截圖區域,一般采用半透明方式。代碼如下:
this.BackColor = Color.Gray; this.Opacity = 0.5; this.FormBorderStyle = FormBorderStyle.None; this.WindowState = FormWindowState.Maximized;
設置窗體背景顏色,通明度,邊框樣式及使其最大化。即可彈出全屏遮罩層。
三、畫選擇區
這個就是截屏中最重要的部分了
我們需要在窗體中加入pictureBox控件,且Dock屬性設置為Fill,這樣才能在屏幕上畫選擇區
跟隨鼠標在 pictureBox的圖片上畫矩形 private int intStartX = 0; private int intStartY = 0; private bool isMouseDraw = false; private void pictureBox_Src_MouseDown(object sender, MouseEventArgs e) { isMouseDraw = true; intStartX = e.X; intStartY = e.Y; } private void pictureBox_Src_MouseMove(object sender, MouseEventArgs e) { if (isMouseDraw) { try { Graphics g = this.pictureBox_Src.CreateGraphics(); //清空上次畫下的痕跡 g.Clear(this.pictureBox_Src.BackColor); Brush brush = new SolidBrush(Color.Red); Pen pen = new Pen(brush, 1); pen.DashStyle = DashStyle.Solid; g.DrawRectangle(pen, new Rectangle(intStartX > e.X ? e.X : intStartX, intStartY > e.Y ? e.Y : intStartY, Math.Abs(e.X - intStartX), Math.Abs(e.Y - intStartY))); g.Dispose(); } catch (Exception ex) { ex.ToString(); } } } private void pictureBox_Src_MouseUp(object sender, MouseEventArgs e) { isMouseDraw = false; intStartX = 0; intStartY = 0; }
當然這只是在圖片上畫了一個紅色的矩形,沒法二次調整矩形大小,移動矩形,且畫圖時會不停的清除畫下的痕跡,導致屏幕閃爍,且平時使用的屏幕截圖在選擇區的區域亮度都會高些,這些都沒實現,不過既然能畫區域了那這些就都不是問題了,只需稍作修改即可,以下給出部分修改代碼:
填充選擇區
SolidBrush soldwhite = new SolidBrush(Color.White); Rectangle rec = new Rectangle(StartX, StartY, ScreenWidth, ScreenHeight); g.FillRectangle(soldwhite, rec);//用來填充矩形區域
屏幕閃爍
清除時屏幕閃爍是由於清除的整個圖片,然后在重新繪制的,這樣若加上填充區設置為白色,我們能看到填充區域閃爍的很厲害,解決方式為采用填充的方式清除選擇區域外的部分,這樣整個圖片總共分5此填充和一次划線。
Graphics g = this.pictureBox1.CreateGraphics(); //清空上次畫下的痕跡 // g.Clear(this.pictureBox1.BackColor); g.FillRectangle(soldgray, 0, 0, pictureBox1.Width, StartY);//清除上 g.FillRectangle(soldgray, 0, StartY + ScreenHeight, pictureBox1.Width, pictureBox1.Height - (StartY + ScreenHeight));//清除下 g.FillRectangle(soldgray, 0, StartY, StartX, ScreenHeight + 1);//清除左 g.FillRectangle(soldgray, StartX + ScreenWidth, StartY, pictureBox1.Width - (StartX + ScreenWidth), ScreenHeight + 1);//清除右
二次調整大小及選擇區移動
當我們對區域進行選擇后,想二次調整大小通常會看到鼠標樣式變化,表示可以對其進行修改或移動
/// <summary> /// 設置鼠標樣式 /// </summary> /// <param name="p"></param> private void SetCursorStyle(Point p) { if (p.X > StartX && p.X < StartX + ScreenWidth && p.Y > StartY && p.Y < StartY + ScreenHeight) {this.Cursor = Cursors.SizeAll; } else if (p.X >= StartX - 10 && p.X <= StartX && p.Y >= StartY - 10 && p.Y <= StartY) {this.Cursor = Cursors.SizeNWSE; } else if (p.X >= StartX + ScreenWidth && p.X <= StartX + ScreenWidth + 10 && p.Y <= StartY + ScreenHeight + 10 && p.Y >= StartY + ScreenHeight) {this.Cursor = Cursors.SizeNWSE; } else if ((p.X >= StartX + ScreenWidth && p.X <= StartX + ScreenWidth + 10 && p.Y >= StartY - 10 && p.Y <= StartY)) {this.Cursor = Cursors.SizeNESW; } else if (p.X >= StartX - 10 && p.X <= StartX && p.Y <= StartY + ScreenHeight + 10 && p.Y >= StartY + ScreenHeight) {this.Cursor = Cursors.SizeNESW; } else {this.Cursor = Cursors.Default; } }
這是設置鼠標在選擇區域內的樣式和四個角的樣式,若是在4個角,只需將起始坐標設置好之后和原來一樣畫區域就行,若是在區域中,移動選擇區則需根據當前坐標和開始坐標計算出差值,在移動時更改開始坐標,固定寬高畫區域即可,若移動到屏幕邊緣需加上判斷。
四、截取選擇區域
畫好區域后,需要選擇是否截取,通常會給出按鈕選擇我們只需在MouseUP和MouseDown事件中加上按鈕的隱藏和顯示即可,顯示時根據選擇區計算顯示的坐標位置。
截取選擇區代碼
Bitmap map = myImage.Clone(new Rectangle(StartX, StartY, ScreenWidth, ScreenHeight), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
這樣即可實現簡單的區域截圖了。