用c#來捕獲屏幕(1)
[ 作者: 王天 添加時間: 2002-3-29 14:37:15 ]
來源: 賽迪網(wǎng) www.ccidnet.com
其實用c??梢酝瓿善渌绦蛟O(shè)計語言的幾乎全部功能,當然c#自身的許多獨到的功能,是其他程序語言所無法實現(xiàn)的,這就是c#越來越受到廣大程序員的喜歡的原因。本文就來探討一下用c#去實現(xiàn)一個重要的功能,用他來編寫一個捕獲當前屏幕地程序。通過這個程序,我們將了解到c#是如何調(diào)用api函數(shù),和.net框架中的類庫內(nèi)容是多么地豐富,功能是多么地強大。
一. 程序設(shè)計開發(fā)及運行環(huán)境:
(1).微軟視窗2000服務(wù)器版
(2)..net framework sdk beta 2
二. 程序設(shè)計的關(guān)鍵步驟:
要想完成這個功能,首先要了解一下在c#中如何調(diào)用api(應(yīng)用程序接口)函數(shù)。雖然在.net框架中已經(jīng)提供了許多類庫,這些類庫的功能也十分強大,但對于一些windows底層編程來說,還是要通過調(diào)用這些api函數(shù)才可以實現(xiàn)。所有api都在"kernel"、"user "和"gdi"三個庫中得以運行:其中"kernel",他的庫名為 "kernel32.dll", 他主要用于產(chǎn)生與操作系統(tǒng)之間的關(guān)聯(lián),譬如:程序加載,上下文選擇,文件輸入輸出,內(nèi)存管理等等。"user "這個類庫在win32中名叫 "user32.dll"。 它允許管理全部的用戶接口。譬如:窗口 、菜單 、對話框 、圖標等等。"gdi"(圖象設(shè)備接口),它在win32中的庫名為:"gdi32.dll",它是圖形輸出庫。使用gdi windows"畫"出窗口、菜單以及對話框等;它能創(chuàng)建圖形輸出;它也能保存圖形文件。由于本文所涉及到是圖象問題,所有調(diào)用的類庫是"gdi32.dll"。在本文程序中我們使用的api函數(shù)是"bitblt",這個函數(shù)對于廣大程序員來說,一定不感覺到陌生,因為在圖象處理方面他的用途是相對廣的,在用其他程序語言編程中,時常也要和他打交道。在.net framework sdk中有一個名字空間"system.runtime.interopservices",此名字空間提供了一系列的類來訪問com對象,和調(diào)用本地的api函數(shù)。下面是在c#中聲明此函數(shù):
[ 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 // 光柵的處理數(shù)值
) ;
通過上面這個聲明,就可以在下面的代碼中使用此函數(shù)了。
下面是用c#做屏幕捕獲程序的具體實現(xiàn)步驟:
(1).首先要獲得當前屏幕的graphic對象,通過以下代碼可以實現(xiàn):
graphics g1 = this.creategraphics ( ) ;
(2).創(chuàng)建一個bitmap對象,并且這個bitmap對象的大小是當前屏幕:
首先要獲得當前屏幕的大小,通過名字空間"system.windows.forms"中的"screen"類的getworkingarea()方法,可以實現(xiàn)。下面是得到當前屏幕的長(height)和寬(width):
rectangle rect = new rectangle ( ) ;
rect = screen.getworkingarea ( this ) ;
"屏幕寬"= rect.width ;
"屏幕長"= rect.height ;
至此就可以得到我們想要的bitmap了,通過下列語句可以實現(xiàn):
image myimage = new bitmap ( rect.width , rect.height , g1 ) ;
//創(chuàng)建以屏幕大小為標準的位圖
(3).獲得當前屏幕和此bitmap對象的dc,這可以通過下列語句實現(xiàn):
//得到屏幕的dc
intptr dc1 = g1.gethdc ( ) ;
//得到bitmap的dc
intptr dc2 = g2.gethdc ( ) ;
(4).調(diào)用api函數(shù),把當前屏幕拷貝到創(chuàng)建的bitmap中:
bitblt ( dc2 , 0 , 0 , rect.width , rect.height , dc1 , 0 , 0 , 13369376 ) ;
(5).釋放當前屏幕和此bitmap對象的dc,通過下面代碼可以實現(xiàn):
//釋放掉屏幕的dc
g1.releasehdc ( dc1 ) ;
//釋放掉bitmap的dc
g2.releasehdc ( dc2 ) ;
(6).保存bitmap對象,形成jpg圖片:
myimage.save ( @"c:/capture.jpg" , imageformat.jpeg );
當然你也可以根據(jù)自己的需要,把屏幕以其他圖片的格式來保存,如果你想把圖片保存為位圖文件,可以把"imageformat.jpeg"改換成"imageformat.bmp";想把圖片保存為gif文件,就把"imageformat.jpeg"改換成"imageformat.gif"。你可以保存的文件類型大概有十多種,這里就不一一介紹了,當然你也要相應(yīng)改變保存文件的后綴。
三. 用c#來捕獲屏幕的源程序代碼(capture.cs):
了解上面的這些步驟的實現(xiàn)方法,就可以得到用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函數(shù)
[ 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 // 光柵的處理數(shù)值
) ;
static void main ( )
{
application.run ( new form1 ( ) ) ;
}
private void button1_click ( object sender , system.eventargs e )
{
//獲得當前屏幕的大小
rectangle rect = new rectangle ( ) ;
rect = screen.getworkingarea ( this ) ;
//創(chuàng)建一個以當前屏幕為模板的圖象
graphics g1 = this.creategraphics ( ) ;
//創(chuàng)建以屏幕大小為標準的位圖
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 ( ) ;
//調(diào)用此api函數(shù),實現(xiàn)屏幕捕獲
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 ( "當前屏幕已經(jīng)保存為c盤的capture.jpg文件!" ) ;
}
}
四. 總結(jié):
本文雖然是c#在實際情況的一個應(yīng)用例子,但所包含的內(nèi)容相對還比較豐富。其中調(diào)用windows的api函數(shù)對廣大的程序員來說都是一個比較頭痛的問題,因為他涉及面比較廣,不僅要掌握c#中使用結(jié)構(gòu)、類型轉(zhuǎn)換、安全/不安全代碼,受管/不受管代碼等許多知識,還要了解api函數(shù)的結(jié)構(gòu)等。希望本文對你有所幫助。