明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

使用C#制作屏幕捕捉程序

[摘要]隨著微軟.Net戰(zhàn)略的進(jìn)一步深入,各種新的技術(shù)、概念可謂層出不窮,特別是C#語言的推出,在業(yè)界產(chǎn)生了重大影響。C#是一門高效的語言,它既有VB的RAD特性,又不乏C++語言的高效性。最重要的它是基于.Net Framework的,在圖形圖像、網(wǎng)絡(luò)編程等方面有著強(qiáng)大的優(yōu)勢,所以它很可能發(fā)展成為未...

隨著微軟.Net戰(zhàn)略的進(jìn)一步深入,各種新的技術(shù)、概念可謂層出不窮,特別是C#語言的推出,在業(yè)界產(chǎn)生了重大影響。C#是一門高效的語言,它既有VB的RAD特性,又不乏C++語言的高效性。最重要的它是基于.Net Framework的,在圖形圖像、網(wǎng)絡(luò)編程等方面有著強(qiáng)大的優(yōu)勢,所以它很可能發(fā)展成為未來的主要編程語言之一。

本文通過一個實(shí)例來向大家展示一下用C#進(jìn)行圖形圖像編程的特性。實(shí)例中運(yùn)用到了GDI+編程的一些基礎(chǔ)知識,GDI+是從GDI演化而來的,是.Net環(huán)境下的新的圖形圖像編程機(jī)制。它不僅具有GDI編程的一些基本功能,而且對GDI進(jìn)行了不少擴(kuò)充,使得它功能更強(qiáng)大。在Visual Studio的以前版本中使用GDI是相當(dāng)復(fù)雜的,而且工作量十分大,F(xiàn)在在GDI+中,微軟已經(jīng)幫我們解決了許多問題,因而使用GDI+進(jìn)行圖形圖像編程將變得非常容易。不過要指出的是:用GDI編程雖然較復(fù)雜,卻可以完成幾乎所有的復(fù)雜功能,比如在實(shí)例中用GDI可以輕易做一個屏幕捕捉程序。那么,現(xiàn)在我們在GDI+是否也能完成同樣的功能呢?答案是肯定的。正因?yàn)镚DI+是從GDI演化而來的,我們只要在GDI+中調(diào)用GDI的一些功能就行了。

C#有一個特性,那就是它允許你運(yùn)用任何預(yù)先已經(jīng)完成的動態(tài)連接庫文件(*.dll),其中當(dāng)然包括了gdi32.dll這個文件。該文件包含了進(jìn)行GDI編程所需的基本類庫、函數(shù)、方法等。這樣,我們在GDI+編程機(jī)制下也同樣可以享受GDI為我們留下的寶貴資源。具體導(dǎo)入的方法如下:

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

在GDI中做屏幕捕捉程序的話,就要用到上下文設(shè)備(device context)了。在程序中,我們用它獲得屏幕圖形并將它寫入內(nèi)存中的一個位圖中,實(shí)現(xiàn)的方法就是調(diào)用BitBlt()函數(shù)。同樣在GDI+中實(shí)現(xiàn)的原理是一樣的,下面給出了GDI+中的外部聲明函數(shù)(用C#語言描述):

privatestaticexternbool BitBlt(

IntPtr hdcDest, //目的上下文設(shè)備的句柄

int nXDest, //目的圖形的左上角的x坐標(biāo)

int nYDest, //目的圖形的左上角的y坐標(biāo)

int nWidth, //目的圖形的矩形寬度

int nHeight, //目的圖形的矩形高度

IntPtr hdcSrc, //源上下文設(shè)備的句柄

int nXSrc, //源圖形的左上角的x坐標(biāo)

int nYSrc, //源圖形的左上角的x坐標(biāo)

System.Int32 dwRop //光柵操作代碼

);

為了能在GDI+中調(diào)用GDI,我們還需要取得上下文設(shè)備的鉤子。在GDI+中有一個方法就提供了這種操作的具體實(shí)現(xiàn):

IntPtr dc1 = aGraphicsObject.GetHdc();


在取得了源上下文設(shè)備以及目的上下文設(shè)備的句柄后,我們就可以在上面的BitBlt()函數(shù)運(yùn)用它們(作為參數(shù)),實(shí)現(xiàn)圖像創(chuàng)建功能了。在圖像創(chuàng)建后,還必須釋放源上下文設(shè)備以及目的上下文設(shè)備資源。 這樣,基本的原理就已介紹完畢,總的來說實(shí)現(xiàn)的原理還是比較簡單的。下面就是實(shí)現(xiàn)實(shí)例的具體步驟:

1. 獲得一個對應(yīng)于屏幕上窗體的圖形對象

2. 創(chuàng)建一個大小為窗體客戶區(qū)大小的位圖文件

3. 獲得窗體的上下文設(shè)備

4. 獲得位圖文件的上下文設(shè)備

5. 把屏幕上的窗體寫入位圖中

6. 釋放窗體的上下文設(shè)備

7. 釋放位圖文件的上下文設(shè)備

8. 將圖像保存為一個jpeg格式的文件

工程步驟:

1. 新建一個C#的工程,不妨命名為“FormCapture”,圖示如下:




2. 布置主窗體:

在窗體上添加一個圖片框(pictureBox)控件以及一個按鈕(button)控件即可。將主窗體的Text屬性設(shè)置為“屏幕捕捉程序”;將圖片框的Image屬性設(shè)置為一個圖形文件;將按鈕的Text屬性設(shè)置為“屏幕捕捉”即可。(當(dāng)然讀者可以添加自己需要的控件來布置主窗體)圖示如下:


3. 代碼編寫:

先在代碼文件中添加上面介紹的BitBlt函數(shù)的外部聲明。

再添加按鈕的OnClick事件處理函數(shù),該函數(shù)就是實(shí)現(xiàn)屏幕捕捉的主要部分了。函數(shù)如下:

private void button1_Click(object sender, System.EventArgs e)

{

Graphics g1 = this.CreateGraphics();//獲得窗體圖形對象

Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);

Graphics g2 = Graphics.FromImage(MyImage);//創(chuàng)建位圖圖形對象

IntPtr dc1 = g1.GetHdc();//獲得窗體的上下文設(shè)備

IntPtr dc2 = g2.GetHdc();//獲得位圖文件的上下文設(shè)備

BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);//寫入到位圖

