您的位置:首页 > 其它

从.NET平台调用Win32 API

2008-03-10 23:53 267 查看
Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制Windows的接口。

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool CopyFile(string src, string dst, bool failIfExists);

如何用C#语言和DllImport特性来调用Win32 API。

using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);

static int Main()
{
MessageBox(0, "Hello Win32 API", "懒猫星空", 4);
Console.ReadLine();
return 0;
}
}
让我们剖析一下这个程序:
1. 要使用DllImport这个特性(特性也是一种类),必须使用这一句using System.Runtime.InteropServices;
,导入“运行时->交互服务”。
2. 然后我们就可以制造一个DllImport类的实例,并把这个实例绑定在我们要使用的函数上了。
3. 接下来就是我们的函数了。在C#里调用Win32函数有这么几个要点。第一:名字要与Win32 API的完全一样。第二:函数除了要有相应的DllImport类修饰外,还要声明成public static extern类型的。第三:也是最变态的一点,函数的返回值和参数类型要与Win32 API完全一致!
常用Win32数据类型与.NET平台数据类型的对应表:
Figure 2 Non-Pointer Data Types

Win32 TypesSpecificationCLR Type
char, INT8, SBYTE, CHAR8-bit signed integerSystem.SByte
short, short int, INT16, SHORT16-bit signed integerSystem.Int16
int, long, long int, INT32, LONG32, BOOL, INT 32-bit signed integerSystem.Int32
__int64, INT64, LONGLONG64-bit signed integerSystem.Int64
unsigned char, UINT8, UCHAR, BYTE8-bit unsigned integerSystem.Byte
unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR, __wchar_t16-bit unsigned integerSystem.UInt16
unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT32-bit unsigned integerSystem.UInt32
unsigned __int64, UINT64, DWORDLONG, ULONGLONG64-bit unsigned integerSystem.UInt64
float, FLOATSingle-precision floating pointSystem.Single
double, long double, DOUBLEDouble-precision floating pointSystem.Double
In Win32 this type is an integer with a specially assigned meaning; in contrast, the CLR provides a specific type devoted to this meaning.
有了这些东西,我们就能把一个Win32 API函数转成C#函数了。还拿MessageBox函数为例(看刚才给出的函数表),它的Win32原形如下:

int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );

函数名:MessageBox将保持不变。
返回值:int 将保持不变(无论是Win32还是C#,int都是32位整数)
参数表:H开头意味着是Handle,一般情况下Handld都是指针类型,Win32平台的指针类型是用32位来存储的,所以在C#里正好对应一个int整型。不过,既然是指针,就没有什么正负之分,32位都应该用来保存数值——这样一来,用uint(无符号32位整型)来对应Win32的H类型更合理。不过提醒大家一点,int是受C#和.NET CLR双重支持的,而uint只受C#支持而不受.NET CLR支持,所以,本例还是老老实实地使用了int型。
至于LPCTSTR是Long Pointer to Constant String的缩写,说白了就是——字符串。所以,用C#里的string类型就对了。
修饰符:要求有相应的DllImport和public static extern

经过上面一番折腾,Win32的MessageBox函数就包装成C#可以调用的函数了:

[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);

第一个:弹出的MessageBox的父窗口是谁。本例中没有,所以是0,也就是“空指针”。
第二个:MessageBox的内容。本例中是“Hello Win32 API”。
第三个:MessageBox的标题。本例中用的是本人Blog的名字——水之真谛——请大家不要忘记。
第四个:MessageBox上的按钮是什么,如果是0,那就只有一个OK,MessageBox太短了,你将看不全“水之真谛”四个字,于是偶改成了4,这样就有两个按钮了。这些在MSDN的函数用法里都有。不过,我还是非常推荐您阅读一下本人的另一篇拙作《一个Win32程序的进化》
.NET Framework都为我们封装好了哪些Win32 API,OK,MSDN里有一篇文章,专门列出了这些。文章的名字是《Microsoft Win32 to Microsoft .NET Framework API Map》请感兴趣的朋友自己阅读。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: