2024年2月9日发(作者:)
事件简介:
任何进行过图形用户界面开发的编程人员都会知道事件的概念。当用户在使用程序的时候,用户必然要和程序进行一定的交互。比如当用户点击窗体上的一个按钮后,程序就会产生该按钮被点击的事件,并通过相应的事件处理函数来响应用户的操作。这样用户的直观感觉就是程序执行了我要求的任务了。当然,事件并不一定是在和用户交互的情况下才会产生的,系统的内部也会产生一些事件并请求处理的,比如时钟事件就是一个很好例子。不过要介绍C#中的事件处理机制(扩展到更广的范围便是整个.Net框架),我们首先得明白一个叫"委托"的概念。
C#中的委托:
委托,顾名思义,就是中间代理人的意思。C#中的委托允许你将一个对象中的方法传递给另一个能调用该方法的类的某个对象。你可以将类A中的一个方法m(被包含在某个委托中了)传递给一个类B,这样类B就能调用类A中的方法m了。同时,你还可以以静态(static)的方式或是实例(instance)的方式来传递该方法。所以这个概念和C++中的以函数指针为参数形式调用其他类中的方法的概念是十分类似的。
委托的概念首先是在Visual J++中被提出来的,现在C#也应用了委托的概念,这也可谓是"拿来主义"吧。C#中的委托是通过继承te中的一个类来实现的,下面是具体的步骤:
1. 声明一个委托对象,其参数形式一定要和你想要包含的方法的参数形式一致。
2. 定义所有你要定义的方法,其参数形式和第一步中声明的委托对象的参数形式必须相同。
3. 创建委托对象并将所希望的方法包含在该委托对象中。
4. 通过委托对象调用包含在其中的各个方法。
以下的C#代码显示了如何运用以上的四个步骤来实现委托机制的:
using System;
file://步骤1: 声明一个委托对象
public delegate void MyDelegate(string input);
file://步骤2::定义各个方法,其参数形式和步骤1中声明的委托对象的必须相同
class MyClass1{
public void delegateMethod1(string input){
ine(
"This is delegateMethod1 and the input to the method is {0}",
input);
}
public void delegateMethod2(string input){
ine(
"This is delegateMethod2 and the input to the method is {0}",
input);
}
}
file://步骤3:创建一个委托对象并将上面的方法包含其中
class MyClass2{
public MyDelegate createDelegate(){
MyClass1 c2=new MyClass1();
MyDelegate d1 = new MyDelegate(teMethod1);
MyDelegate d2 = new MyDelegate(teMethod2);
MyDelegate d3 = d1 + d2;
return d3;
}
}
file://步骤4:通过委托对象调用包含在其中的方法
class MyClass3{
public void callDelegate(MyDelegate d,string input){
d(input);
}
}
class Driver{
static void Main(string[] args){
MyClass2 c2 = new MyClass2();
MyDelegate d = Delegate();
MyClass3 c3 = new MyClass3();
legate(d,"Calling the delegate");
}
}
C#中的事件处理函数:
C#中的事件处理函数是一个具有特定参数形式的委托对象,其形式如下:
public delegate void MyEventHandler(object sender, MyEventArgs e);
其中第一个参数(sender)指明了触发该事件的对象,第二个参数(e)包含了在事件处理函数中可以被运用的一些数据。上面的MyEventArgs类是从EventArgs类继承过来的,后者是一些更广泛运用的类,如MouseEventArgs类、ListChangedEventArgs类等的基类。对于基于GUI的事件,你可以运用这些更广泛的、已经被定义好了的类的对象来完成处理;而对于那些基于非GUI的事件,你必须要从EventArgs类派生出自己的类,并将所要包含的数据传递给委托对象。下面是一个简单的例子:
public class MyEventArgs EventArgs{
public string m_myEventArgumentdata;
}
在事件处理函数中,你可以通过关键字event来引用委托对象,方法如下:
public event MyEventHandler MyEvent;
现在,我们来创建两个类,通过这两个类我们可以知道C#完成事件处理的机制是如何工作的。在我们的实例中,A类将提供事件的处理函数,并在步骤3中创建委托对象同时将事件处理函数包含在其中,同上所述,事件处理函数的参数形式必须和委托对象的参数形式相一致。然后,A类将委托对象传递给B类。当B类中的事件被触发后,A类中的事件处理函数就相应的被调用了。下面是示例代码:
using System;
file://步骤1:声明委托对象
public delegate void MyHandler1(object sender,MyEventArgs e);
public delegate void MyHandler2(object sender,MyEventArgs e);
file://步骤2:创建事件处理函数的方法
class A{
public const string m_id="Class A";
public void OnHandler1(object sender,MyEventArgs e){
ine("I am in OnHandler1 and MyEventArgs is {0}",
e.m_id);
}
public void OnHandler2(object sender,MyEventArgs e){
ine("I am in OnHandler2 and MyEventArgs is {0}",
e.m_id);
}
file://步骤3:创建委托对象,并事件处理函数包含在其中同时设置好将要触发事件的对象
public A(B b){
MyHandler1 d1=new MyHandler1(OnHandler1);
MyHandler2 d2=new MyHandler2(OnHandler2);
1 +=d1;
2 +=d2;
}
}
file://步骤4:通过委托对象(也就是触发事件)来调用被包含的方法
class B{
public event MyHandler1 Event1;
public event MyHandler2 Event2;
public void FireEvent1(MyEventArgs e){
if(Event1 != null){
Event1(this,e);
}
}
public void FireEvent2(MyEventArgs e){
if(Event2 != null){
Event2(this,e);
}
}
}
public class MyEventArgs EventArgs{
public string m_id;
}
public class Driver{
public static void Main(){
B b= new B();
A a= new A(b);
MyEventArgs e1=new MyEventArgs();
MyEventArgs e2=new MyEventArgs();
e1.m_id ="Event args for event 1";
e2.m_id ="Event args for event 2";
ent1(e1);
ent2(e2);
}
}
C#中的GUI的事件处理函数:
完成GUI下的事件处理函数的基本方法和上面介绍的并没有什么多大区别,下面我们就通过上面的方法来完成一个简单的实例程序。该实例程序的主类MyForm类是从Form类继承过来的。通过观察整段代码和相关的注解,你可以发现我们并没有给它声明委托对象并通过event关键字来引用该委托对象,那是因为GUI控件早就帮我们做好了该项工作,其委托对象是andler。然而,我们还是要为各个控件定义方法(也就是事件的处理函数)并将它们包含在创建好的委托对象(andler)中。那样,在用户和程序进行交互的时候,相应的事件处理函数就会被触发。具体代码如下:
using System;
using g;
using tions;
using entModel;
using ;
using ;
public class MyForm Form{
private Button m_nameButton;
private Button m_clearButton;
private Label m_nameLabel;
private Container m_components = null;
public MyForm(){
initializeComponents();
}
private void initializeComponents(){
m_nameLabel=new Label();
m_nameButton = new Button();
m_clearButton = new Button();
SuspendLayout();
m_on=new Point(16,16);
m_="Click NAME button, please";
m_=new Size(300,23);
m_on=new Point(16,120);
m_=new Size(176, 23);
m_="NAME";
file://创建委托对象,包含方法并将委托对象赋给按钮的Click事件
m_ += new andler(NameButtonClicked);
m_on=new Point(16,152);
m_=new Size(176,23);
m_="CLEAR";
file://创建委托对象,包含方法并将委托对象赋给按钮的Click事件
m_ += new andler(ClearButtonClicked);
Size = new Size(292, 271);
ge(new Control[] {m_nameLabel,
m_nameButton,
m_clearButton});
Layout(false);
}
file://定义方法(事件的处理函数),其参数形式必须和委托对象的一致
private void NameButtonClicked(object sender, EventArgs e){
m_=
"My name is john, please click CLEAR button to clear it";
}
private void ClearButtonClicked(object sender,EventArgs e){
m_="Click NAME button, please";
}
public static void Main(){
(new MyForm());
}
}
小结:
这样,我就向大家初步介绍了C#中的事件处理机制。通过本文,希望能使大家对C#中的事件处理机制乃至整个.Net框架的事件处理机制有个大致的了解,同时还希望大家能明确"委托"这样的较新的概念。最后还要指出的是,如果你是在用Visual Studio的集成开发环境进行开发的话,那么各个GUI控件会自动帮你生成相关的许多代码,但是知道了其内部的工作机制的话总归是有很大益处的,对吗?
归类于: 程序学习 — 长笑 @ 11:34 am 评论(0)
[转载]浅析C#中的图形编程
像Java一样,C#提供了一整套相当丰富的类库、方法以及事件以供开发者使用。C#还引入了GDI+,它是由GDI演变而来的,具有比GDI更强大的功能而且简化了程序员的编程工作。所以开发者运用这些,就可以很方便的开发出具有强大图形图像功能的应用程序了。本文,笔者就通过一些实例像读者介绍一下C#中的图形编程的基本知识。
简单实例:
首先,让我们从例子开始,以下是一个最简单的实例:
using System;
using ;
using g;
public class Hello:Form {
public Hello() {
+= new PaintEventHandler(f1_paint);
}
private void f1_paint(object sender,PaintEventArgs e) {
Graphics g = cs;
ring("你好,C#!",new Font("Verdana",20),
new SolidBrush(),40,40);
ctangle(new Pen(,3),20,20,150,100);
}
public static void Main() {
(new Hello());
}
}
在上面的实例中,我们用到了一个方法:DrawString(),它带有5个参数。同时,我们发现在运用DrawString()方法以前,我们先创建了一个Graphics类型的对象g=cs,这就说明了在运用任何图形类的方法以前我们必须先创建该类的一个实例化对象。在DrawString()方法后,我们用到了DrawRectangle()方法,其实我们还可以运用其他的方法来画椭圆或是多边形等等。第一个实例还是相当简单易懂的,不是吗?
变换图形的度量单位:
在图形编程中,默认的图形度量单位是象素。不过,你可以通过修改PageUnit属性来修改图形的度量单位,可以是英寸或是毫米等。实现方法如下:
Graphics g = cs;
it =
操作颜色选择对话框:
在实际运用特别是图形图像编程过程中,我们可能会经常碰到颜色选择对话框(以及下面要提到的字体选择对话框)。使用颜色选择对话框,我们可以让用户来选择系统预定的颜色以及用户自定义的颜色。在使用颜色选择对话框之前,我们必须先创建一个ColorDialog类型的对象:
ColorDialog cd = new ColorDialog();
然后,我们就可以用ShowDialog()方法来显示颜色选择对话框了。之后,就可以通过调用
用户的颜色选择进行相关的图形操作了。
以下,我给大家一个实例。该实例中有一个按钮和一个文本框,通过点击按钮可以调出颜色选择对话框,根据用户的颜色选择就可以设置文本框的背景颜色了。
using System;
using g;
using ;
public class Clr:Form{
Button b1 = new Button();
TextBox tb = new TextBox();
ColorDialog clg = new ColorDialog();
public Clr(){
+= new EventHandler(b1_click);
= "选择颜色";
on = new Point(50,50);
(b1);
(tb);
}
public void b1_click(object sender, EventArgs e){
alog();
lor = ;
}
public static void Main() {
(new Clr());
}
}
操作字体选择对话框:
字体是图形编程的一个重要组成部分,通过设置不同的字体,你可以在程序中达到不同的视觉效果。和以上的颜色选择对话框的创建差不多,你可以很方便地创建一个字体选择对话框,并通过它来让用户选择其所需的字体。
下面同样给出一个实例,这个实例和上面的实例差不多,只是用来字体选择对话框代替了原来的颜色选择对话框,最后是根据用户的字体选择来设置文本框的字体。
using System;
using g;
using ;
public class Fonts:Form {
Button b1 = new Button();
TextBox tb = new TextBox();
FontDialog flg = new FontDialog();
public Fonts() {
+= new EventHandler(b1_click);
= "选择字体";
on = new Point(50,50);
(b1);
(tb);
}
public void b1_click(object sender, EventArgs e) {
alog();
me = ;
}
public static void Main() {
(new Fonts());
}
}
使用g2D名字空间:
如果你有一些图形图像编程的经验,那么你一定知道画笔和画刷的概念。它们在图形编程有非常广泛的运用。g2D名字空间提供了相当强大的功能,能让开发者很容易地操作画笔以及画刷对象。比如,你可以通过设置画笔的DashStyle属性(有Dash、DashDot、Solid等风格)来确定直线的风格。同样,通过运用SolidBrush、HatchBrush、GradientBrush等画笔你可以很轻易地修改被填充区域的外观。比如,你可以用SolidBrush将一个矩形区域用许许多多不同粗细的直线来填充。那么,我们在什么时候运用画笔和画刷呢?就像上面的例子中那样,通常一个图形轮廓(运用DrawXXX()方法)是用画笔对象来实现的,而一个填充区域(运用FillXXX()方法)则是用画刷对象来实现的。
使用画笔对象:
在下面的实例中,我们用到了g2D名字空间。实例中我们用画笔以不同的风格画了直线、椭圆、馅饼图形、多边形等图形。
using System;
using ;
using g;
using g2D;
public class Drawgra:Form {
public Drawgra() {
= "运用画笔示例";
= new Size(450,400);
+= new PaintEventHandler(Draw_Graphics);
}
public void Draw_Graphics(object sender,PaintEventArgs e) {
Graphics g = cs;
Pen penline = new Pen(,5);
Pen penellipse = new Pen(,5);
Pen penpie = new Pen(,3);
Pen penpolygon = new Pen(,4);
/*DashStyle有Dash、DashDot、DashDotDot、Dot、Solid等风格*/
//以Dash风格画一条直线
yle = ;
ne(penline,50,50,100,200);
//以DashDotDot风格画一个椭圆
yle = tDot;
lipse(penellipse,15,15,50,50);
//以Dot风格画一个馅饼图形
yle = ;
e(penpie,90,80,140,40,120,100);
//以Solid风格画一个多边形
lygon(penpolygon,new Point[]{
new Point(30,140),
new Point(270,250),
new Point(110,240),
new Point(200,170),
new Point(70,350),
new Point(50,200)});
}
public static void Main() {
(new Drawgra());
}
}
使用画刷对象:
画刷对象是用特定的颜色、模式或是图像来填充一块区域的。总共有四种类型的画刷:SolidBrush(默认的画刷)、HatchBrush、GradientBrush以及TexturedBrush。下面,我们分别给出实例来进行介绍。
1、运用SolidBrush:
using System;
using ;
using g;
using g2D;
public class Solidbru:Form {
public Solidbru() {
= "运用SolidBrush示例";
+= new PaintEventHandler(Fill_Graph);
}
public void Fill_Graph(object sender,PaintEventArgs e) {
Graphics g = cs;
//创建一把SolidBrush并用它来填充一个矩形区域
SolidBrush sb = new SolidBrush();
ctangle(sb,50,50,150,150);
}
public static void Main() {
(new Solidbru());
}
}
2、运用HatchBrush:
using System;
using ;
using g;
using g2D;
public class Hatchbru:Form {
public Hatchbru() {
= "运用HatchBrush示例";
+= new PaintEventHandler(Fill_Graph);
}
public void Fill_Graph(object sender,PaintEventArgs e) {
Graphics g = cs;
//创建一把HatchBrush并用它来填充一个矩形区域
/*该画刷的HatchStyle有DiagonalCross、
ForwardDiagonal、Horizontal、 Vertical、 Solid等不同风格 */
HatchStyle hs = ;
HatchBrush sb = new HatchBrush(hs,,);
ctangle(sb,50,50,150,150);
}
public static void Main() {
(new Hatchbru());
}
} 3、运用GradientBrush:
GradientBrush又可分为LinearGradientBrush和PathGradientBrush两种,从它们的名称我们可以知道前者是线性渐变的,而后者则是路径渐变的,因而能创造出更复杂和完美的效果。下面我就给大家分别举例:
1)、运用LinearGradientBrush:
using System;
using ;
using g;
using g2D;
public class LinearGradientbru:Form {
public LinearGradientbru() {
= "运用LinearGradientBrush示例";
+= new PaintEventHandler(Fill_Graph);
}
public void Fill_Graph(object sender,PaintEventArgs e) {
Rectangle r = new Rectangle(500, 300, 100, 100);
LinearGradientBrush lb = new LinearGradientBrush(r, , ,
rdDiagonal);
ctangle(lb, r);
}
public static void Main() {
(new LinearGradientbru());
}
}
所得图形如下:
2)、运用PathGradientBrush:
using System;
using ;
using g;
using g2D;
public class PathGradientbru:Form {
public PathGradientbru() {
= "运用PathGradientBrush示例";
+= new PaintEventHandler(Fill_Graph);
}
public void Fill_Graph(object sender,PaintEventArgs e) {
nderingHint = iased;
ctangle(backgroundBrush, ClientRectangle);
ctangle(new SolidBrush(gb(180, )), ClientRectangle);
//先设置好一个路径
GraphicsPath path = new GraphicsPath(new Point[] {
new Point(40, 140),
new Point(275, 200),
new Point(105, 225),
new Point(190, 300),
new Point(50, 350),
new Point(20, 180),
}, new byte[] {
(byte),
(byte),
(byte),
(byte),
(byte),
(byte),
});
//创建一把PathGradientBrush
PathGradientBrush pgb = new PathGradientBrush(path);
//设置画刷的周围颜色
ndColors = new Color[] {
,
,
,
,
,
,
};
//用画刷进行填充
th(pgb, path);
}
public static void Main() {
(new PathGradientbru());
}
}
所得图形如下:
4、运用TexturedBrush:
using System;
using ;
using g;
using g2D;
public class Texturedbru:Form {
Brush bgbrush;
public Texturedbru() {
//创建一幅图像以供填充椭圆的背景用
Image bgimage = new Bitmap("");
bgbrush = new TextureBrush(bgimage);
+=new PaintEventHandler(Text_bru);
}
public void Text_bru(object sender,PaintEventArgs e) {
Graphics g = cs;
lipse(bgbrush,50,50,500,300);
}
public static void Main() {
(new Texturedbru());
}
}
使用图像:
图像在图形编程中经常要用到的,其对用户界面的作用也是非常明显的。在以前的编程过程中,对图像的操作细节是相当繁琐的而且很容易出错。现在,在GDI+下面,你可以用C#语言很容易的完成你所希望的图像编程。
很简单,你只要通过以下步骤就可以实现图像的编程。
1、 创建一个位图类对象如下:
Image img = new Bitmap("");
2、 在DrawImage()方法中运用上述对象:
age(img,20,20,100,90);
至于使用图像的实例,限于篇幅,我就不再这里介绍了。相信大家能很容易地完成一个运用图像的实例的。
总结:
在这篇文章中,我主要用到了两个非常核心的名字空间:一个是g、一个是g2D。有了它们,我们就可以很方便的调用其中的方法、属性来实现以往进行图形编程需要付出很大代价才能完成的任务,这不能不说是GDI+给我们带来的优点。所以,掌握好GDI+,我相信你的图形编程能力会更上一层楼的。
归类于: 程序学习 — 长笑 @ 11:32 am 评论(0)
[转载]用C#制作屏幕捕获程序
一. 程序设计开发及运行环境:
(1).微软视窗2000服务器版
(2)..Net FrameWork SDK Beta 2
二. 程序设计的关键步骤以及具体的实现方法:
(1).首先要创建一个和当前屏幕大小相同的Bitmap对象:
要实现此操作,首先就要现获得当前显示器的DC,然后根据此DC来创建Graphic对象,再由此Graphic对象产生此位图对象。这样产生的位图对象才是和当前屏幕大小相一致的。由于要获得显示器的DC,利用.Net的类库是无法实现的,这需要调用一个Windows的API函数。我们知道视窗所有API都封装在"Kernel"、"User "和"GDI"三个库中文件中:其中"Kernel",他的库名为 ""。"User "这个类库在Win32中名叫 ""。 它主要管理全部的用户接口。譬如:窗口 、菜单 、对话框 、图标等等。"GDI"(图象设备接口),它在Win32中的库名为:"",要获得显示器的DC,所调用的API函数–CreateDC ( ),就被封装在此类库中。而要在C#中声明视窗的API函数需要使用.Net FrameWork SDK中的名字空间"pServices",此名字空间提供了一系列的类来访问COM对象,和调用本地的API函数。下面是在C#中声明此函数:
[ ortAttribute ( "" ) ]
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 = c ( dc1 ) ;
//由一个指定设备的句柄创建一个新的Graphics对象
MyImage = new Bitmap ( , , g1 ) ;
//根据屏幕大小创建一个与之相同大小的Bitmap对象
(2).根据此位图创建一个和其一样的Graphic对象:
通过下面代码就可以实现此功能:
Graphics g2 = age ( MyImage ) ;
(3).获得当前屏幕和位图的句柄:
获得此二个对象的句柄是为了下一步实现对当前屏幕图象的捕获,程序中实现的具体捕获的方法是把当前屏幕捕获到已经创建的位图对象中。具体实现代码如下:
//获得屏幕的句柄
IntPtr dc3 = ( ) ;
//获得位图的句柄
IntPtr dc2 = ( ) ;
//把当前屏幕捕获到位图对象中
(4).捕获当前屏幕:
我们是通过当前屏幕保存到创建的位图对象中来实现的,具体的实现过程中是通过Windows的一个API函数–Bitblt。我想大多数程序员对此API函数一定不陌生,因为在Windows的图象编程中,会在很多地方使用到此函数。这个API函数和上面介绍的那个API函数一样,也是被封装在""中的,下面是此函数在C#中的声明:
[ ortAttribute ( "" ) ]
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坐标
32 dwRop // 光栅的操作值
) ;
知道了此声明就可以实现对当前屏幕的保存了,具体如下:
BitBlt ( dc2 , 0 , 0 , , , dc3 , 0 , 0 , 13369376 ) ;
(5).把当前屏幕保存到硬盘,并释放句柄:
eHdc ( dc3 ) ;
//释放屏幕句柄
eHdc ( dc2 ) ;
//释放位图句柄
( "c:" , ) ;
我们可以根据自己的要求把当前屏幕以不同的文件格式来保存,在本文中介绍的程序是以"jpg"文件来保存的,你可以通过修改"Save"方法的第二个参数来改变保存到硬盘的文件类型,譬如,如果第二个参数为"",那么你保存到硬盘的文件就为"GIF"文件了。对于其他文件格式可以参考.Net FrameWork SDK,里面有详细的介绍。
三. 用C#做Screen Capture程序的代码和运行节目:
在掌握了上面这些重要步骤后,可以得到用C#做Screen Capture程序的源代码(),具体如下:
using System ;
using g ;
using tions ;
using entModel ;
using ;
using ;
using g ;
using ;
//导入在程序中使用到的名称空间
public class Capture : Form
{
private ner components = null ;
private Icon mNetTrayIcon = new Icon ( "" ) ;
private Bitmap MyImage = null ;
private NotifyIcon TrayIcon ;
private ContextMenu notifyiconMnu ;
public Capture ( )
{
//初始化窗体中使用到的组件
InitializeComponent ( ) ;
}
protected override void OnActivated ( EventArgs e )
{
( ) ;
}
[ ortAttribute ( "" ) ]
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坐标
32 dwRop // 光栅的操作值
) ;
[ ortAttribute ( "" ) ]
private static extern IntPtr CreateDC (
string lpszDriver , // 驱动名称
string lpszDevice , // 设备名称
string lpszOutput , // 无用,可以设定位"NULL"
IntPtr lpInitData // 任意的打印机数据
) ;
public void capture ( object sender , rgs e )
{
e = false ;
IntPtr dc1 = CreateDC ( "DISPLAY" , null , null , ( IntPtr ) null ) ;
//创建显示器的DC
Graphics g1 = c ( dc1 ) ;
//由一个指定设备的句柄创建一个新的Graphics对象
MyImage = new Bitmap ( , , g1 ) ;
//根据屏幕大小创建一个与之相同大小的Bitmap对象
Graphics g2 = age ( MyImage ) ;
//获得屏幕的句柄
IntPtr dc3 = ( ) ;
//获得位图的句柄
IntPtr dc2 = ( ) ;
//把当前屏幕捕获到位图对象中
BitBlt ( dc2 , 0 , 0 , , , dc3 , 0 , 0 , 13369376 ) ;
//把当前屏幕拷贝到位图中
eHdc ( dc3 ) ;
//释放屏幕句柄
eHdc ( dc2 ) ;
//释放位图句柄
( "c:" , ) ;
( "已经把当前屏幕保存到C:文件中!" ) ;
e = true ;
}
public void ExitSelect ( object sender , rgs e )
{
//隐藏托盘程序中的图标
e = false ;
//关闭系统
( ) ;
}
//清除程序中使用过的资源
public override void Dispose ( )
{
e ( ) ;
if ( components != null )
e ( ) ;
}
private void InitializeComponent ( )
{
//设定托盘程序的各个属性
TrayIcon = new NotifyIcon ( ) ;
= mNetTrayIcon ;
= "用C#做Screen Capture程序" ;
e = true ;
//定义一个MenuItem数组,并把此数组同时赋值给ContextMenu对象
MenuItem [ ] mnuItms = new MenuItem [ 3 ] ;
mnuItms [ 0 ] = new MenuItem ( ) ;
mnuItms [ 0 ] .Text = "捕获当前屏幕!" ;
mnuItms [ 0 ] .Click += new andler ( e ) ;
mnuItms [ 1 ] = new MenuItem ( "-" ) ;
mnuItms [ 2 ] = new MenuItem ( ) ;
mnuItms [ 2 ] .Text = "退出系统" ;
mnuItms [ 2 ] .Click += new andler ( lect ) ;
mnuItms [ 2 ] .DefaultItem = true ;
notifyiconMnu = new ContextMenu ( mnuItms ) ;
tMenu = notifyiconMnu ;
//为托盘程序加入设定好的ContextMenu对象
dLayout ( ) ;
aleBaseSize = new ( 5 , 13 ) ;
Size = new ( 320 , 56 ) ;
lBox = false ;
zeBox = false ;
zeBox = false ;
State = zed ;
= "capture" ;
Taskbar = false ;
= "用C#做Screen Capture程序!" ;
Layout ( false ) ;
}
static void Main ( )
{
( new Capture ( ) ) ;
}
}
下图是此代码编译后的运行界面:
图01:用C#做Screen Capture程序的源代码
四. 总结:
虽然.Net FrameWork SDK的内容十分丰富,借助他所能够实现的功能也非常强大,但对于一些底层的操作,有时还是需要借助Windows的API函数才可以实现,而实现Screen Capture的关键也就在于掌握C#中调用API函数的方法。希望通过本文,能够对你掌握在C#中的API编程有所帮助。
发布评论