g1.ReleaseHdc(dc1);//釋放窗體的上下文設(shè)備

g2.ReleaseHdc(dc2);//釋放位圖文件的上下文設(shè)備

MyImage.Save(@"c:\Captured.jpg", ImageFormat.Jpeg);//保存為jpeg文件

MessageBox.Show("保存圖片結(jié)束!");

}


4.到此為止,程序已經(jīng)做完了。按Ctrl+F5可以試試效果如下圖:




圖片已經(jīng)保存好了,看看屏幕捕捉的結(jié)果吧(如下圖)!




不過,這個程序只是捕捉到了程序自身的客戶區(qū),所以功能有限。當(dāng)然,你也可以試著做個捕捉屏幕任何位置的程序!你只要改變源圖像的寬度和高度即可,而這個寬度和高度當(dāng)然可以由用戶來選定。這樣,一個自制的屏幕捕捉程序就出爐了。

從上面的實(shí)例中,我們不難發(fā)現(xiàn)用C#編程實(shí)現(xiàn)一些基本功能還是非常容易的,真可謂是高效開發(fā)的好工具。所以,筆者希望有更多的人加入C#的行列,開發(fā)出更實(shí)用、更完善的軟件。 完整代碼:

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Drawing.Imaging;


namespace FormCapture

{

///

/// Summary description for Form1.

///

public class Form1 : System.Windows.Forms.Form

{

private System.Windows.Forms.PictureBox pictureBox1;

private System.Windows.Forms.Button button1;

///

/// Required designer variable.

///

private System.ComponentModel.Container components = null;



public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();


//

// TODO: Add any constructor code after InitializeComponent call

//

}


///

/// Clean up any resources being used.

///

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}



#region Windows Form Designer generated code

///

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

///

private void InitializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));

this.button1 = new System.Windows.Forms.Button();

this.pictureBox1 = new System.Windows.Forms.PictureBox();

this.SuspendLayout();

//

// button1

//

this.button1.BackColor = System.Drawing.SystemColors.ActiveBorder;

this.button1.ForeColor = System.Drawing.SystemColors.ControlDarkDark;

this.button1.Location = new System.Drawing.Point(272, 19);

this.button1.Name = "button1";

this.button1.Size = new System.Drawing.Size(72, 27);

this.button1.TabIndex = 4;

this.button1.Text = "屏幕捕捉";

this.button1.Click += new System.EventHandler(this.button1_Click);

//

// pictureBox1

//

this.pictureBox1.Image = ((System.Drawing.Bitmap)(resources.GetObject("pictureBox1.Image")));

this.pictureBox1.Location = new System.Drawing.Point(16, 16);

this.pictureBox1.Name = "pictureBox1";

this.pictureBox1.Size = new System.Drawing.Size(240, 224);

this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;

this.pictureBox1.TabIndex = 0;

this.pictureBox1.TabStop = false;

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

this.ClientSize = new System.Drawing.Size(358, 255);

this.Controls.AddRange(new System.Windows.Forms.Control[] {

this.button1,

this.pictureBox1});

this.KeyPreview = true;

this.Name = "Form1";

this.Text = "屏幕捕捉程序";

this.ResumeLayout(false);



}

#endregion



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

private static extern bool BitBlt(

IntPtr hdcDest, //目的DC的句柄

int nXDest, //目的圖形的左上角的x坐標(biāo)

int nYDest, //目的圖形的左上角的y坐標(biāo)

int nWidth, //目的圖形的矩形寬度

int nHeight, //目的圖形的矩形高度

IntPtr hdcSrc, //源DC的句柄

int nXSrc, //源圖形的左上角的x坐標(biāo)

int nYSrc, //源圖形的左上角的x坐標(biāo)

System.Int32 dwRop //光柵操作代碼

);



private void button1_Click(object sender, System.EventArgs e)

{

Graphics g1 = this.CreateGraphics();//獲得窗體圖形對象

Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);

Graphics g2 = Graphics.FromImage(MyImage);//創(chuàng)建位圖圖形對象

IntPtr dc1 = g1.GetHdc();//獲得窗體的上下文設(shè)備

IntPtr dc2 = g2.GetHdc();//獲得位圖文件的上下文設(shè)備

BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);//寫入到位圖

g1.ReleaseHdc(dc1);//釋放窗體的上下文設(shè)備

g2.ReleaseHdc(dc2);//釋放位圖文件的上下文設(shè)備

MyImage.Save(@"c:\Captured.jpg", ImageFormat.Jpeg);//保存為jpeg文件

MessageBox.Show("保存圖片結(jié)束!");

}



///

/// The main entry point for the application.

///

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

}

} (出處:eNet硅谷動力)