高手才能解决的问题:关于C#屏幕捕捉的问题

大可山人
博客专家认证
2004-11-01 10:16:49
http://www.bobpowell.net/capture.htm
谁可以做出一个完整的例子出来,就好象QQ的屏幕捕捉一样,然后发送到服务器一样?万一不行,可以先存为一个文件,然后上传。
...全文
89 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
大可山人 2004-11-03
  • 打赏
  • 举报
回复
cancersyf(fengzhimei):
ActiveX方式如何实现呀?我对ActiveX一窍不通,哪里有相应的书或例子?
cancersyf 2004-11-02
  • 打赏
  • 举报
回复
参考--
http://www.c-sharpcorner.com/Code/2003/Dec/ScreenCapture.asp

如果你想在客户端捕捉,就只有通过ActiveX的方式了。
qqdao 2004-11-02
  • 打赏
  • 举报
回复
程序设计的关键步骤以及具体的实现方法:

   (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 ( ) ) ;
}
}


62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