C#捕获当前屏幕的例子
#region 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 ( , 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函数
[ 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 // 光栅的处理数值 ) ;
static void Main ( ) {
Application.Run ( new Form1 ( ) ) ;
}
private void button1_Click ( object sender , System.EventArgs e ) {
//获得当前屏幕的大小
Rectangle rect = new Rectangle ( ) ; rect = Screen.GetWorkingArea ( this ) ; //创建一个以当前屏幕为模板的图象 Graphics g1 = this.CreateGraphics ( ) ; //创建以屏幕大小为标准的位图
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 ( ) ;
//调用此API函数,实现屏幕捕获
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 ( \"当前屏幕已经保存为C盘的capture.jpg文件!\" ) ; } }
#endregion
上面的例子中,应用C#调用非托管DLL的函数如下: //声明一个API函数
[ 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 // 光栅的处理数值 ) ;
在上面这段代码中,我将以分别介绍 DllImportAttribute属性、extern关键字 、IntPtr类型 这三个方面,向大家介绍如何应用C#调用非托管DLL函数。
C# 如何使用 DllImport Attribute(属性) 标识 DLL 和函数
System.Runtime.InteropServices.DllImportAttribute
从托管代码中访问非托管 DLL 函数之前,需要知道该函数的名称以及该 DLL 的名称,然后为 DLL 的非托管函数 编写 托管定义。
它将用到 static 和 extern 修饰符,此类型的公共静态成员对于多线程操作是安全的。
DllImport 属性提供非托管 DLL 函数的调用信息。
示例1 简单DllImportAttribute 应用 using System.Runtime.InteropServices; [DllImport(\"user32.dll\")]
public static extern int MessageBox(int hWnd, String text, String caption, uint type);
示例2 如何将 DllImportAttribute 应用于方法。 using System.Runtime.InteropServices; [DllImport( \"KERNEL32.DLL\
EntryPoint=\"MoveFileW\ SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall )
]
public static extern bool MoveFile(String src, String dst);
参数说明:
EntryPoint 指定要调用的 DLL 入口点。
SetLastError 判断在执行该方法时是否出错(使用 Marshal.GetLastWin32Error API 函数来确定)。
C#中默认值为 false。
CharSet 控制名称及函数中字符串参数的编码方式。默认值为 CharSet.Ansi。
ExactSpelling 是否修改入口点以对应不同的字符编码方式。
CallingConvention 指定用于传递方法参数的调用约定。默认值为 WinAPI。 该值对应于基于32位Intel平台的 __stdcall。
BestFitMapping 是否启用最佳映射功能,默认为 true。
最佳映射功能提供在没有匹配项时,自动提供匹配的字符。 无法映射的字符通常转换为默认的“?”。
PreserveSig 托管方法签名是否转换成返回 HRESULT,默认值为 true(不应转换签名)。
并且返回值有一个附加的 [out, retval] 参数的非托管签名。
ThrowOnUnmappableChar 控制对转换为 ANSI '?' 字符的不可映射的 Unicode 字符引发异常。
C# 关键字 extern 的使用
public static extern int MyMethod(int x);
外部修饰符 extern 用于指示外部实现方法,常与 DllImport 属性一起使用(DllImport 属性提供非托管 DLL 函数的调用信息)。
若将 abstract 和 extern 修饰符一起使用来修改同一成员是错误的。extern 将方法在 C# 代码的外部实现,而 abstract 意味着在此类中未提供此方法的实现。
因为外部方法声明不提供具体实现,所以没有方法体;
此方法声明只是以一个分号结束,并且在签名后没有大括号{ }。
示例3 接收用户输入的字符串并显示在消息框中
程序从 User32.dll 库导入的 MessageBox 方法。 using System;
using System.Runtime.InteropServices; class MyClass
{
[DllImport(\"User32.dll\")]
public static extern int MessageBox(int h, string m, string c, int type);
public static int Main() {
string myString;
Console.Write(\"Enter your message: \"); myString = Console.ReadLine();
return MessageBox(0, myString, \"My Message Box\ } }
运行结果: 输入\"Hello\"文本后,屏幕上将弹出一个包含该文本的消息框。 Enter your message: Hello
示例4 调用DLL进行计算
该示例使用两个文件 CM.cs 和 Cmdll.c 来说明 extern。 C 文件是从 C# 程序中调用的外部 DLL。
使用 Visual C++ 命令行将 Cmdll.c 编译为 DLL: cl /LD /MD Cmdll.c
文件:Cmdll.c // cmdll.c
// compile with: /LD /MD
int __declspec(dllexport) MyMethod(int i) {
return i*10; }
使用命令行编译 CM.cs: csc CM.cs
这将创建可执行文件 CM.exe。
文件:CM.cs // cm.cs
using System;
using System.Runtime.InteropServices; public class MyClass {
[DllImport(\"Cmdll.dll\")]
public static extern int MyMethod(int x);
public static void Main() {
Console.WriteLine(\"MyMethod() returns {0}.\ }
}
运行此程序,MyMethod 将值 5 传递到 DLL 文件,该文件将此值乘以 10 返回。 运行结果:MyMethod() returns 50.
IntPtr 类型的说明
对于平台调用,应让参数为 IntPtr 类型,而不是 String 类型。使用 System.Runtime.InteropServices.Marshal 类所提供的方法,可将类型手动转换为字符串并手动将其释放。
IntPtr 类型被设计成整数,其大小适用于特定平台。
在 32 位硬件和操作系统中将是 32 位;
在 位硬件和操作系统中将是 位。
IntPtr 类型由支持指针的语言使用,并作为在支持与不支持指针的语言间引用数据的一种通
用方式。它也可用于保持句柄。例如,IntPtr 的实例广泛地用在 System.IO.FileStream 类中来保持文件句柄。
IntPtr 类型符合 CLS,而 UIntPtr 类型却不符合。只有 IntPtr 类型可用在公共语言运行库中。此类型实现 ISerializable 接口。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- igbc.cn 版权所有 湘ICP备2023023988号-5
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务