分享
 
 
 

用C#制作作屏幕捕获程序

王朝c#·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

我们已经了解了Visual Basic或者Delphi等语言是如何来实现对屏幕图象捕获的。那么对于C#来说,是如何实现这种功能的?本文就来探讨一下这个问题。

一. 程序设计开发及运行环境:

(1).微软视窗2000服务器版

(2)..Net FrameWork SDK Beta 2

二. 程序设计的关键步骤以及具体的实现方法:

(1).首先要创建一个和当前屏幕大小相同的Bitmap对象:

要实现此操作,首先就要现获得当前显示器的DC,然后根据此DC来创建Graphic对象,再由此Graphic对象产生此位图对象。这样产生的位图对象才是和当前屏幕大小相一致的。由于要获得显示器的DC,利用.Net的类库是无法实现的,这需要调用一个Windows的API函数。我们知道视窗所有API都封装在"Kernel"、"User "和"GDI"三个库中文件中:其中"Kernel",他的库名为 "KERNEL32.DLL"。"User "这个类库在Win32中名叫 "USER32.DLL"。 它主要管理全部的用户接口。譬如:窗口 、菜单 、对话框 、图标等等。"GDI"(图象设备接口),它在Win32中的库名为:"GDI32.dll",要获得显示器的DC,所调用的API函数--CreateDC ( ),就被封装在此类库中。而要在C#中声明视窗的API函数需要使用.Net FrameWork SDK中的名字空间"System.Runtime.InteropServices",此名字空间提供了一系列的类来访问COM对象,和调用本地的API函数。下面是在C#中声明此函数:

[ System.Runtime.InteropServices.DllImportAttribute ( "gdi32.dll" ) ]

private static extern IntPtr CreateDC (

string lpszDriver , // 驱动名称

string lpszDevice , // 设备名称

string lpszOutput , // 无用,可以设定位"NULL"

IntPtr lpInitData // 任意的打印机数据

) ;

在C#中声明过此API函数,就可以创建和显示器大小一致的位图对象,具体实现语句如下:

IntPtr dc1 = CreateDC ( "DISPLAY" , null , null , ( IntPtr ) null ) ;

//创建显示器的DC

Graphics g1 = Graphics.FromHdc ( dc1 ) ;

//由一个指定设备的句柄创建一个新的Graphics对象

MyImage = new Bitmap ( Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Height , g1 ) ;

//根据屏幕大小创建一个与之相同大小的Bitmap对象

(2).根据此位图创建一个和其一样的Graphic对象:

通过下面代码就可以实现此功能:

Graphics g2 = Graphics.FromImage ( MyImage ) ;

(3).获得当前屏幕和位图的句柄:

获得此二个对象的句柄是为了下一步实现对当前屏幕图象的捕获,程序中实现的具体捕获的方法是把当前屏幕捕获到已经创建的位图对象中。具体实现代码如下:

//获得屏幕的句柄

IntPtr dc3 = g1.GetHdc ( ) ;

//获得位图的句柄

IntPtr dc2 = g2.GetHdc ( ) ;

//把当前屏幕捕获到位图对象中

(4).捕获当前屏幕:

我们是通过当前屏幕保存到创建的位图对象中来实现的,具体的实现过程中是通过Windows的一个API函数--Bitblt。我想大多数程序员对此API函数一定不陌生,因为在Windows的图象编程中,会在很多地方使用到此函数。这个API函数和上面介绍的那个API函数一样,也是被封装在"GDI32.dll"中的,下面是此函数在C#中的声明:

[ System.Runtime.InteropServices.DllImportAttribute ( "gdi32.dll" ) ]

private static extern bool BitBlt (

IntPtr hdcDest , // 目标设备的句柄

int nXDest , // 目标对象的左上角的X坐标

int nYDest , // 目标对象的左上角的X坐标

int nWidth , // 目标对象的矩形的宽度

int nHeight , // 目标对象的矩形的长度

IntPtr hdcSrc , // 源设备的句柄

int nXSrc , // 源对象的左上角的X坐标

int nYSrc , // 源对象的左上角的X坐标

System.Int32 dwRop // 光栅的操作值

) ;

知道了此声明就可以实现对当前屏幕的保存了,具体如下:

BitBlt ( dc2 , 0 , 0 , Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Height , dc3 , 0 , 0 , 13369376 ) ;

(5).把当前屏幕保存到硬盘,并释放句柄:

g1.ReleaseHdc ( dc3 ) ;

//释放屏幕句柄

g2.ReleaseHdc ( dc2 ) ;

//释放位图句柄

MyImage.Save ( "c:\\MyJpeg.jpg" , ImageFormat.Jpeg ) ;

我们可以根据自己的要求把当前屏幕以不同的文件格式来保存,在本文中介绍的程序是以"jpg"文件来保存的,你可以通过修改"Save"方法的第二个参数来改变保存到硬盘的文件类型,譬如,如果第二个参数为"ImageFormat.Gif",那么你保存到硬盘的文件就为"GIF"文件了。对于其他文件格式可以参考.Net FrameWork SDK,里面有详细的介绍。

三. 用C#做Screen Capture程序的代码和运行节目:

在掌握了上面这些重要步骤后,可以得到用C#做Screen Capture程序的源代码(Capture.cs),具体如下:

using System ;

using System.Drawing ;

using System.Collections ;

using System.ComponentModel ;

using System.Windows.Forms ;

using System.Data ;

using System.Drawing.Imaging ;

