用c#来捕获屏幕(1)
[ 作者: 王天 添加时间: 2002-3-29 14:37:15 ]
来源: 赛迪网 www.ccidnet.com
其实用c#可以完成其他程序设计语言的几乎全部功能,当然c#自身的许多独到的功能,是其他程序语言所无法实现的,这就是c#越来越受到广大程序员的喜欢的原因。本文就来探讨一下用c#去实现一个重要的功能,用他来编写一个捕获当前屏幕地程序。通过这个程序,我们将了解到c#是如何调用api函数,和.net框架中的类库内容是多么地丰富,功能是多么地强大。
一. 程序设计开发及运行环境:
(1).微软视窗2000服务器版
(2)..net framework sdk beta 2
二. 程序设计的关键步骤:
要想完成这个功能,首先要了解一下在c#中如何调用api(应用程序接口)函数。虽然在.net框架中已经提供了许多类库,这些类库的功能也十分强大,但对于一些windows底层编程来说,还是要通过调用这些api函数才可以实现。所有api都在"kernel"、"user "和"gdi"三个库中得以运行:其中"kernel",他的库名为 "kernel32.dll", 他主要用于产生与操作系统之间的关联,譬如:程序加载,上下文选择,文件输入输出,内存管理等等。"user "这个类库在win32中名叫 "user32.dll"。 它允许管理全部的用户接口。譬如:窗口 、菜单 、对话框 、图标等等。"gdi"(图象设备接口),它在win32中的库名为:"gdi32.dll",它是图形输出库。使用gdi windows"画"出窗口、菜单以及对话框等;它能创建图形输出;它也能保存图形文件。由于本文所涉及到是图象问题,所有调用的类库是"gdi32.dll"。在本文程序中我们使用的api函数是"bitblt",这个函数对于广大程序员来说,一定不感觉到陌生,因为在图象处理方面他的用途是相对广的,在用其他程序语言编程中,时常也要和他打交道。在.net framework sdk中有一个名字空间"system.runtime.interopservices",此名字空间提供了一系列的类来访问com对象,和调用本地的api函数。下面是在c#中声明此函数:
[ system.runtime.interopservices.dllimportattribute ( "gdi32.dll" ) ]
private static extern bool bitblt (
intptr hdcdest , // 目标 dc的句柄
int nxdest ,
int nydest ,
int nwidth ,
int nheight ,
intptr hdcsrc , // 源dc的句柄
int nxsrc ,
int nysrc ,
system.int32 dwrop // 光栅的处理数值
) ;
通过上面这个声明,就可以在下面的代码中使用此函数了。
下面是用c#做屏幕捕获程序的具体实现步骤:
(1).首先要获得当前屏幕的graphic对象,通过以下代码可以实现:
graphics g1 = this.creategraphics ( ) ;
(2).创建一个bitmap对象,并且这个bitmap对象的大小是当前屏幕:
首先要获得当前屏幕的大小,通过名字空间"system.windows.forms"中的"screen"类的getworkingarea()方法,可以实现。下面是得到当前屏幕的长(height)和宽(width):
rectangle rect = new rectangle ( ) ;
rect = screen.getworkingarea ( this ) ;
"屏幕宽"= rect.width ;
"屏幕长"= rect.height ;
至此就可以得到我们想要的bitmap了,通过下列语句可以实现:
image myimage = new bitmap ( rect.width , rect.height , g1 ) ;
//创建以屏幕大小为标准的位图
(3).获得当前屏幕和此bitmap对象的dc,这可以通过下列语句实现:
//得到屏幕的dc
intptr dc1 = g1.gethdc ( ) ;
//得到bitmap的dc
intptr dc2 = g2.gethdc ( ) ;
(4).调用api函数,把当前屏幕拷贝到创建的bitmap中:
bitblt ( dc2 , 0 , 0 , rect.width , rect.height , dc1 , 0 , 0 , 13369376 ) ;
(5).释放当前屏幕和此bitmap对象的dc,通过下面代码可以实现:
//释放掉屏幕的dc
g1.releasehdc ( dc1 ) ;
//释放掉bitmap的dc
g2.releasehdc ( dc2 ) ;
(6).保存bitmap对象,形成jpg图片:
myimage.save ( @"c:/capture.jpg" , imageformat.jpeg );
当然你也可以根据自己的需要,把屏幕以其他图片的格式来保存,如果你想把图片保存为位图文件,可以把"imageformat.jpeg"改换成"imageformat.bmp";想把图片保存为gif文件,就把"imageformat.jpeg"改换成"imageformat.gif"。你可以保存的文件类型大概有十多种,这里就不一一介绍了,当然你也要相应改变保存文件的后缀。
三. 用c#来捕获屏幕的源程序代码(capture.cs):
了解上面的这些步骤的实现方法,就可以得到用c#捕获屏幕的源程序,如下:
using system ;
using system.drawing ;
using system.collections ;
using system.componentmodel ;
using system.windows.forms ;
using system.data ;
using system.drawing.imaging ;
public class form1 : form
{
private button button1 ;
private system.componentmodel.container components = null ;
public form1 ( )
{
//初始化窗体中的各个组件
initializecomponent ( ) ;
}
// 清除程序中使用过的资源
protected override void dispose ( bool disposing )
{
if ( disposing )
{
if ( components != null )
{
components.dispose ( ) ;
}
}
base.dispose ( disposing ) ;
}
private void initializecomponent ( )
{
button1 = new button ( );
suspendlayout ( ) ;
button1.location = new system.drawing.point ( 64 , 40 ) ;
button1.name = "button1" ;
button1.size = new system.drawing.size ( 80 , 32 ) ;
button1.tabindex = 0 ;
button1.text = "捕获" ;
button1.click += new system.eventhandler ( button1_click ) ;
autoscalebasesize = new system.drawing.size ( 6 , 14 ) ;
clientsize = new system.drawing.size ( 216 , 125 ) ;
controls.add ( button1 ) ;
maximizebox = false ;
minimizebox = false ;
name = "form1" ;
text = "c#捕获当前屏幕!" ;
resumelayout ( false ) ;
}
//声明一个api函数
[ system.runtime.interopservices.dllimportattribute ( "gdi32.dll" ) ]
private static extern bool bitblt (
intptr hdcdest , // 目标 dc的句柄
int nxdest ,
int nydest ,
int nwidth ,
int nheight ,
intptr hdcsrc , // 源dc的句柄
int nxsrc ,
int nysrc ,
system.int32 dwrop // 光栅的处理数值
) ;
static void main ( )
{
application.run ( new form1 ( ) ) ;
}
private void button1_click ( object sender , system.eventargs e )
{
//获得当前屏幕的大小
rectangle rect = new rectangle ( ) ;
rect = screen.getworkingarea ( this ) ;
//创建一个以当前屏幕为模板的图象
graphics g1 = this.creategraphics ( ) ;
//创建以屏幕大小为标准的位图
image myimage = new bitmap ( rect.width , rect.height , g1 ) ;
graphics g2 = graphics.fromimage ( myimage ) ;
//得到屏幕的dc
intptr dc1 = g1.gethdc ( ) ;
//得到bitmap的dc
intptr dc2 = g2.gethdc ( ) ;
//调用此api函数,实现屏幕捕获
bitblt ( dc2 , 0 , 0 , rect.width , rect.height , dc1 , 0 , 0 , 13369376 ) ;
//释放掉屏幕的dc
g1.releasehdc ( dc1 ) ;
//释放掉bitmap的dc
g2.releasehdc ( dc2 ) ;
//以jpg文件格式来保存
myimage.save ( @"c:/capture.jpg" , imageformat.jpeg );
messagebox.show ( "当前屏幕已经保存为c盘的capture.jpg文件!" ) ;
}
}
四. 总结:
本文虽然是c#在实际情况的一个应用例子,但所包含的内容相对还比较丰富。其中调用windows的api函数对广大的程序员来说都是一个比较头痛的问题,因为他涉及面比较广,不仅要掌握c#中使用结构、类型转换、安全/不安全代码,受管/不受管代码等许多知识,还要了解api函数的结构等。希望本文对你有所帮助。