浅析如何用C#.NET做屏幕截图软件以及注册全局快捷键(上)1
2010-04-04 18:06
260 查看
最近为了学习C#,决定自己做一个屏幕截图工具,来代替长久以来每次都要按下PrintScreen键然后到CliPBoard里面寻找之麻烦。学以致用~
用C#做屏幕截图,大致有三种方法。
1、最managed大概就是使用Graphics.CopyFromScreen()方法,此方法有四个重载,不过经反编可见最后调用的都是:
调用该方法的优点是代码简单,不用平台调用。不过最大的缺点是:不能截取半透明窗体。你要想截图透明窗体的话,可以加一个参数,它就是:CopyPixelOperation.CaptureBlt。但是,这样的话,只能截图透明窗体,截不到屏幕的其他部分了。所以,该方法已经基本可以放弃了。不过我们还是来研究了一下CopyFromScreen()的内部实现吧,看看问题之所在。下面是该方法的具体实现,reflect自System.Drawing.dll
CopyFromScreen
2、平台调用,即调用Windows的API函数。其中要用到的最主要的就是BitBlt()。在此,本人先给各位推荐个网站,它就是:www.pinvoke.net,一个包含几乎所有API的wiki,里面一般还含有示例代码~为了便于没有网络的情况下查询,本人已经把该网站拷贝下来了。。耗费了一天时间做成CHM。。。
先来看看BitBlt()的description:The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
这里,我们只关心它的最后一个参数/// <param name="dwRop">A raster-operation code.</param>
中文翻译大概叫作:光栅操作码。大概就是控制从source device context 到 destination device context的拷贝方式。它是一个DWORD类型,取值在
现在继续回来说截取透明窗体的问题,我们知道它跟dwRop参数有关,在codeproject上面可以找到的源码,调用BitBlt()时,都是这样的:
我想一般的屏幕截图软件也是这样做的,这样做的话,你是不能截取到透明窗体的,我们应该改成这个样子:
通过试验可知是实现了预期效果。CaptureBlt的作用在上面~
需要注意的是,当我们使用BitBlt的时候,涉及设备上下文句柄操作,需要用到另外几个API函数来创建和释放资源。贴个例子:
GetDesktopImage
可见虽然直接的平台调用相比Graphics.CopyFromScreen()速度快,灵活,但是还是相当繁琐的。涉及到句柄操作。这些操作在Graphics.CopyFromScreen()已经替我们做了。
下面来说第三种方法:
出处:http://1971ruru.cnblogs.com/
用C#做屏幕截图,大致有三种方法。
1、最managed大概就是使用Graphics.CopyFromScreen()方法,此方法有四个重载,不过经反编可见最后调用的都是:
CopyFromScreen(int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
调用该方法的优点是代码简单,不用平台调用。不过最大的缺点是:不能截取半透明窗体。你要想截图透明窗体的话,可以加一个参数,它就是:CopyPixelOperation.CaptureBlt。但是,这样的话,只能截图透明窗体,截不到屏幕的其他部分了。所以,该方法已经基本可以放弃了。不过我们还是来研究了一下CopyFromScreen()的内部实现吧,看看问题之所在。下面是该方法的具体实现,reflect自System.Drawing.dll
CopyFromScreen
public void CopyFromScreen(int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation) { switch (copyPixelOperation) { case CopyPixelOperation.NotSourceErase: case CopyPixelOperation.NotSourceCopy: case CopyPixelOperation.NoMirrorBitmap: case CopyPixelOperation.Blackness: case CopyPixelOperation.SourceErase: ... case CopyPixelOperation.SourceCopy: case CopyPixelOperation.SourceAnd: case CopyPixelOperation.MergePaint: case CopyPixelOperation.SourcePaint: case CopyPixelOperation.PatCopy: case CopyPixelOperation.PatPaint: case CopyPixelOperation.Whiteness: case CopyPixelOperation.CaptureBlt: { new UIPermission(UIPermissionWindow.AllWindows).Demand(); int width = blockRegionSize.Width; int height = blockRegionSize.Height; using (DeviceContext context = DeviceContext.FromHwnd(IntPtr.Zero)) { HandleRef hSrcDC = new HandleRef(null, context.Hdc); HandleRef hDC = new HandleRef(null, this.GetHdc()); try { if (SafeNativeMethods.BitBlt(hDC, destinationX, destinationY, width, height, hSrcDC, sourceX, sourceY, (int) copyPixelOperation) == 0) { throw new Win32Exception(); } } finally { this.ReleaseHdc(); } } return; } } throw new InvalidEnumArgumentException("value", (int) copyPixelOperation, typeof(CopyPixelOperation)); }
通过上面代码可知,类库里面最后调用的是Windows 的API :BitBlt(),这就是我们要说的第二种方法。
2、平台调用,即调用Windows的API函数。其中要用到的最主要的就是BitBlt()。在此,本人先给各位推荐个网站,它就是:www.pinvoke.net,一个包含几乎所有API的wiki,里面一般还含有示例代码~为了便于没有网络的情况下查询,本人已经把该网站拷贝下来了。。耗费了一天时间做成CHM。。。
先来看看BitBlt()的description:The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
这里,我们只关心它的最后一个参数/// <param name="dwRop">A raster-operation code.</param>
中文翻译大概叫作:光栅操作码。大概就是控制从source device context 到 destination device context的拷贝方式。它是一个DWORD类型,取值在
// Summary: // Determines how the source color in a copy pixel operation is combined with // the destination color to result in a final color. public enum CopyPixelOperation { // Summary: // The bitmap is not mirrored. NoMirrorBitmap = -2147483648, // // Summary: // The destination area is filled by using the color associated with index 0 // in the physical palette. (This color is black for the default physical palette.) Blackness = 66, // // Summary: // The source and destination colors are combined using the Boolean OR operator, // and then resultant color is then inverted. NotSourceErase = 1114278, // // Summary: // The inverted source area is copied to the destination. NotSourceCopy = 3342344, // // Summary: // The inverted colors of the destination area are combined with the colors // of the source area using the Boolean AND operator. SourceErase = 4457256, // // Summary: // The destination area is inverted. DestinationInvert = 5570569, // // Summary: // The colors of the brush currently selected in the destination device context // are combined with the colors of the destination are using the Boolean XOR // operator. PatInvert = 5898313, // // Summary: // The colors of the source and destination areas are combined using the Boolean // XOR operator. SourceInvert = 6684742, // // Summary: // The colors of the source and destination areas are combined using the Boolean // AND operator. SourceAnd = 8913094, // // Summary: // The colors of the inverted source area are merged with the colors of the // destination area by using the Boolean OR operator. MergePaint = 12255782, // // Summary: // The colors of the source area are merged with the colors of the selected // brush of the destination device context using the Boolean AND operator. MergeCopy = 12583114, // // Summary: // The source area is copied directly to the destination area. SourceCopy = 13369376, // // Summary: // The colors of the source and destination areas are combined using the Boolean // OR operator. SourcePaint = 15597702, // // Summary: // The brush currently selected in the destination device context is copied // to the destination bitmap. PatCopy = 15728673, // // Summary: // The colors of the brush currently selected in the destination device context // are combined with the colors of the inverted source area using the Boolean // OR operator. The result of this operation is combined with the colors of // the destination area using the Boolean OR operator. PatPaint = 16452105, // // Summary: // The destination area is filled by using the color associated with index 1 // in the physical palette. (This color is white for the default physical palette.) Whiteness = 16711778, // // Summary: // Windows that are layered on top of your window are included in the resulting // image. By default, the image contains only your window. Note that this generally // cannot be used for printing device contexts. CaptureBlt = 1073741824, }
里面。
现在继续回来说截取透明窗体的问题,我们知道它跟dwRop参数有关,在codeproject上面可以找到的源码,调用BitBlt()时,都是这样的:
BitBlt( hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, PlatformInvokeGDI32.TernaryRasterOperations.SourceCopy);
我想一般的屏幕截图软件也是这样做的,这样做的话,你是不能截取到透明窗体的,我们应该改成这个样子:
BitBlt( hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, (uint)(PlatformInvokeGDI32.TernaryRasterOperations.SourceCopy | PlatformInvokeGDI32.TernaryRasterOperations.CaptureBlt) );
通过试验可知是实现了预期效果。CaptureBlt的作用在上面~
需要注意的是,当我们使用BitBlt的时候,涉及设备上下文句柄操作,需要用到另外几个API函数来创建和释放资源。贴个例子:
GetDesktopImage
public static Bitmap GetDesktopImage() { //In size variable we shall keep the size of the screen. SIZE size; //Variable to keep the handle to bitmap. IntPtr hBitmap; //Here we get the handle to the desktop device context. IntPtr hDC = PlatformInvokeUSER32.GetDC(PlatformInvokeUSER32.GetDesktopWindow()); //Here we make a compatible device context in memory for screen device context. IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC); //We pass SM_CXSCREEN constant to GetSystemMetrics to get the X coordinates of screen. size.cx = PlatformInvokeUSER32.GetSystemMetrics(PlatformInvokeUSER32.SM_CXSCREEN); //We pass SM_CYSCREEN constant to GetSystemMetrics to get the Y coordinates of screen. size.cy = PlatformInvokeUSER32.GetSystemMetrics(PlatformInvokeUSER32.SM_CYSCREEN); //We create a compatible bitmap of screen size using screen device context. hBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(hDC, size.cx, size.cy); //As hBitmap is IntPtr we can not check it against null. For this purspose IntPtr.Zero is used. if (hBitmap!=IntPtr.Zero) { //Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap. IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject(hMemDC, hBitmap); //We copy the Bitmap to the memory device context. PlatformInvokeGDI32.BitBlt( hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, (uint)(PlatformInvokeGDI32.TernaryRasterOperations.SRCCOPY | PlatformInvokeGDI32.TernaryRasterOperations.CAPTUREBLT) ); //We select the old bitmap back to the memory device context. PlatformInvokeGDI32.SelectObject(hMemDC, hOld); //We delete the memory device context. PlatformInvokeGDI32.DeleteDC(hMemDC); //We release the screen device context. PlatformInvokeUSER32.ReleaseDC(PlatformInvokeUSER32.GetDesktopWindow(), hDC); //Image is created by Image bitmap handle and stored in local variable. Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap); //Release the memory to avoid memory leaks. PlatformInvokeGDI32.DeleteObject(hBitmap); //This statement runs the garbage collector manually. GC.Collect(); //Return the bitmap return bmp; } //If hBitmap is null retunrn null. return null; }
可见虽然直接的平台调用相比Graphics.CopyFromScreen()速度快,灵活,但是还是相当繁琐的。涉及到句柄操作。这些操作在Graphics.CopyFromScreen()已经替我们做了。
下面来说第三种方法:
出处:http://1971ruru.cnblogs.com/
相关文章推荐
- 浅析如何用C#.NET做屏幕截图软件以及注册全局快捷键(上)
- 浅析如何用C#.NET做屏幕截图软件以及注册全局快捷键(下)
- 浅析如何用C#.NET做屏幕截图软件以及注册全局快捷键(下)
- C# 如何获取屏幕的截图,以及如何在图像上添加文字
- C#软件开发实例.私人订制自己的屏幕截图工具(二)创建项目、注册热键、显示截图主窗口
- C#软件开发实例.私人订制自己的屏幕截图工具(二)创建项目、注册热键、显示截图主窗口
- C#软件开发实例.私人订制自己的屏幕截图工具(五)针对拖拽时闪烁卡顿现象的优化
- C#软件开发实例.私人订制自己的屏幕截图工具(十)在截图中包含鼠标指针形状
- Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库 自定义日志记录功能,按日记录,很方便 C#常量和字段以及各种方法的语法总结 类型,对象,线程栈,托管堆在运行时的关系,以及clr如何调用静态方法,实例方法,和虚方法 asp.net webapi 自定义身份验证
- C#_注册系统全局快捷键
- c#注册全局快捷键
- C# 窗体(Form)中如何实现全局快捷键 如:[Ctrl + Enter]
- C# 注册系统全局快捷键
- 黄聪:VS2010开发如何在c#中使用Ctrl、Alt、Tab等全局组合快捷键
- 截图软件Shutter-如何绑定键盘快捷键?
- C#软件开发实例.私人订制自己的屏幕截图工具(六)添加配置管理功能
- C#软件开发实例.私人订制自己的屏幕截图工具——放大镜的功能代码优化
- C#软件开发实例.私人订制自己的屏幕截图工具(六)添加配置管理功能
- [C#.net]如何解决安装系统全局钩子程序调试时失败的问题
- C#软件开发实例.个人定制自己的屏幕抓图工具(八)加入了截图功能键盘