张晓慧, 徐向文, 姚恒传
(1.上海船舶运输科学研究所 舰船自动化分所,上海 200135; 2.苏州杜科设备工程有限公司,江苏 昆山 215300)
随着计算机技术的发展,监控系统对界面显示的要求也从简单的文字显示转化为以图形界面为主,显示风格从简单的WINDOWS灰白界面向多种显示基色发展,对显示内容也提出了更高的要求。由于通用WINDOWS提示在显示时会挡住一部分正常显示界面,这样就有用户提出了在提示窗进行半透明显示的要求。
图形设备接口+(GraphicsDeviceInterfacePlus,GDI+)是微软的.NET Framework类库的组成部分,用于图形编程。在微软以前的开发工具中,使用GDI进行图形编程,相当复杂,而GDI+是GDI的包装器,简化了图形程序设计任务。GDI+与GDI的不同之处在于不仅提供了很多新功能,如像素消除锯齿技术,渐变画笔,变形和矩阵对象,独立的路径对象、基数样条、对多图像格式的支持和Alpha混合等;更重要的是它改变了编程模型,GDI是基于句柄的而GDI+是基于对象模型的。使用GDI+,只需创建1个Graphics对象,然后以熟悉的面向对象样式调用其方法,而没有必要去考虑句柄和设备环境(DeviceContext)的概念。设备环境位于GDI的核心,Graphics对象也位于GDI+核心,其作用相似, 但在使用设备环境的基于句柄的编程模式和使用Graphics对象的基于面向对象的编程模型之间,存在一些基本的差异。Graphics对象(和设备环境一样)与屏幕上特定的窗口关联,并具有指定如何绘制项目的属性(如SmoothingMode),但是,Graphics对象不受钢笔、画笔、路径、图像或字体的约束,这与设备环境不同,例如,使用设备环境绘制线条之前,必须先调用SelectObject以使钢笔对象和设备环境关联,将钢笔选入设备环境中。在设备环境中绘制的所有线条均使用该钢笔(只有一支画笔是可以使用的),直到选择另一支不同的钢笔为止。而在GDI+中,将Pen对象作为参数传递给Graphics类的DrawLine方法,可以在一系列DrawLine调用的每个调用中使用不同的Pen对象,而不必使给定的Pen对象和Graphics对象关联。也就是说,在GDI+中,可以同时使用多个画笔进行不同的绘图操作[1]。
要实现透明显示,可在VC(Microsoft Visual C++)开发环境下使用GDI+技术完成。
由于VC6.0 本身并不带有GDI+函数库,需要下载GDI+函数库,在工程目录下建立GdiFiles目录,将下载的GDI+文件拷贝到该目录下,并使工程包含GdiFilesGdiPlus.lib库文件,包含gdiplus.h头文件,并为GDI+申请using namespace Gdiplus。这样就能在VC6.0中使用GDI+。
在VC2010中由于开发工具已包含GDI+,因此可直接使用。
在使用GDI+库前必须先向系统注册,使用语句为:
Gdiplus::GdiplusStartupInput gdiplusStartupInput
然后初始化GDI+相关句柄,使用语句为:
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL)
在程序退出前必须注销GDI+,使用语句为:
Gdiplus::GdiplusShutdown(m_gdiplusToken)
使用GDI+库,建立与显示关联的graphics指针
Graphics graphics(pDC->m_hDC).
设置半透明显示的底色
COLORREF col = RGB(250,250,250)
设置半透明显示的文字色
COLORREF coltxt = RGB(0,0,0)
设置半透明度
int fillair=150;(透明度范围在0-255,值越小透明度越高)
建立半透明画刷
SolidBrush brush(Color(Color::MakeARGB(BYTE(fillair), GetRValue(col), GetGValue(col), GetBValue(col)))) 创建笔刷,第一项是透明度,后三项是RGB值
建立半透明区域 Rect rcFill(25,25,200,100),其参数为left,top,Width,Height
显示半透明区域 graphics.FillRectangle(&brush, rcFill)
建立半透明画刷
SolidBrush brush1(Color(Color::MakeARGB(BYTE(fillair), GetRValue(coltxt), GetGValue(coltxt), GetBValue(coltxt)))) 创建一个笔刷,第一项是透明度,后三项是RGB值
选择显示文字字体
FontFamily fontFamily(L"Latha")
设置字体大小和显示风格
Font font(&fontFamily,0.15,FontStyleRegular,UnitInch)
设置显示位置
PointF pointF(25,25)
显示提示信息
graphics.DrawString(L"测点信息:",-1,&font,pointF,&brush1)
pointF.Y=pointF.Y+20;
graphics.DrawString(L"1#发电机曲轴箱进口滑油温度",-1,&font,pointF,&brush1);
pointF.Y=pointF.Y+20;
graphics.DrawString(L"安装部位:",-1,&font,pointF,&brush1);
pointF.Y=pointF.Y+20;
graphics.DrawString(L"1#电站1#发电机曲轴",-1,&font,pointF,&brush1);
按照上述步骤进行编程,执行效果见图1。
图1
完成以上步骤,就能实现提示窗体的半透明显示,并且显示的透明度还可自由调节。但在实际应用中还会遇到以下问题:由于半透明显示时GDI系统将会取得该区域屏幕显存,如果用户定时对屏幕进行画屏显示操作,由于获取的是上次已显示的半透明显存,叠加后会产生显示透明度逐渐加深的情况。解决这一问题的方法是使用显示双缓冲[3]的方法。双缓冲就是除了在屏幕上有图形进行显示以外,在内存中也有图形在绘制。可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上。这样在内存中绘图时,由于内存中的图形未进行半透明显示,所以可以避免叠加效果。
参考文献:
[1] 李顺亮,王新辉,钟碧良.应用GDI+和C#开发船舶压载水监控系统控件[J].广州航海高等专科学校学报,2012,20(1):4-6.
[2] 於文雪,李松毅,罗立民.基于Windows GDI的图形图像处理探讨[J].计算机工程,2003,29(2):270-272.
[3] 韩丽娜,石昊苏.使用双缓存来解决GDI下的闪烁问题[J].计算机工程与设计,2006,27(17):3257-3260.