https://m.toutiao.com/is/ipqLJmE/ 前言:作为Windows图形系统的GDI存在诸多不足:Alpha通道支持较弱、不支持高级图像功能、抗锯齿能力差等。为了解决这些问题,微软推出GDI+,使用非常方便,满足大多数场合需求。需要指明的是,对于游戏等性能要求高的需求,微软推荐使用Direct2D和Direct3D,它们很好支持抗抗锯齿等高级特性且支持硬件加速。 基于GDI+绘制的Visual C++ MFC软件界面示例图 下面详细说下GDI+ 在Visual C++ MFC常用方法的使用。 1.环境初始化GDI+使用需要链接对应的链接库,在stdafx头文件中添加如下代码: //GDI+ 兼容Visual C++ 6.0#ifndef ULONG_PTR#define ULONG_PTR unsigned long*#endif#include 'gdiplus/GdiPlus.h'#pragma comment(lib, 'GdiPlus.lib')using namespace Gdiplus; 2.常见图像绘制和GDI 中dc对应的是GDI+中的Graphics。但是: 1.GDI是有状态的,GDI+是无状态的,比如GDI中要把当前画笔、画刷等选进dc,然后使用这些GDI图元来工作,GDI+中不一样,画笔、画刷、字体等等都是对象,我们只需要Graphics绘制时将对象作为参数传递即可。 2.GDI画矩形、圆等图形的副作用是会填充区域,要不填充区域必须使用NULL_BRUSH,GDI+中绘制边缘和填充是两个概念,另外GDI+支持的图形种类更多也更灵活 演示如下:
可以看到: 1.这里绘制时我们创建一个Pen对象,设置他的属性,然后Graphics绘制时作为参数 2.填充区域是Fill*函数,绘制图形是Draw*函数 3.路径和区域在GDI中使用路径,必须包含在BeginPath和EndPath中,使用非常不方便。在GDI+中路径GraphicPath、区域Region和其他图元(如Pen)一样, 都是基本的对象。如下: void DrawPathAndRegion(HDC &hdc){ PointF data[] = { PointF(40,140), PointF(275,200), PointF(105,255), PointF(50,350), PointF(20,180) }; BYTE typeline[] = { PathPointTypeLine, PathPointTypeLine, PathPointTypeLine, PathPointTypeLine, PathPointTypeLine }; GraphicsPath path1(data, typeline, 5); Graphics g(hdc); g.SetSmoothingMode(SmoothingModeAntiAlias);//绘制时反走样来消除锯齿 g.TranslateTransform(400., 0.); g.FillPath(&SolidBrush(Color::Red), &path1); g.TranslateTransform(300., 0.); GraphicsPath path2; FontFamily fontFamily(L'Arial'); path2.AddString(L'Add String', -1, &fontFamily, FontStyleRegular, 100, PointF(0,0), NULL); Pen pen(Color::Black); g.DrawPath(&pen, &path2); GraphicsState s = g.Save(); g.SetClip(&path2);//path做剪切区域 for (int i=0; i<100; i+=2) { g.DrawLine(&pen, 0, i, 600, i); } Region rgn(&path2); //路径转区域 g.Restore(s); //取消剪切区域 g.TranslateTransform(0., 100.); g.FillRegion(&SolidBrush(Color::Black), &rgn);} 可以看到这里路径path1由指定的点连成的线构成,路径path2由字体输出构成, setclip可以类似GDI设置当前绘图的剪切区域,这里我们用字体做剪切区域,效果就是在字体区域中间填充一系列的横线。 路径和区域可以互转。 另外,这里 g.SetSmoothingMode(SmoothingModeAntiAlias);指定绘制时反走样来消除锯齿,g.Save和g.Restore(s)可以完成Graphics的设置和恢复,g.TranslateTransform指明当前坐标系的平移变换(还支持旋转、缩放等高级变换功能)。 4.文本绘制GDI中DrawText来绘制文本和测量输出区域大小,GDI+提供了更强大的功能,而且支持字体的抗锯齿输出,如下:
可以看到类似GDI,这里我们 使用StringFormat控制输出文本的格式。 g.SetTextRenderingHint( 使用MeasureString测量文本输出大小,而且可以看到 指定包围盒高度为0时它可以根据宽度来完成自适应计算,计算出文本显示的个数、行数和包围框大小。 5.图像绘制GDI中图像功能有很多确定,只支持加载bmp格式,Alpha通道支持有限,图像处理功能较弱。GDI+很好的弥补了这一切。 GDI+支持BMP/TIFF/JPG/PNG/GIF等,且支持透明,GDI的AlphaBlend函数缩放时不支持抗锯齿,GDI+的DrawImage弥补了这些,如下: void DrawImages(HDC &hdc){ Graphics g(hdc); g.Clear(Color::WhiteSmoke);//清空当前背景 Image img1(L'.\\pop_bk.png'); PointF pt1(0.f, 0.f); g.DrawImage(&img1, pt1); g.SetInterpolationMode(InterpolationModeHighQualityBicubic);//设置插值模式,处理图像缩放 RectF rcDest(400.f,400.f,REAL(img1.GetWidth()), REAL(img1.GetHeight())); g.DrawImage(&img1, rcDest, 20.f,20.f,40.f,40.f, UnitPixel);} g.SetInterpolationMode( 可在DrawImage时传入Attr参数,指定图像的色彩变换,具体参考API使用。 6.双缓冲绘制GDI中我们都是通过创建一个兼容DC,一个兼容BMP,兼容BMP选入兼容DC绘制完成后,再将BMP一次性贴到实际DC上。 在GDI+中不用这么麻烦,GDI+将一切表面抽象,如果想在位图上绘制,直接将Graphics的表面选成位图即可,如下:
7.GDI+绘制示例程序8、结束语Visual C++ / MFC的世界,仍受不少IT专家和程序员的喜爱,话说微软提供的操作系统和开发工具,从兼容性上来说,小编认为是全球公认的第一,不亏IDE拳霸世界这么多年,九十年代发布的VC6.0代码工程可以快速无缝升级到VS2022。建议从事C++编程的老铁们尝试一下,Visual C++ MFC作为曾经的Windows桌面开发王者,在全球服务器省电趋势下,或者仍有全新的开始和保持生命力。 参考: |
|
来自: 山峰云绕 > 《c加加c井号面向对象》