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

2016-02-19 16:57 18 1 收藏

想不想get新技能酷炫一下,今天图老师小编就跟大家分享个简单的用制作C#作屏幕捕获程序教程,一起来看看吧!超容易上手~

【 tulaoshi.com - 编程语言 】

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

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

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

  (2)..Net FrameWork SDK Beta 2

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

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

  (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 ) ;//创建显示器的DCGraphics 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 ( ) ;//把当前屏幕捕获到位图对象中

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  (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 ) ;//创建显示器的DCGraphics 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 ( ) ) ;}}

  下图是此代码编译后的运行界面:

  图01:用C#做Screen Capture程序的源代码

  四. 总结:

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

来源:http://www.tulaoshi.com/n/20160219/1613680.html

延伸阅读
前言: 因为本程序是木马程序,所以在介绍之前有一些木马构成的基本知识事先说明,因为下面很多地方会提到这些内容。一个完整的木马系统由硬件部分,软件部分和具体连接部分组成。这里主要对软件部分介绍,它主要有控制端程序、木马程序(后台服务程序)、木马配制程序组成。控制端用以远程控制服务端的程序;木马程序是潜入服务端内...
C# Builder是Borland公司推出的又一款基于.NET的开发工具。我们下面就用它做个简单的屏幕保护程序。屏幕保护程序是以scr为扩展名的标准Windows可执行程序。屏幕保护程序不仅可以延长显示器的使用寿命,还可以保护私人信息。本文向大家介绍一个用C# Builder编写的一个动态文本及图形的屏幕保护程序。 具体实现步骤 1)在C# Builder下新建...
如何于Windows Form控件中捕捉按键向来是许多程序员所关心的课题,基本上,标准的KeyUp、KeyDown与KeyPress事件就足以去捕捉并处理按键。然而问题在于,并非所有的控件会在所有的情况下为所有的按键操作产生这些事件。 图CH8_DemoForm004.cs运行画面 如果您希望不管控件的状况如何,都能够顺利地捕捉Windows Form控件中的...
终于有时间可以学点新东西了,今天大略看了一下有关asp+的资料,并且写了个域名查询的页面,感觉很不错,asp+比起 asp来进步实在是太大了,尽管用asp+组件也能实现域名查询的功能,并且前几天我用vc写过这么个组件,但用asp+简单方 便多了。好了,废话少提,看源码吧。 <% @Page Language="C#" % <% @Assembly Name="System.Net" % <...
作不规则窗体涉及到API的调用和大量的编程,是件很复杂的事情。下面我们可以使用Borland C# Builder轻松的实现一个不规则窗体,以下面用一个示例来讲述其制作过程。 一.准备不规则窗体位图 二.窗体的设置 三.代码的完成 一.准备不规则窗体位图 为了方便起见,我们随便找几个别的软件用的Skin。 这里使用金山...

经验教程

440

收藏

22
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部