c# wpf 利用截屏鍵實現截屏功能
? ? 最近做一個wpf程序需要截圖功能,查找資料費了一些曲折,跟大家分享一下。
????先是找到了這樣一份代碼:
????static?class?ScreenCut
????{
????????public?static?System.Drawing.Bitmap?GetScreenSnapshot()
????????{
????????????System.Drawing.Rectangle?rc = System.Windows.Forms.SystemInformation
????????????System.Drawing.Bitmap?bitmap = new?System.Drawing.Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
????????????using?(System.Drawing.Graphics?g = System.Drawing.Graphics.FromImage(bitmap))
????????????{
????????????????g.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, System.Drawing.CopyPixelOperation
????????????}
????????????return?bitmap;
????????}
????????public?static?BitmapSource?ToBitmapSource(this?System.Drawing.Bitmap?bmp)
????????{
????????????BitmapSource?returnSource;
????????????try
????????????{
????????????????returnSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr
????????????}
????????????catch
????????????{
????????????????returnSource = null;
????????????}
????????????return?returnSource;
????????}
?
????????public?static?BitmapSource?CopyFromScreenSnapshot(BitmapSource?screenSnapshot, Rect?region)
????????{
????????????var?sourceRect = new?System.Drawing.Rectangle((int)region.Left, (int)region.Top, (int)region.Width, (int)region.Height);
????????????var?destRect = new?System.Drawing.Rectangle(0, 0, sourceRect.Width, sourceRect.Height);
?
????????????if?(screenSnapshot != null)
????????????{
????????????????var?bitmap = new?System.Drawing.Bitmap(sourceRect.Width, sourceRect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
????????????????using?(System.Drawing.Graphics?g = System.Drawing.Graphics.FromImage(bitmap))
????????????????{
????????????????????g.DrawImage(bitmap, destRect, sourceRect.Left, sourceRect.Top, sourceRect.Width, sourceRect.Height, System.Drawing.GraphicsUnit.Pixel);
????????????????}
?
????????????????return?bitmap.ToBitmapSource();
????????????}
?
????????????return?null;
????????}
}
?
調用時包裝一下,下面的函數截下屏幕指定區域並保存:
????System.Drawing.Image?takePicture(Rect?wnd, String?saveLocation, String?pictureName)
{ ???
????????BitmapSource?bitmapScr = ScreenCut.CopyFromScreenSnapshot(ScreenCut.ToBitmapSource(ScreenCut.GetScreenSnapshot()),wnd);
????????PngBitmapEncoder?encoder = new?PngBitmapEncoder();
????????encoder.Frames.Add(BitmapFrame.Create(bitmapScr));
????????FileStream?fileStream = new?FileStream(saveLocation + "\\"?+ pictureName ".png", FileMode.Create, FileAccess.Write);
????????encoder.Save(fileStream);
????????fileStream.Close();
}
?
但實際效果保存下來的圖是空的,經驗證前兩個函數沒有問題。於是我查資料找到了另一種切割BitmapSource的方法,將第三個函數改成這樣:
BitmapSource?CopyFromScreenSnapshot(BitmapSource?screenSnapshot, Rect?region)
{
????????Int32Rect?window?= new Int32Rect(region.X, region.Y, region.Width, region.Height);
????????BitmapSource?bitmapScr = ScreenCut.ToBitmapSource(ScreenCut.GetScreenSnapshot());
????????//計算Stride
????????int?stride = bitmapScr.Format.BitsPerPixel * window.Width / 8;
????????//聲明字節數組
????????byte[] data = new?byte[window.Height * stride];
????????//調用CopyPixels
????????bitmapScr.CopyPixels(window, data, stride, 0);
????????PngBitmapEncoder?encoder = new?PngBitmapEncoder();
????return?BitmapSource.Create(window.Width, window.Height, 0, 0, PixelFormats.Bgr32, null, data, stride);
}
?
這樣總算能截到屏了。不過後來發現在某些主題下有些程序的窗口在截下的圖中是透明的。這個方法還是不夠完美。
我想到了利用鍵盤的截屏鍵截圖再進行剪切的方法。分為三步:1、模擬按下截屏鍵 2、從剪貼板獲取圖片 3、截取和保存圖片。
對於第一點,利用SendMessage函數發送WM_KEY事件沒有用,不過我找到了另一個模擬鍵盤輸入的方法:
using?System.Runtime.InteropServices;
????[DllImport("user32.dll")]
????static?extern?void?keybd_event
????(
????????byte?bVk,// 虛擬鍵值
????????byte?bScan,// 硬件掃描碼 ???
????????uint?dwFlags,// 動作標識 ???
????????IntPtr?dwExtraInfo// 與鍵盤動作關聯的輔加信息 ???
);
?
上面這個函數對本程序發送按鈕事件,模擬截屏鍵的話像下面這樣寫,wpf需要在項目添加引用System.Windows.Forms
const?int?VK_SNAPSHOT = 0x2C;
????public?void?PrintScreen()
????{
????????keybd_event((byte)VK_SNAPSHOT, 0, 0x0, IntPtr.Zero);//down ?
????????System.Windows.Forms.Application.DoEvents();//強制窗口響應按鈕事件
????????keybd_event((byte)VK_SNAPSHOT, 0, 0x2, IntPtr.Zero);//up ?
????????System.Windows.Forms.Application.DoEvents();
}
?
接下來從剪貼板獲取圖片,wpf需要在項目添加引用System.Windows.Forms??System.Drawing
????if?(System.Windows.Forms.Clipboard.ContainsImage())
????{
???????System.Drawing.Image?image = System.Windows.Forms.Clipboard.GetImage();
}
?
然後剪切。
????System.Drawing.Image?cutPicture(System.Drawing.Image?image, Int32Rect?window)
????{
????????PrintScreen();
????????if?(window.X + window.Width > image.Width)
????????????window.Width = image.Width - window.X;
????????if?(window.Y + window.Height > image.Height)
????????????window.Height = image.Height - window.Y;
????????if?(image == null)
????????{
????????????//新建一個bmp圖片
????????????System.Drawing.Image?bitmap = new?System.Drawing.Bitmap(window.Width, window.Height);
????????????//新建一個畫板
????????????System.Drawing.Graphics?graphic = System.Drawing.Graphics.FromImage(bitmap);
????????????//設置高質量查值法
????????????graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
????????????//設置高質量,低速度呈現平滑程度
????????????graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
????????????//清空畫布並以透明背景色填充
????????????graphic.Clear(System.Drawing.Color.Transparent);
????????????//在指定位置並且按指定大小繪制原圖片的指定部分
????????????graphic.DrawImage(image, new?System.Drawing.Rectangle(0, 0, window.Width, window.Height), new?System.Drawing.Rectangle(window.X, window.Y, window.Width, window.Height), System.Drawing.GraphicsUnit.Pixel);
????????????return?bitmap;
????????}
????????else
????????{
????????????return?null;
????????}
}
?
最後包裝一下
????System.Drawing.Image?cutScreen(Int32Rect?window)
????{
????????PrintScreen();
????????Thread.Sleep(1000);
????????if?(System.Windows.Forms.Clipboard.ContainsImage())
????????{
????????????System.Drawing.Image?image?=?cutPicture(System.Windows.Forms.Clipboard.GetImage(), Int32Rect?window);
????????????return?image;
????????}
????????else
????????{
????????????Console.WriteLine("clipboard doesn‘t contain picture");
????????????return?null;
????????}
}
System.Drawing.Image類有實例函數Save,保存很簡單,就不細說了。
資料來源:
http://www.cnblogs.com/zhouyinhui/archive/2010/08/20/1804762.html
https://www.mgenware.com/blog/?p=285
http://blog.csdn.net/testcs_dn/article/details/39762017
c# wpf 利用截屏鍵實現截屏功能