关于Gdi+和GdiplusStartup

GDI+实际上是一组类的定义,封装了gdi+的几乎所有API,当然使用方法就要从这些“例子”里边寻找了:)本文正是尝试用GDI+写一个纯SDK的程序,语言自然是我最喜欢的语言WIN32ASM.这个程序很简单,就是用GDI+画了一条直线。算是抛砖引玉吧,感兴趣的可以自己探索其他函数的用法。 
使用GDI+ API之前,必须先调用GdiplusStartup这个函数,作用是初始化GDI+函数库。这个函数在SDK中就有。函数的原型是:

  
Status GdiplusStartup(ULONG_PTR token *token, 
const GdiplusStartupInput *input, 
GdiplusStartupOutput *output 
);   

第一个参数是指向一个32位的无符号整型的指针,也就是指向一个汇编中的DWORD变量的指针,用于接受GDI+的TOKEN.TOKEN可以暂时理解成一个句柄,就像窗口的句柄类似。这个参数在调用GdiplusShutdown的时候用到。这个函数在结束GDI+编程后调用,起作用是释放GDI+的资源。 
第二个以及第三个参数是指向两个结构体变量的指针。GdiplusStartupInput的定义如下: 
struct GdiplusStartupInput 
{ 
UINT32 GdiplusVersion; 
DebugEventProc DebugEventCallback; 
BOOL SuppressBackgroundThread; 
BOOL SuppressExternalCodecs; 

GdiplusStartupInput( 
DebugEventProc debugEventCallback = NULL, 
BOOL suppressBackgroundThread = FALSE, 
BOOL suppressExternalCodecs = FALSE) 
{ 
GdiplusVersion = 1; 
DebugEventCallback = debugEventCallback; 
SuppressBackgroundThread = suppressBackgroundThread; 
SuppressExternalCodecs = suppressExternalCodecs; 

}; 
这个定义看似复杂,实际就四个32位的变量,可以定义成如下的形式: 
struct GdiplusStartupInput 
{ 
UINT32 GdiplusVersion; 
DebugEventProc DebugEventCallback; 
BOOL SuppressBackgroundThread; 
BOOL SuppressExternalCodecs; 

一般这个结构体初始化成1,0,0,0即可,并且这时候这个函数的最后一个参数GdiplusStartupOutput可以忽略,直接用NULL就可以。

   
下面是MASM32的代码例子: 

include windows.inc 
include kernel32.inc 
include user32.inc 
include Comctl32.inc 
include shell32.inc 

includelib kernel32.lib 
includelib user32.lib 
includelib Comctl32.lib 
includelib shell32.lib 

include gdiplus.inc ;这是GDI+的MASM32格式的头文件,现在只是从现成的 
;GDI+的库转换而来,没有整理其数据结构。 
includelib gdiplus.lib ;GDI+的库文件,取自VC7.1 

;上边包含的头文件以及库文件我会附在这篇文章上提供。 
GdiplusStartupInput struct 
GdiplusVersion dword ; // Must be 1 
DebugEventCallback dword ; // Ignored on free builds 
SuppressBackgroundThread dword ; // FALSE unless you're prepared to call 
; // the hook/unhook functions properly 
SuppressExternalCodecs dword ; // FALSE unless you want GDI+ only to use 
GdiplusStartupInput ends 
;上边是GdiplusStartupInput结构体的定义。 
.data? 

hInstance dd ? 
gptoken dd ?;定义TOKEN的接收变量 
.data 
gpstart GdiplusStartupInput<1,0,0,0>;定义这个结构并初始化 

接下来,就是在程序初始化和结束时调用GdiplusStartup跟GdiplusShutdown两个函数: 
invoke GdiplusStartup,offset gptoken,offset gpstart,NULL 
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL 
invoke GdiplusShutdown,gptoken 
这里我选择在主窗口生成前跟销毁后调用这两个函数。 
现在,在WM_PAINT里边就可以调用GDI+函数进行绘图了: 
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM 
LOCAL ps:PAINTSTRUCT 
LOCAL dc:HDC 
LOCAL gp 
LOCAL ggg 
mov eax,uMsg 
.if eax==WM_INITDIALOG 
.elseif eax==WM_PAINT 
invoke BeginPaint,hWin,addr ps 
mov dc,eax 
invoke GdipCreateFromHDC,dc,addr gp 
mov ggg,0 
invoke GdipCreatePen1,0ffff00ffh,1,0,addr ggg 
invoke GdipDrawLineI,gp,ggg,10,10,130,100 
invoke GdipDeletePen,ggg 
invoke GdipDeleteGraphics,gp 
invoke EndPaint,hWin,addr ps 

最前与最后的Begin/EndPaint()是gdi作图时常用的,不用我多说。首先,调用GdipCreateFromHDC产上一个Graphics的句柄,这个函数有两个参数看看微软提供的头文件里边的用法: 
lastResult = DllExports::GdipCreateFromHDC(hdc, &graphics); 
第一个参数是当前的dc,后一个则是存放Graphics句柄的指针。值得注意的是,GDI+函数的返回值一般是通过参数传递而不是eax了,eax在GDI+函数中往往返回错误代码。所以调试的时候如果执行了GDI+函数后如果返回0则说明调用成功,返回非零值一般是调用失败所致。 
接下来调用GdipCreatePen1生成一个画笔对象,这个函数在微软的头文件中是这么用的: 
Unit unit = UnitWorld; 
nativePen = NULL; 
lastResult = DllExports::GdipCreatePen1(color.GetValue(), 
width, unit, &nativePen); 
这个函数的第一个参数是画笔的颜色值,这是一个32位的颜色值,前8位估计是alpha通道,决定这个颜色的透明度,后边的24位以8位一组,分别代表红绿兰三原色。第二个从字面看是画笔宽度,不过我改了一下,好像并没有效果,可能是还不会用。第三个参数是一个枚举类型 
enum Unit 
{ 
UnitWorld, // 0 -- World coordinate (non-physical unit) 
UnitDisplay, // 1 -- Variable -- for PageTransform only 
UnitPixel, // 2 -- Each unit is one device pixel. 
UnitPoint, // 3 -- Each unit is a printer's point, or 1/72 inch. 
UnitInch, // 4 -- Each unit is 1 inch. 
UnitDocument, // 5 -- Each unit is 1/300 inch. 
UnitMillimeter // 6 -- Each unit is 1 millimeter. 
}; 
UnitWorld是带表0的。 
同样,最户一个参数是一个存放生成的画笔举柄的指针。Eax中返回值也是错误信息。 
然后我们用GdipDrawLineI画一条直线,下边是微软头文件中的用法: 
SetStatus(DllExports::GdipDrawLineI(nativeGraphics, 
pen->nativePen, 
x1, 
y1, 
x2, 
y2)); 
前边两个参数分别是当前nativeGraphics的句柄跟Pen的句柄,后边则是两个坐标。 
最后的两个函数GdipDeletePen与GdipDeleteGraphics是删除前边生成的画笔对象跟Graphics对象,只有一个参数,即对象的句柄。注意这两个函数的参数都是实际的地址而不是指针。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值