using System.IO ;

//导入在程序中使用到的名称空间

public class Capture : Form

{

private System.ComponentModel.Container components = null ;

private Icon mNetTrayIcon = new Icon ( "Tray.ico" ) ;

private Bitmap MyImage = null ;

private NotifyIcon TrayIcon ;

private ContextMenu notifyiconMnu ;

public Capture ( )

{

//初始化窗体中使用到的组件

InitializeComponent ( ) ;

}

protected override void OnActivated ( EventArgs e )

{

this.Hide ( ) ;

}

[ System.Runtime.InteropServices.DllImportAttribute ( "gdi32.dll" ) ]

private static extern bool BitBlt (

IntPtr hdcDest , //目标设备的句柄

int nXDest , // 目标对象的左上角的X坐标

int nYDest , // 目标对象的左上角的X坐标

int nWidth , // 目标对象的矩形的宽度

int nHeight , // 目标对象的矩形的长度

IntPtr hdcSrc , // 源设备的句柄

int nXSrc , // 源对象的左上角的X坐标

int nYSrc , // 源对象的左上角的X坐标

System.Int32 dwRop // 光栅的操作值

) ;

[ System.Runtime.InteropServices.DllImportAttribute ( "gdi32.dll" ) ]

private static extern IntPtr CreateDC (

string lpszDriver , // 驱动名称

string lpszDevice , // 设备名称

string lpszOutput , // 无用,可以设定位"NULL"

IntPtr lpInitData // 任意的打印机数据

) ;

public void capture ( object sender , System.EventArgs e )

{

this.Visible = false ;

IntPtr dc1 = CreateDC ( "DISPLAY" , null , null , ( IntPtr ) null ) ;

//创建显示器的DC

Graphics g1 = Graphics.FromHdc ( dc1 ) ;

//由一个指定设备的句柄创建一个新的Graphics对象

MyImage = new Bitmap ( Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Height , g1 ) ;

//根据屏幕大小创建一个与之相同大小的Bitmap对象

Graphics g2 = Graphics.FromImage ( MyImage ) ;

//获得屏幕的句柄

IntPtr dc3 = g1.GetHdc ( ) ;

//获得位图的句柄

IntPtr dc2 = g2.GetHdc ( ) ;

//把当前屏幕捕获到位图对象中

BitBlt ( dc2 , 0 , 0 , Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Height , dc3 , 0 , 0 , 13369376 ) ;

//把当前屏幕拷贝到位图中

g1.ReleaseHdc ( dc3 ) ;

//释放屏幕句柄

g2.ReleaseHdc ( dc2 ) ;

//释放位图句柄

MyImage.Save ( "c:\\MyJpeg.jpg" , ImageFormat.Jpeg ) ;

MessageBox.Show ( "已经把当前屏幕保存到C:\\MyJpeg.jpg文件中!" ) ;

this.Visible = true ;

}

public void ExitSelect ( object sender , System.EventArgs e )

{

//隐藏托盘程序中的图标

TrayIcon.Visible = false ;

//关闭系统

this.Close ( ) ;

}

//清除程序中使用过的资源

public override void Dispose ( )

{

base.Dispose ( ) ;

if ( components != null )

components.Dispose ( ) ;

}

private void InitializeComponent ( )

{

//设定托盘程序的各个属性

TrayIcon = new NotifyIcon ( ) ;

TrayIcon.Icon = mNetTrayIcon ;

TrayIcon.Text = "用C#做Screen Capture程序" ;

TrayIcon.Visible = true ;

//定义一个MenuItem数组,并把此数组同时赋值给ContextMenu对象

MenuItem [ ] mnuItms = new MenuItem [ 3 ] ;

mnuItms [ 0 ] = new MenuItem ( ) ;

mnuItms [ 0 ] .Text = "捕获当前屏幕!" ;

mnuItms [ 0 ] .Click += new System.EventHandler ( this.capture ) ;

mnuItms [ 1 ] = new MenuItem ( "-" ) ;

mnuItms [ 2 ] = new MenuItem ( ) ;

mnuItms [ 2 ] .Text = "退出系统" ;

mnuItms [ 2 ] .Click += new System.EventHandler ( this.ExitSelect ) ;

mnuItms [ 2 ] .DefaultItem = true ;

notifyiconMnu = new ContextMenu ( mnuItms ) ;

TrayIcon.ContextMenu = notifyiconMnu ;

//为托盘程序加入设定好的ContextMenu对象

this.SuspendLayout ( ) ;

this.AutoScaleBaseSize = new System.Drawing.Size ( 5 , 13 ) ;

this.ClientSize = new System.Drawing.Size ( 320 , 56 ) ;

this.ControlBox = false ;

this.MaximizeBox = false ;

this.MinimizeBox = false ;

this.WindowState = System.Windows.Forms.FormWindowState.Minimized ;

this.Name = "capture" ;

this.ShowInTaskbar = false ;

this.Text = "用C#做Screen Capture程序!" ;

this.ResumeLayout ( false ) ;

}

static void Main ( )

{

Application.Run ( new Capture ( ) ) ;

}

}

四. 总结:

虽然.Net FrameWork SDK的内容十分丰富,借助他所能够实现的功能也非常强大,但对于一些底层的操作,有时还是需要借助Windows的API函数才可以实现,而实现Screen Capture的关键也就在于掌握C#中调用API函数的方法。希望通过本文,能够对你掌握在C#中的API编程有所帮助。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有