1.GDI+ 常用方法详解
来源:互联网 发布:昆明暴恐 中国公知 编辑:程序博客网 时间:2024/06/06 11:51
作为Windows图形系统基准的GDI存在诸多不足:Alpha通道支持较弱,不支持高级图像功能,抗锯齿能力差等等。为了解决这鞋问题,微软推出GDI+,使用非常方便,满足大多数场合需求。
需要指明的是,GDI+是构建于GDI上的基于CPU渲染的图形系统,所以尽管微软一直在优化,它的性能是比不上GDI的且实测发现XP上GDI+有一定概率崩溃,另外,GDI可以借助[GDI DDI驱动程序和显卡实现]完成硬件加速而GDI+不行。对于游戏等性能要求高的需求,微软推荐使用Direct2D和Direct3D,他们很好支持抗抗锯齿等高级特性且支持硬件加速。
下面详细说下GDI+ 常用方法的使用。
1.环境初始化
GDI+使用需要链接对应的链接库,使用完成后要反初始化环境。这里封装一个类,构造函数中完成初始化,析构函数中完成反初始化,使用时作为全局变量或类成员,即可自动完成这些过程,如下:
#pragma once//GDI+#include <GdiPlus.h>#include <GdiplusGraphics.h>#pragma comment(lib, "gdiplus.lib")using namespace Gdiplus;class CGdiplusInitHelper{public:CGdiplusInitHelper(){//gdi+初始化m_nGidToken = 0;Gdiplus::GdiplusStartupInput gdiplusStartupInput;GdiplusStartup(&m_nGidToken, &gdiplusStartupInput, NULL);}~CGdiplusInitHelper(){//gdi+卸载if ( 0 != m_nGidToken ){GdiplusShutdown( m_nGidToken );m_nGidToken = 0;}}private:ULONG_PTR m_nGidToken;};
2.常见图像绘制
和GDI 中dc对应的是GDI+中的Graphics。但是:
1.GDI是有状态的,GDI+是无状态的,比如GDI中要把当前画笔、画刷等选进dc,然后使用这些GDI图元来工作,GDI+中不一样,画笔、画刷、字体等等都是对象,我们只需要Graphics绘制时将对象作为参数传递即可。
2.GDI画矩形、圆等图形的副作用是会填充区域,要不填充区域必须使用NULL_BRUSH,GDI+中绘制边缘和填充是两个概念,另外GDI+支持的图形种类更多也更灵活
演示如下:
void DrawLines(HDC &hdc){Graphics g(hdc);Pen redP(Color(255,0,0), 2);g.DrawLine(&redP, 20, 20, 40, 60);redP.SetDashStyle(DashStyle::DashStyleDashDotDot);//线条样式g.DrawLine(&redP, 1, 10, 300, 20);Pen cyanP(Color::DarkCyan);g.DrawRectangle(&cyanP, 60,30,20,100);g.DrawEllipse(&cyanP, 60,30,20,100);Point pts[] = {Point(10,120), Point(60,200), Point(80,200), Point(90,90)};g.DrawPolygon(&cyanP, pts, 4);Pen pinkP(Color::HotPink);PointF pts2[] = {PointF(10.0f,220.0f), PointF(60.0f, 230.0f), PointF(50.0f, 250.0f)};g.DrawCurve(&pinkP, pts2, 3);Point pt1(10,300);Point pt2(50,400);Point pt3(100,350);Point pt4(30,250);g.DrawBezier(&pinkP, pt1, pt2, pt3, pt4);}//填充和绘制分开void FillShape(){Graphics g(m_hWnd);SolidBrush redB(Color(255,0,0));g.FillRectangle(&redB, 100,400,200,250);}
可以看到:
1.这里绘制时我们创建一个Pen对象,设置他的属性,然后Graphics绘制时作为参数
2.填充区域是Fill*函数,绘制图形是Draw*函数
3.路径和区域
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);}
4.文本绘制
void DrawText(HDC &hdc){Graphics g(hdc);Font myFont(L"Arial", 50, FontStyleItalic, UnitPixel);RectF layoutRect(10.0f, 10.0f, 197.0f, 50.0f);StringFormat format;format.SetAlignment(StringAlignmentCenter);//水平对齐format.SetLineAlignment(StringAlignmentCenter);//垂直对齐format.SetFormatFlags(StringFormatFlagsNoClip); //不截断format.SetHotkeyPrefix(HotkeyPrefixShow);//&前导符SolidBrush blackBrush(Color(255,0,0,0));LPCWSTR pszText = L"Out&putx Text";g.DrawString(pszText, -1, &myFont, layoutRect, &format, &blackBrush);g.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);//抗锯齿format.SetTrimming(StringTrimmingEllipsisCharacter);//结尾...layoutRect.Offset(0, 100);LPCWSTR pszText2 = L"Output Text Output Text Output Text Output Text";g.DrawString(pszText2, -1, &myFont, layoutRect, &format, &blackBrush);//测量指定文本大小RectF boundRect;g.MeasureString(pszText2, -1, &myFont, PointF(0,0), &boundRect);CString str;str.Format(L"W:%d-H:%d", boundRect.Width, boundRect.Height);OutputDebugString(str);//测量指定layoutRect宽度内,文本显示的个数、行数和包围框大小INT codepointsFitted = 0;INT linesFilled = 0;RectF layoutRect2(10.0f, 10.0f, 197.0f, 0.f);//高度必须为0才能自适应计算g.MeasureString(pszText2, -1, &myFont, layoutRect2, &format,&boundRect, &codepointsFitted, &linesFilled);}可以看到类似GDI,这里我们使用StringFormat控制输出文本的格式。g.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);指明字体抗锯齿输出。
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(InterpolationModeHighQualityBicubic)设置图像缩放时的插值方式,保证高质量显示。这里主要演示DrawImage使用,图像的加载和处理下一节再细述。
可在DrawImage时传入Attr参数,指定图像的色彩变换,具体参考API使用。
6.双缓冲绘制
GDI中我们都是通过创建一个兼容DC,一个兼容BMP,兼容BMP选入兼容DC绘制完成后,再将BMP一次性贴到实际DC上。
在GDI+中不用这么麻烦,GDI+将一切表面抽象,如果想在位图上绘制,直接将Graphics的表面选成位图即可,如下:
//双缓冲void DrawImages5(HDC &hdc){Bitmap bmp1(L".\\pop_bk.png");//内存绘图Bitmap bmpMem(bmp1.GetWidth(), bmp1.GetHeight());Graphics gMem(&bmpMem);//以内存Bitmap为表面绘图gMem.DrawImage(&bmp1, 0, 0);gMem.DrawRectangle(&Pen(Color::Black), 0,0,40,40);//一次性绘制到DCGraphics g(hdc);g.DrawImage(&bmpMem, 0, 0);}
测试程序下载链接
参考书籍《精通GDI+》,很多示例,可以当做手册查询
原创,转载请注明来自http://blog.csdn.net/wenzhou1219
- 1.GDI+ 常用方法详解
- C++ GDI+ DrawImage方法详解(绘制指定图像Image)
- C++ GDI+ DrawImage方法详解(绘制指定图像Image)
- fstream常用方法详解
- phpExcel常用方法详解
- fstream常用方法详解
- UIPickerView常用方法详解
- ByteBuffer常用方法详解
- ByteBuffer常用方法详解
- WebChromeClient常用方法详解
- ByteBuffer常用方法详解
- ByteBuffer常用方法详解
- 原型-----常用方法详解
- ByteBuffer常用方法详解
- HibernateTemplate常用方法详解
- PDO常用方法详解
- ByteBuffer常用方法详解
- AsyncTask常用方法详解
- NOIP 2008 Senior 4
- 注册登录展示数据
- Python-Day04-装饰器(2)
- C++中String类型的逆序
- Python chapter 6 learning notes
- 1.GDI+ 常用方法详解
- 直接排序算法
- 第 0004 题: 任一个英文的纯文本文件,统计其中的单词出现的个数
- Python chapter 7 learning notes
- SQL语句范例之索引和PLSQL
- Java:Collections框架
- XlistView
- [成长] 生病~
- LuoguP1720 月落乌啼算钱 解题报告【模拟+找规律/数学】