分类
日历
登陆
最新文章
回复
站点统计
友情链接
我熟悉 BCB6,一直在此环境下工作,原先又不熟悉GDI+,所以使用 GDI+ 只能靠着微软提供的标准 C++ 对象。经过很多试验,发现 BCB6 的编译器对微软的这套 C++ 封装水土不服,不仅产生许多冲突,很多地方根本就无法通过编译。
在熟悉了一点之后,找到问题所在:微软提供的 GDI+ 的 C++ 封装和 BCB 的 VCL 有名称定义冲突,典型的就是 VCL 中有个 Graphics 集合,而 GDI+ 中有个 Graphics 对象,作为名字空间的 VCL 的 Graphics 集合让编译器区分不出源代码中的对象和集合的区别,所以产生无法避免的错误。这不能怪 Broland 的编译器不好,毕竟那时出了 GDI+ 没多久,C++ 的新标准颁布也不长,微软又爱赶时髦,经常出些别出心裁的东西,导致 Broland 的编译器赶不上了,也不知道是不是微软故意这样干的?
熟悉GDI+之后,掌握它的工作原理就好办了。GDI+ 中的 Graphics 对象是个绘图工具,仅仅用来绘图,它不包含任何图形数据,创建它的目的就是利用它来进行绘图操作。
它进行绘制操作的目标就是它所关联的一个图形对象,而这个对象既可以是窗体也可以是图片等图形数据的载体。所以 Graphics 对象的创建过程必须要和这个载体关联起来,然后这个新创建的 Graphics 对象的所有绘制动作都是针对它创建时关联的这个载体进行的。
和微软的 VS 环境不同,在 BCB 中可以直接用 C++ 的标准 new 语法创建此对象。例如,创建一个窗体的Graphics 对象可以是这样的:Gdiplus::Graphics * myGP = new Gdiplus::Graphics(Form1->Handle, false); 。
如此一来,这个新创建的 Graphics 对象就可以在 Form1 上乱涂乱画了。利用 Graphics 对象的方法,可以画圆、矩形、线条、图片(包括支持 Alpha 特性的高级图片)等等,这是 BCB 原来的 VCL 无法做到的。而 BCB 中原有的 VCL 中的图形载体组件,都可以利用它自己创建关联的 Graphics 对象来扩充自己的绘图能力。
GDI+ 中的 Image 和 Bitmap 对象不仅仅支持了新的图形格式:PNG、GIF等,更加支持了 64bit 的彩色特性。仅 32bit 的彩色格式就可让每个象素带有自己专用的 Alpha 数据,这样每个象素点都能带有不同的透明度,绘图时很玄的!
熟悉了GDI+之后,我们就可以改装 GDI+ 的C++封装包了。例如:有个 BCB 不能识别的问题,我么们看看 GDI+ Graphics 对象的构造函数申明定义:
Graphics(IN HDC hdc)
{
GpGraphics *graphics = NULL;
lastResult = DllExports::GdipCreateFromHDC(hdc, &graphics);
SetNativeGraphics(graphics);
};
Graphics(IN HWND hwnd, IN BOOL icm = FALSE)
{
GpGraphics *graphics = NULL;
if (icm)
{
lastResult = DllExports::GdipCreateFromHWNDICM(hwnd, &graphics);
}
else
{
lastResult = DllExports::GdipCreateFromHWND(hwnd, &graphics);
}
SetNativeGraphics(graphics);
}
在第二个声明中,使用了缺省值 icm = FALSE ,这样的话,在 BCB 中,编译器将 GDI+ 的 C++ 包装展开后,这两个构造函数就变成了:
Graphics ( int hdc )
Graphics ( int hwnd, bool icm = false )
这是由于 HWND 和 HDC 原来都是 int 型数据的别名,一展开后,恢复了本质, BCB 就无法识别你的这句源码:
Gdiplus::Graphics * myGP = new Gdiplus::Graphics(Form1->Handle);
它不知道你想调用Graphics ( (int ) hdc ) 还是 Graphics ( (int) hwnd, false )。我是在失败了很多次之后,才在跟踪执行中发现这个问题。所以,我将定义文件中的这句定义改成了: Graphics(IN HWND hwnd, IN BOOL icm)才解决了这个问题。
由此可见,类似的问题在 GDI+ 的 C++ 封装中还有很多。所以,在 BCB 中使用 GDI+ 时,不要使用函数的默认参数,否则编译器可能会调错函数。
一个好的方法是将微软的 GDI+ 的标准 C++ 封装修改成 BCB 专用的定义封装。将所有 GDI+ 对象的名称前加一个前缀,这样就和 BCB 中的定义区分开了。然后将所有的缺省值取消掉,避免 BCB 的编译器无法识别它们。不过,这个工作量可是很大的哦!等有时间再慢慢来吧!