科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件托管C++中GDI 和GDI混合编程技术

托管C++中GDI 和GDI混合编程技术

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在托管C++中通过平台调用来实现GDI 和GDI的混合编程,不仅可以克服GDI 中的不足,如XOR的光栅操作,更主要的是可以借助MFC DLL来拓展GDI 的图形图像的开发能力。

作者:丁有和 来源:天极网 2007年11月16日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
3.2 数据封送

  由于在 GDI API(在wingdi.h中列出)函数中所使用的数据类型和托管C++( .NET Framework内置值类型)存在一些区别(如表1所示),虽然在托管C++中可以不通过平台调用中的数据封送来直接调用GDI API,但对于结构、数组和字符串数据类型来说,通过使用平台调用中的属性和方法来封送数据可以更好地实现自己的数据定制。

  表1 数据类型

wtypes.h C++ 托管C++ .NET类名 说明
GDI句柄 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 位

  (1) 封送结构

  在托管C++中,当调用的GDI API函数有内置结构时,需要对其使用StructLayout属性来进行封送。通过该属性类的构造函数来指定被封送的结构的数据成员在非托管内存中的排列方式。当为LayoutKind::Explicit时,则每个成员必须使用FieldOffset属性来指定该字段在类型中的位置。当为LayoutKind::Sequential时,则强制将成员按其出现的顺序进行顺序布局。例如:

namespace GDI32API
{
 using namespace System;
 using namespace System::Runtime::InteropServices;
 typedef void* HDC;
 [StructLayout(LayoutKind::Sequential)]
 public __value struct RECT
 {
  public:
   long left; // long或Int32
   long top;
   long right;
   long bottom;
 };
 [DllImport("gdi32", EntryPoint="GetClipBox")]
 extern "C" int GetClipBox(HDC hDC, RECT* rect);
}

  (2) 封送字符串和数组等

  在托管C++中,使用MarshalAs属性类可以封送GDI API函数中的参数、内置结构的字段或返回值。MarshalAs属性通常需要指定UnmanagedType枚举来标识非托管数据的格式。

  当需要封送String *字符串时,可指定UnmanagedType枚举中的LPStr、LPWStr或LPTStr来封送,这些类型分别对应于GDI API中的LPSTR、LPWSTR或LPTSTR字符串类型。例如:

[DllImport("gdi32", EntryPoint="TextOut")]
extern "C" bool TextOut(HDC hDC, int x, int y,
[MarshalAs(UnmanagedType::LPWStr)] String *str, int nNum);

  若封送结构中的字符串成员,则需指定UnmanagedType::ByValTStr类型,并指定SizeConst值来确定要导入的字符串中的字符数。

  当需要封送数组时,需指定UnmanagedType::LPArray类型,并指定SizeConst值来确定要导入的数组大小,根据需要也可用ArraySubType字段指定数组元素的数据类型。例如,若有DLL中有这样的非托管函数:

HRESULT New1(int ar[10]);
HRESULT New2(double ar[10][20]);
HRESULT New3(LPWSTR ar[10]);

  则封送的托管代码如下:

void New1([MarshalAs(UnmanagedType::LPArray, SizeConst=10)] int ar __gc[]);
void New2([MarshalAs(UnmanagedType::LPArray, SizeConst=200)] double ar __gc[]);
void New2([MarshalAs(UnmanagedType::LPArray,
ArraySubType=UnmanagedType::LPWStr, SizeConst=10)] String[] ar);

  若封送结构中的数组成员,则需指定UnmanagedType::ByValArray类型,并指定SizeConst值来确定要导入的数组大小。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章