赞
踩
GDI 是 Graphics Device Interface 的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有 Windows 程序的图形输出。
在 Windows 操作系统下,绝大多数具备图形界面的应用程序都离不开 GDI,我们利用 GDI 所提供的众多 API 就可以方便的在屏幕、打印机及其它输出设备上输出图形、文本等操作。
GDI 具有如下特点:
GDI 函数大致可分类为:
GDI+ 是 GDI 的后续版本,最早于 2000 年随 Windows 2000 一起推出,后来又被包装进 .NET 框架的托管类库中,成为 .NET 中窗体绘图的主要工具。
GDI+ 主要提供了以下三类服务:
GDI 接口是基于函数的,而 GDI+ 是基于 C++ OO 的编程接口,因此使用起来比 GDI 要方便。因为 GDI+ 实际上是 GDI 的封装和扩展,所以执行效率一般要低于 GDI。
GDI 的核心是设备上下文,GDI 函数都依赖于设备上下文句柄,其编程方式是基于句柄的;GDI+ 无需时刻依赖于句柄或设备上下文,用户只需创建一个 Graphics 对象,就可以用面向对象的方式调用其成员函数进行图形操作,编程方式是基于对象的。
GDI 在使用设备上下文绘制线条之前,必须先调用 SelectObject 以使钢笔对象和设备上下文关联。其后,在设备上下文中绘制的所有线条均使用该钢笔,直到选择另一支不同的钢笔为止。GDI 中有当前位置的概念,所以在使用 GDI 绘制线条前应该先使用MoveTo 移动当前位置,再使用 LineTo 画线。
CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
dc.SelectObject(pen.GetSafeHandle());
dc.MoveTo(0, 0);
dc.LineTo(100, 100);
在 GDI+ 中,只需将 Pen 对象直接作为参数传递给 Graphics 类的 DrawLine 等方法即可,而不必使 Pen 对象与 Graphics 对象关联。且 GDI+ 中则没有当前位置的概念,画线函数中可以直接指定起点和终点。
Pen myPen(Color::Red);
graphics.DrawLine(&myPen, 0, 0, rect.right, 0);
Direct2D 是一个基于 Direct3D 的 2D 图形 API,可以利用硬件加速特性来提供高性能、高质量的 2D 渲染。而且十分方便的是,Direct2D 与 GDI,GDI+ 和 D3D 都是可以交互的。一项技术总是有其受众面,看看微软怎么说的:
使用 Direct2D 渲染出来的效果要比 GDI 要好的多。因为 Direct2D 使用基于图元的反锯齿效果(这样会使线条更加的平滑),而且在渲染二维图元的时候,完全支持透明和 Alpha 混合。以下是对比的照片:
显然,右边的 Direct2D 的线条效果要好于左边的 GDI。
GDI 绘图代码:
void CChildView::_drawWithGDI( CPaintDC& dc ) { CRect rect; GetClientRect(&rect); // 绘制 title dc.TextOut(10, 10, _T("GDI"), 3); //逻辑坐标与设备坐标变换 dc.SetMapMode(MM_ANISOTROPIC); dc.SetWindowOrg(0, 0); dc.SetWindowExt(rect.right, rect.bottom); dc.SetViewportOrg(0, rect.bottom / 2); dc.SetViewportExt(rect.right, - rect.bottom); //创建绘制 x 轴的 pen 并将其选入设备上下文 CPen penx(PS_SOLID, 1, RGB(0, 0, 255)); HGDIOBJ oldObject = dc.SelectObject(penx.GetSafeHandle()); //绘制 x 轴 dc.MoveTo(0, 0); dc.LineTo(rect.right, 0); //创建绘制正旋曲线的 pen 并将其选入设备上下文 CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); dc.SelectObject(pen.GetSafeHandle()); //绘制正弦曲线 dc.MoveTo(0, 0); for (int i = 0; i < rect.right; i++) dc.LineTo(i, (int)(100 * sin(2 *(i / (rect.right / 5.0)) * M_PI))); //恢复原先的 pen dc.SelectObject(oldObject); // 恢复逻辑坐标与设备坐标变换 dc.SetViewportOrg(0, 0); dc.SetViewportExt(rect.right, rect.bottom); }
GDI+ 绘图代码:
void CChildView::_drawWithGDIPlus( CPaintDC& dc ) { using namespace Gdiplus; CRect rect; GetClientRect(&rect); Graphics graphics(dc); //创建渐变画刷 LinearGradientBrush lgb(Point(0, 0), Point(rect.right, rect.bottom), Color::Blue, Color::Purple); graphics.FillRectangle(&lgb, 0, 0, rect.right, rect.bottom); //创建ColorMatrix ColorMatrix ClrMatrix = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; //将 ColorMatrix 赋给 ImageAttributes ImageAttributes ImgAttr; ImgAttr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap); FontFamily fontFamily1(_T("Calibri")); Font font1(&fontFamily1, 12, FontStyleRegular, UnitPoint); //Alpha 混合 graphics.DrawString(_T("LENA"), 4, &font1, PointF(140.0f, 140.0f), &SolidBrush(Color::White)); TCHAR szImgPath[MAX_PATH] = {0}; //确保程序所在目录下存在 lena.png (res 文件夹下有) PathHelper::makeFullPathWithModuleDir(szImgPath, MAX_PATH, _T("lena.png")); Image img(szImgPath); graphics.DrawImage(&img, RectF(60, 140, 200, 200), 0, 0, (REAL)img.GetWidth(), (REAL)img.GetHeight(), UnitPixel, &ImgAttr); // 绘制 title graphics.DrawString(_T("GDI+"), 4, &font1, PointF(10.0f, 10.0f), &SolidBrush(Color::White)); }
Direct2D 绘制代码(部分):
HRESULT D2DImpl::render(HWND hwnd) { using namespace D2D1; HRESULT hr; hr = createDeviceResources(hwnd); RETURN_IF_FAILED(hr); int wndState = m_pRenderTarget->CheckWindowState(); RETURN_IF_TRUE(wndState & D2D1_WINDOW_STATE_OCCLUDED, E_FAIL); D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize(); // Prepare to draw. m_pRenderTarget->BeginDraw(); // Reset to identity transform m_pRenderTarget->SetTransform(Matrix3x2F::Identity()); m_pRenderTarget->Clear(ColorF(ColorF::Black)); TCHAR szTitle[] = _T("Direct2D"); m_pRenderTarget->DrawText( szTitle, _tcslen(szTitle), m_pTextFormat, D2D1::RectF(10, 10, rtSize.width, rtSize.height), m_pTextBrush); //center the path float minWidthHeightScale = min(rtSize.width, rtSize.height) / 512; Matrix3x2F scale = Matrix3x2F::Scale(minWidthHeightScale, minWidthHeightScale); Matrix3x2F translation = Matrix3x2F::Translation(rtSize.width / 2, rtSize.height / 2); m_pRenderTarget->SetTransform(scale * translation); //draw the path in red m_pRenderTarget->DrawGeometry(m_pPathGeometry, m_pRedBrush); static float float_time = 0.0f; float length = m_animation.GetValue(float_time); D2D1_POINT_2F point; D2D1_POINT_2F tangent; // Ask the geometry to give us the point that corresponds with the length at the current time. hr = m_pPathGeometry->ComputePointAtLength(length, NULL, &point, &tangent); // Reorient the triangle so that it follows the direction of the path. D2D1_MATRIX_3X2_F triangleMatrix = Matrix3x2F( tangent.x, tangent.y, -tangent.y, tangent.x, point.x, point.y ); m_pRenderTarget->SetTransform(triangleMatrix * scale * translation); // Draw the yellow triangle. m_pRenderTarget->FillGeometry(m_pObjectGeometry, m_pYellowBrush); // Commit the drawing operations. hr = m_pRenderTarget->EndDraw(); if (hr == D2DERR_RECREATE_TARGET) { hr = S_OK; discardDeviceResources(); } // When we reach the end of the animation, loop back to the beginning. if (float_time >= m_animation.GetDuration()) float_time = 0.0f; else float_time += (float)(m_dwmTiming.rateCompose.uiDenominator) / (m_dwmTiming.rateCompose.uiNumerator); InvalidateRect(hwnd, NULL, FALSE); return hr; }
– EOF –
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。