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 __func__
    Python 可变对象 & 不可变对象
    Kafka SASL ACL配置踩坑总结
    C++ 传递动态内存
    负数取反,单目运算“-”的运算
    C++重载运算符的理解
    c++ 随机函数用法
    static变量
    路由汇聚及其相关计算
  • 原文地址:https://www.cnblogs.com/riskyer/p/3221799.html
Copyright © 2011-2022 走看看