zoukankan      html  css  js  c++  java
  • Direct2D 几何图形绘制基础

    之前说过,D2D主要为了绘制有三种类型的数据:几何图形,图片,文字。这几种对象也叫做资源,资源就是要D2D流水线中要被加工的对象。

    几何图形包括

    • 简单几何图形
      • 直线DrawLine,由起点和终点构成,点用结构体:D2D1_POINT_2F描述。
      • 矩形,ID2D1RectangleGeometry,DrawRectangle,由距四条边的距离表示,用结构体:D2D1_RECT_F描述。
      • 圆角矩形,ID2D1RoundedRectangleGeometry ,DrawRoundedRectangle,同矩形,用结构体:D2D1_ROUNDED_RECT描述,另外还要加入圆角参数。
      • 椭圆,包括圆,ID2D1EllipseGeometry ,DrawEllipse,用结构体:D2D1_ELLIPSE 描述。
    • 路径,ID2D1PathGeometry 
    • 组合图形,
      • 几何图形组合,ID2D1GeometryGroup 
      • 变幻几何图形,ID2D1TransformedGeometry 

    准备绘制:

    在开始绘制之前,至少要准备好3样东西:
    • D2D工厂对象,ID2D1Factory接口。用于创建绘制目标,用方法CreateHwndRenderTarget。
    • 渲染窗口,ID2D1HwndRenderTarget接口。如果是Win32程序就是默认的HWND窗口,如果是商店应用则是一个绘制表面的控件。
      渲染窗口同时还负责着绘制几何图形,文字和图片。
    • 画刷,ID2D1SolidColorBrush接口。绘制几何图形时用于指定图形的样式。
    • 绘制区域,如果是win32程序还需要指定渲染窗口中要绘制的区域。
    首先要引入头文件和命名空间:
    #include "windows.h"
    #include "D2D1.h"
    
    using namespace D2D1;

    别忘了加要链接的Lib,要input的lib如下:
    d2d1.lib;
    dxgi.lib;
    dwrite.lib;
    dxguid.lib;
    windowscodecs.lib;

    声明以上4个对象的代码如下:
    	// Direct2D factory
    	ID2D1Factory* pD2DFactory; 
    	// Render target
    	ID2D1HwndRenderTarget* pRenderTarget;
    	// A black brush, reflect the line color
    	ID2D1SolidColorBrush* pBlackBrush; 
    	// Render area
    	RECT rc ; 
    初始化这些值的代码如下:
    	//create d2d factory
    	hr =  D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory) ;
    	//create render target (hwnd window)
    	GetClientRect(hWnd, &rc);
    	hr = pD2DFactory->CreateHwndRenderTarget( RenderTargetProperties(), HwndRenderTargetProperties(hWnd, SizeU(rc.right - rc.left, rc.bottom - rc.top)), &pRenderTarget);
    	//create brush
    	hr = pRenderTarget->CreateSolidColorBrush(ColorF(ColorF::Blue), &pBlackBrush);

    然后就可以开始绘制了。笔者使用的程序是win32应用程序,绘制的代码都必须写在WndProc回调函数的case WM_PAINT:之后,并且要将所有绘制代码都包含在pRenderTarget->BeginDraw();和pRenderTarget->EndDraw();之间。例如:
    	pRenderTarget->BeginDraw();
    
    	//clear screen
    	pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
    	//draw line with 2 points
    	D2D1_POINT_2F ptStart = Point2F(0,0);
    	D2D1_POINT_2F ptEnd = Point2F(100,100);
    	pRenderTarget->DrawLine(ptStart,ptEnd,pBlackBrush);
    	
    	//draw rectangle
    	D2D1_RECT_F rect  = RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f);
    	pRenderTarget->DrawRectangle(rect, pBlackBrush);
    
    	//draw round rect
    	D2D1_ROUNDED_RECT roundrect  = RoundedRect(RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f), 30.0f, 50.0f);
    	pRenderTarget->DrawRoundedRectangle(roundrect, pBlackBrush, 1.0f);
    
    	pRenderTarget->EndDraw();

    WM_PAINT是在窗口需要重绘时由系统调用的,所以我们不用主动地去调用它,它们不断地刷新的。
    当然了,把代码都积压在WM_PAINT之后也太SB了,最好自己封装一个类,如下:
    头文件如下:
    #pragma once
    
    #include "stdafx.h"
    #include "windows.h"
    #include "D2D1.h"
    
    using namespace D2D1;
    
    class D2DRender
    {
    public:
    	D2DRender(void);
    	~D2DRender(void);
    	
    	HRESULT CreateDeviceIndependentResources();
    	HRESULT CreateDeviceResources(HWND hWnd);
    	void OnRender();
    	void DiscardDeviceResources();
    	void OnResize(UINT width, UINT height);
    
    private:
    	// Direct2D factory
    	ID2D1Factory* pD2DFactory; 
    	// Render target
    	ID2D1HwndRenderTarget* pRenderTarget;
    	// A black brush, reflect the line color
    	ID2D1SolidColorBrush* pBlackBrush; 
    	// Render area
    	RECT rc ; 
    	//result
    	HRESULT hr;
    };
    
    实现如下:
    #include "stdafx.h"
    #include "D2DRender.h"
    
    D2DRender::D2DRender()
    {
    	// Direct2D factory
    	pD2DFactory = NULL; 
    	// Render target
    	pRenderTarget = NULL;
    	// A black brush, reflect the line color
    	pBlackBrush = NULL; 	
    }
    
    D2DRender::~D2DRender()
    {
    	pD2DFactory->Release();
    	pRenderTarget->Release();
    	pBlackBrush->Release();
    
    }
    
    void D2DRender::DiscardDeviceResources()
    {
    	pD2DFactory->Release();
    	pRenderTarget->Release();
    	pBlackBrush->Release();
    }
    
    
    void D2DRender::OnResize(UINT width, UINT height)
    {
    	if(pRenderTarget)
    	{
    		pRenderTarget->Resize(SizeU(width,height));
    	}
    }
    
    HRESULT D2DRender::CreateDeviceIndependentResources()
    {
    	//create d2d factory
    	hr =  D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory) ;
    
    	return hr;
    }
    
    HRESULT D2DRender::CreateDeviceResources(HWND hWnd)
    {
    	//create render target (hwnd window)
    	GetClientRect(hWnd, &rc);
    	hr = pD2DFactory->CreateHwndRenderTarget( RenderTargetProperties(), HwndRenderTargetProperties(hWnd, SizeU(rc.right - rc.left, rc.bottom - rc.top)), &pRenderTarget);
    
    	//create brush
    	hr = pRenderTarget->CreateSolidColorBrush(ColorF(ColorF::Blue), &pBlackBrush);
    
    	return hr;
    }
    
    void D2DRender::OnRender()
    {
    	pRenderTarget->BeginDraw();
    
    	//clear screen
    	pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
    	//draw line with 2 points
    	D2D1_POINT_2F ptStart = Point2F(0,0);
    	D2D1_POINT_2F ptEnd = Point2F(100,100);
    	pRenderTarget->DrawLine(ptStart,ptEnd,pBlackBrush);
    	
    	//draw rectangle
    	D2D1_RECT_F rect  = RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f);
    	pRenderTarget->DrawRectangle(rect, pBlackBrush);
    
    	//draw round rect
    	D2D1_ROUNDED_RECT roundrect  = RoundedRect(RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f), 30.0f, 50.0f);
    	pRenderTarget->DrawRoundedRectangle(roundrect, pBlackBrush, 1.0f);
    
    	pRenderTarget->EndDraw();
    }
    
    
    
    

    然后在WM_PANIT里调用,默认生成的gdi绘制用到的hdc相关代码可以删掉。
    	case WM_PAINT:
    		//hdc = BeginPaint(hWnd, &ps);
    		D2DRender pRender;
    		pRender.CreateDeviceIndependentResources();
    		pRender.CreateDeviceResources(hWnd);
    		pRender.OnRender();
    		//EndPaint(hWnd, &ps);
    		break;

    还是比较简单。

  • 相关阅读:
    python 基础2.5 循环中continue与breake用法
    python 基础 2.4 while 循环
    python 基础 2.3 for 循环
    python 基础 2.2 if流程控制(二)
    python 基础 2.1 if 流程控制(一)
    python 基础 1.6 python 帮助信息及数据类型间相互转换
    python 基础 1.5 python数据类型(四)--字典常用方法示例
    Tornado Web 框架
    LinkCode 第k个排列
    LeetCode 46. Permutations
  • 原文地址:https://www.cnblogs.com/riskyer/p/3221799.html
Copyright © 2011-2022 走看看