型的标记,除了此标记名外,函数原型的声明和C++函数的声明是一样的,函数名可以与EntryPoint字段指定的函数名相同,也可不同。为了避免声明的函数名与托管程序中其他方法重名,通常将要调用的DLL函数放在一个自定义的命名空间或自定义类中。例如:
namespace GDI32API // 自定义的命名空间
{
using namespace System;
using namespace System::Runtime::InteropServices;
typedef void* HDC;
[DllImport("gdi32", EntryPoint="LineTo")]
extern "C" bool LineTo(HDC hDC, int nXEnd, int nYEnd);
}
此时调用LineTo函数时须指定其所在的命名空间,例如:
Graphics *g = this->panel1->CreateGraphics();
// 创建与panel1控件相关联的Graphics
IntPtr hdc = g->GetHdc();
GDI32API::LineTo( (GDI32API::HDC)hdc,100, 200 );
g->ReleaseHdc( hdc );
若将将要调用的DLL函数放在一个自定义类中,则该函数一般要定义成静态类型。但由于extern "C"标记会在自定义的类中出现编译错误,若不使用extern "C"标记,对于没有内置结构或类的GDI API函数是可以的。例如:
public __gc class GDI32API
{
public:
typedef void* HDC;
[DllImport("gdi32", EntryPoint="LineTo")]
static bool LineTo(HDC hDC, int nXEnd, int nYEnd);
};
3.2 数据封送
由于在 GDI API(在wingdi.h中列出)函数中所使用的数据类型和托管C++( .NET Framework内置值类型)存在一些区别(如表1所示),虽然在托管C++中可以不通过平台调用中的数据封送来直接调用GDI API,但对于结构、数组和字符串数据类型来说,通过使用平台调用中的属性和方法来封送数据可以更好地实现自己的数据定制。
表1 数据类型
wtypes.h |
C++ |
托管C++ |
.NET类名 |
说明 |
GDI句?/TD> |
void * |
void * |
IntPtr, UIntPtr |
32 位 |
BYTE |
unsigned char |
unsigned char |
Byte |
8 位 |
SHORT |
short |
short |
Int16 |
16 位 |
WORD |
unsigned |
short unsigned |
short UInt16 |
16 位 |
INT |
int |
int |
Int32 |
32 位 |
UINT |
unsigned int |
unsigned int |
UInt32 |
32 位 |
LONG |
long |
long |
Int32 |
32 位 |
BOOL |
long |
bool |
Boolean |
32 位 |
DWORD |
unsigned long |
unsigned long |
UInt32 |
32 位 |
ULONG |
unsigned long |
unsigned long |
UInt32 |
32 位 |
CHAR |
char |
char |
Char |
用 ANSI 修饰 |
LPSTR |
char * |
String * [in], StringBuilder * [in, out] |
String [in], StringBuilder [in, out] |
用 ANSI 修饰 |
LPCSTR |
const char * |
String * |
String |
用 ANSI 修饰 |
LPWSTR |
wchar_t * |
String * [in], StringBuilder * [in, out] |
String [in], StringBuilder [in, out] |
用 Unicode 修饰 |
LPCWSTR |
const wchar_t * |
String * |
String |
用 Unicode 修饰 |
FLOAT |
float |
float |
Single |
32 位 |
DOUBLE |
double |
double |
Double |
64 位 |
|