如何使用C#调用非托管DLL函数
点击次数:16 次 发布日期:2008-11-26 10:36:06 作者:源代码网
|
源代码网推荐 源代码网推荐 源代码网推荐 引用: 用C#来捕获屏幕的源程序代码(Capture.cs) 源代码网推荐 源代码网推荐 源代码网推荐 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 ( 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函数 源代码网推荐 [ 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", 0); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 运行结果: 输入"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)); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 运行此程序,MyMethod 将值 5 传递到 DLL 文件,该文件将此值乘以 10 返回。 源代码网推荐 运行结果:MyMethod() returns 50. 源代码网推荐 源代码网推荐 源代码网推荐 IntPtr 类型的说明 源代码网推荐 源代码网推荐 对于平台调用,应让参数为 IntPtr 类型,而不是 String 类型。使用 System.Runtime.InteropServices.Marshal 类所提供的方法,可将类型手动转换为字符串并手动将其释放。 源代码网推荐 源代码网推荐 IntPtr 类型被设计成整数,其大小适用于特定平台。 源代码网推荐 在 32 位硬件和操作系统中将是 32 位; 源代码网推荐 在 64 位硬件和操作系统中将是 64 位。 源代码网推荐 源代码网推荐 IntPtr 类型由支持指针的语言使用,并作为在支持与不支持指针的语言间引用数据的一种通用方式。它也可用于保持句柄。例如,IntPtr 的实例广泛地用在 System.IO.FileStream 类中来保持文件句柄。 源代码网推荐 源代码网推荐 IntPtr 类型符合 CLS,而 UIntPtr 类型却不符合。只有 IntPtr 类型可用在公共语言运行库中。此类型实现 ISerializable 接口。 源代码网推荐 源代码网推荐 其中引用了微软官方的部分例子,特此声名。希望多多指教,共同进步! 源代码网推荐 源代码网推荐 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
