概要
有时候希望在相同的代码路径中混合使用GDI和GDI +绘图操作。当您编写允许GDI和GDI +互操作的代码时,请记住一些注意事项。本文概述了这些注意事项,并提供了其他信息来帮助您成功编写此类代码。
更多信息
虽然可以将GDI和GDI+代码混合使用,但是必须遵守一定的规则。通常,您不应该将GDI和GDI +调用交错在一个目标对象上。例如,围绕HDC
包装一个Graphics
对象是可以的,但是在Graphics
对象被销毁之前,您不应该直接从GDI访问HDC
。
本文介绍了GDI和GDI +之间互操作性的四个主要场景:
- 在由屏幕支持的GDI +图形对象上使用GDI
- 在由位图支持的GDI +图形对象上使用GDI
- 在GDI HDC上使用GDI +
- 在GDI内存HBITMAP上使用GDI +
在由屏幕支持的GDI+图形对象上使用GDI
在屏幕支持的GDI+ Graphics对象上使用GDI的一个例子就是绘制一个“橡皮筋”或“焦点”矩形。GDI+目前不支持光栅操作(ROPs),因此如果需要R2_XOR
笔操作,则必须直接使用GDI。在这种情况下,您可以使用Graphics::GetHDC()
来获取GDI输出指向的HDC
。GDI +输出不应该在HDC
生命周期的图形对象上进行尝试(也就是直到调用Graphics::ReleaseHDC()
)。
在位图所支持的GDI+图形对象上使用GDI
当为位图支持的Graphics
对象而不是屏幕调用Graphics::GetHDC()
时,会创建一个内存HDC
,并创建一个新的HBITMAP
并将其选入内存HDC
中。这个新的内存位图不是使用原始位图的图像进行初始化,而是使用一个标记模式,它允许GDI +跟踪对位图的更改。通过使用GDI代码对内存位图所做的任何更改,都会在对哨兵模式的更改中变得明显。当Graphics::ReleaseHDC()
被调用时,这些更改被复制回原始位图。由于内存位图未用位图的图像进行初始化,因此以这种方式获得的HDC
应被视为“只写”,因此不适合与ROP一起使用,其使用需要能够读取目标,如R2_XOR
。此外,这种方法的性能成本也很高,因为GDI +必须将更改复制回原始位图。
在GDI HDC
上使用GDI+
通过使用以HDC
为参数的Graphics构造函数,可以方便地在HDC
上使用GDI +。Graphics类的绘图成员可以用这种方式在HDC
上绘图。一旦Graphics对象被附加到HDC
,在Graphics
对象被销毁或超出范围之前,不应该在HDC
上执行GDI操作。如果在HDC
上需要GDI输出,则可以在使用原始HDC
之前销毁Graphics
对象,或者使用Graphics::GetHDC()
获取新的HDC
,然后按照本文前面所述的规则进行互操作,同时在GDI +目的。
在GDI内存HBITMAP
上使用GDI+
将HBITMAP作为参数的GDI +位图构造函数不使用实际的源HBITMAP作为位图的后备图像。而是在构造函数中创建图像副本,即使在执行析构函数期间,也不会将更改写回原始位图。新的位图可以被认为是“在创建时复制”,因此为了让GDI +从GDI中获取HBITMAP
内存,并将这些更改应用于HBITMAP
,需要使用类似下面的方法:
- 列表内容
- 创建一个
DIBSection
。 - 将
DIBSection
选择到内存HDC
中。 - 要使用GDI +绘制
DIBSection
,请围绕HDC包装一个Graphics
对象。 - 要使用GDI绘制
DIBSection
,请销毁Graphics
对象,然后使用HDC
。 - 销毁图形对象,然后清除
HDC
中的DIBSection
选项。
稍后,如果需要,可以从DIBSection
构造一个位图,并将其用作Graphics::DrawImage()
中的源图像。