本小节主要介绍如何使用Direct2D来绘制几何图形,其中会使用到FillGeometry函数和FillEllipse函数,FillGeometry函数用于填充几何图形的内部区域,而FillEllipse函数则专门用于填充椭圆的内部区域。下面将分别来介绍如何使用FillGeometry函数和FillEllipse函数在应用窗口中绘制简单的三角形和圆形。

1.使用FillGeometry函数绘制三角形

本示例中所要添加的代码比较多,为了让读者能更为清晰地了解如何使用Direct2D绘制几何图形,下面将分为四部分来介绍使用FillGeometry函数绘制三角形的步骤。其中第一部分首先介绍如何新建Direct2D中的资源,第二部分紧接着介绍如何初始化和激活应用窗口,接下来在第三部分中具体来介绍使用FillGeometry函数绘制三角形的方法,最后一部分将介绍如何为项目添加主入口函数,以便于项目能正常运行。

(1)新建Direct2D资源

在使用FillGeometry函数绘制几何图形之前,首先需要新建Direct2D资源,这些资源包括独立于设备的资源和依赖于设备的资源。Direct2D中独立于设备的资源包括ID2D1Factory工厂接口、IDWriteFactory工厂接口、ID2D1Geometry接口和ID2D1GeometrySink接口等,在显示设备发生改变时这些资源不会被重新创建,如显示设备的分辨率发生改变,以及远程桌面连接断开等。下面列举出了Direct2D中常用的独立于设备的资源:

  • ID2D1Factory工厂接口,用于新建Direct2D中的资源。
  • IDWriteFactory工厂接口,用于创建DirectWrite类的对象。
  • ID2D1Geometry接口,绘制弧线、曲线和线段所需的接口。
  • ID2D1GeometrySink接口,绘制线段、弧线、三次方和二次方贝塞尔曲线所需的接口。

Direct2D中依赖于设备的资源包括ID2D1Brush接口、ID2D1Layer接口、ID2D1RenderTarget接口和ID2D1DeviceContext接口等,这些资源会在GPU可用的情况下直接映射到GPU上,并且当显示设备发生改变时将会重新创建这些资源。下面列举出了Direct2D中常用的依赖于设备的资源:

  • ID2D1SolidColorBrush接口,用于绘制纯色区域的画刷。
  • ID2D1Layer接口,实现图层的接口。
  • ID2D1RenderTarget接口,用于渲染图形的接口。
  • ID2D1DeviceContext接口,继承自ID2D1RenderTarget的接口。

在Visual Staudio 2012中新建一个Visual C++的Windows应用商店的Direct3D应用程序项目,并命名为Direct2DDemo。由于本示例中并没有用到Direct3D应用程序项目默认的绘图代码,读者可以分别右键点击BasicTimer.h、CubeRenderer.cpp、CubeRenderer.h、Direct2DDemo.cpp、Direct2DDemo.h、Direct3DBase.cpp、Direct3DBase.h、SimplePixelShader.hlsl和SimpleVertexShader.hlsl文件,并在弹出的菜单栏中选中"移除",将这些不必要的文件从项目中移除掉,以保证在本示例中所要添加的代码不会和项目中默认的代码产生冲突。

接着打开pch.h头文件,并引用如下的头文件,在使用Direct2D绘制图形的过程中将会用到定义在这些头文件中的类。

#include <wrl.h>

#include <d3d11_1.h>

#include <d2d1_1.h>

#include <d2d1effects.h>

#include <d2d1_1helper.h>

#include <dwrite_1.h>

#include <wincodec.h>

#include <math.h>

#include <agile.h>

引用了上面的头文件以后,接下来在解决方案资源管理器窗口中右键点击项目图标,在弹出的菜单栏中选中"添加", 并在"添加"的子菜单栏中选择"新建项",在出现的"添加新项"窗口中选中"C++ 文件(.cpp)",添加名为"DirectXBase.cpp"的源文件。然后使用同样的方法在"添加新项"窗口中选中"头文件(.h)",添加名为"DirectXBase.h"的头文件。这里新建Direct2D资源的实现代码以及第二部分中用于初始化应用窗口的实现代码将添加在DirectXBase.cpp源文件中,而DirectXBase.h头文件则用于声明在DirectXBase.cpp源文件中使用到的函数和变量。

下面来介绍如何新建Direct2D中独立于设备的资源,首先打开DirectXBase.h头文件,并添加如下代码用于定义一个DirectXBase类。

#include "DirectXHelper.h"

ref class DirectXBase abstract

{

internal:

    //声明构造函数DirectXBase

    DirectXBase();

};

定义了DirectXBase类以后,接下来在此类中添加如下的代码,用于声明在创建独立于设备的资源的过程中使用到的成员变量和函数。

protected private:

    //声明成员变量d2dFactory

    Microsoft::WRL::ComPtr<ID2D1Factory1> d2dFactory;

    //声明成员变量dwriteFactory

    Microsoft::WRL::ComPtr<IDWriteFactory> dwriteFactory;

    //声明成员变量wicFactory

    Microsoft::WRL::ComPtr<IWICImagingFactory> wicFactory;

internal:

    //声明CreateDeviceIndependentResources函数

    void CreateDeviceIndependentResources();

在上面的代码中,使用protected private关键字声明三个受保护的私有成员变量,分别为d2dFactory、dwriteFactory和wicFactory,其中d2dFactory为ID2D1Factory1类型的指针,dwriteFactory为IDWriteFactory类型的指针,wicFactory为IWICImagingFactory类型的指针。然后使用internal关键字声明内部访问的CreateDeviceIndependentResources函数,用于新建Direct2D中独立于设备的资源。

声明了上述的成员变量和CreateDeviceIndependentResources函数以后,接下来实现CreateDeviceIndependentResources函数。首先打开DirectXBase.cpp源文件,并添加如下的代码,引用DirectXBase.h头文件和pch.h头文件。

#include "pch.h"

#include "DirectXBase.h"

接下来在DirectXBase.cpp源文件中引用如下的命名空间,新建Direct2D中独立于设备的资源时将会用到定义在这些命名空间中的类。代码如下所示:

using namespace Windows::UI::Core;

using namespace Windows::Foundation;

using namespace Microsoft::WRL;

using namespace Windows::Graphics::Display;

using namespace D2D1;

添加了上述的代码以后,在DirectXBase.cpp源文件中添加CreateDeviceIndependentResources函数的实现代码,具体代码如下所示:

// 新建独立于设备的资源

void DirectXBase::CreateDeviceIndependentResources()

{

    //ID2D1Factory的调试级别

    D2D1_FACTORY_OPTIONS options;

    ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));

#if defined(_DEBUG)

    options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;

#endif

    //得到ID2D1Factory1类型的对象

    DX::ThrowIfFailed(

        D2D1CreateFactory(

            D2D1_FACTORY_TYPE_SINGLE_THREADED,

            __uuidof(ID2D1Factory),

            &options,

            &d2dFactory

        )

    );

    //得到IDWriteFactory1类型的对象

    DX::ThrowIfFailed(

        DWriteCreateFactory(

            DWRITE_FACTORY_TYPE_SHARED,

            __uuidof(IDWriteFactory),

            &dwriteFactory

        )

    );

    //得到IWICImagingFactory2类型的对象

    DX::ThrowIfFailed(

        CoCreateInstance(

            CLSID_WICImagingFactory,

            nullptr,

            CLSCTX_INPROC_SERVER,

            IID_PPV_ARGS(&wicFactory)

        )

    );

}

在上面的代码中,首先声明D2D1_FACTORY_OPTIONS结构体的变量options,此结构体变量用于存储ID2D1Factory类的对象的调试级别,并将options结构体变量作为参数传递给ZeroMemory函数,用来为此结构体变量分配内存空间。当程序出现异常时,将options结构体变量的成员debugLevel赋值为D2D1_DEBUG_LEVEL_INFORMATION,设置ID2D1Factory类的对象的调试级别为向调试层发送错误信息、警告和其他有助于提高性能的诊断信息。接着以options结构体变量作为参数调用D2D1CreateFactory函数得到ID2D1Factory1类型的对象,使用d2dFactory指针指向这个对象。接下来调用DWriteCreateFactory函数得到IDWriteFactory1类型的对象,使用dwriteFactory指针指向这个对象。最后调用CoCreateInstance函数得到一个IWICImagingFactory2类型的对象,并使用wicFactory指针指向这个对象。

新建了Direct2D中独立于设备的资源以后,接下来新建Direct2D中依赖于设备的资源。在DirectXBase.h头文件的DirectXBase类中添加如下代码:

protected private:

    //声明成员变量d2dDevice

    Microsoft::WRL::ComPtr<ID2D1Device> d2dDevice;

    //声明成员变量d2dContext

    Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2dContext;

    //声明成员变量d3dDevice

    Microsoft::WRL::ComPtr<ID3D11Device> d3dDevice;

    //声明成员变量d3dContext

    Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3dContext;

    //声明成员变量swapChain

    Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;

    //声明成员变量featureLevel

    D3D_FEATURE_LEVEL featureLevel;

internal:

    //声明CreateDeviceResources函数

    virtual void CreateDeviceResources();

在上面的代码中,使用protected private关键字声明六个受保护的私有成员变量d2dDevice、d2dContext、d3dDevice、d3dContext、swapChain和featureLevel。然后使用internal关键字声明内部访问的CreateDeviceResources函数,用于新建Direct2D中依赖于设备的资源,另外需要注意的是这里使用virtual关键字将CreateDeviceResources函数声明为虚函数,以便于能在DirectXBase类的子类中重写此函数。

添加了上述的代码以后,接下来在DirectXBase.cpp源文件中添加CreateDeviceResources函数的实现代码,具体代码如下所示:

// 以下是依赖设备的资源

void DirectXBase::CreateDeviceResources()

{

    // 此标志为与 API 默认设置具有不同颜色渠道顺序的图面添加支持

    // 要与 Direct2D 兼容,必须满足此要求

    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

    ComPtr<IDXGIDevice> dxgiDevice;

#if defined(_DEBUG)

    // 如果项目处于调试生成过程中,请通过带有此标志的 SDK 层启用调试

    creationFlags |= D3D11_CREATE_DEVICE_DEBUG;

#endif

    // DirectX硬件特性级别

    D3D_FEATURE_LEVEL featureLevels[] =

    {

        D3D_FEATURE_LEVEL_11_1,

        D3D_FEATURE_LEVEL_11_0,

        D3D_FEATURE_LEVEL_10_1,

        D3D_FEATURE_LEVEL_10_0,

        D3D_FEATURE_LEVEL_9_3,

        D3D_FEATURE_LEVEL_9_2,

        D3D_FEATURE_LEVEL_9_1

    };

    //得到ID3D11Device和ID3D11DeviceContext类型的对象

    DX::ThrowIfFailed(

        D3D11CreateDevice(

            nullptr,

            D3D_DRIVER_TYPE_HARDWARE,

            0,

            creationFlags,

            featureLevels,

            ARRAYSIZE(featureLevels),

            D3D11_SDK_VERSION,

            &d3dDevice,

            &featureLevel,

            &d3dContext

        )

    );

    DX::ThrowIfFailed(

        d3dDevice.As(&dxgiDevice)

    );

    //得到ID2D1Device类型的对象

    DX::ThrowIfFailed(

        d2dFactory->CreateDevice(dxgiDevice.Get(), &d2dDevice)

    );

    DX::ThrowIfFailed(

        d2dDevice->CreateDeviceContext(

            D2D1_DEVICE_CONTEXT_OPTIONS_NONE,

            &d2dContext

        )

    );

    //swapChain赋值为空指针

    swapChain = nullptr;

}

在上面的代码中,首先声明UINT类型的变量creationFlags,并将其赋值为D3D11_CREATE_DEVICE_BGRA_SUPPORT用来表示Direct2D可以共享Direct3D中的资源,接着定义D3D_FEATURE_LEVEL类型的数组featureLevels用来储存应用程序支持的DirectX硬件特性级别。然后以creationFlags变量和featureLevels数组作为参数调用D3D11CreateDevice函数,得到ID3D11Device类型的对象和ID3D11DeviceContext类型的对象,使用d3dDevice指针指向ID3D11Device类型的对象,d3dContext指针指向ID3D11DeviceContext类型的对象。

接下来调用d2dFactory指针所指向的对象的CreateDevice函数得到一个ID2D1Device类型的对象,并使用d2dDevice指针指向这个对象。接着调用d2dDevice指针所指向的对象的CreateDeviceContext函数得到一个ID2D1DeviceContext类型的对象,使用d2dContext指针指向这个对象,最后将swapChain指针赋值为空指针。

Win10系列:VC++绘制几何图形1的更多相关文章

  1. Win10系列:VC++绘制几何图形2

    新建了Direct2D中的资源后,接下来初始化用于绘制图形的应用窗口.在解决方案资源管理器窗口中右键点击项目图标,在弹出的菜单栏中选中"添加", 并在"添加"的 ...

  2. Win10系列:VC++绘制几何图形5

    打开D2DBasicAnimation.h头文件,并在D2DBasicAnimation类中添加如下的代码: private:     //声明成员变量point     D2D1_POINT_2F ...

  3. Win10系列:VC++绘制几何图形4

    三角形绘制完成以后,接下来介绍如何给项目添加主入口函数.打开D2DBasicAnimation.h头文件,添加如下的代码定义一个DirectXAppSource类. //定义类DirectXAppSo ...

  4. Win10系列:VC++绘制几何图形3

    在绘制三角形之前,首先需要创建一个三角形,打开D2DBasicAnimation.h头文件,在D2DBasicAnimation类中添加如下的代码: private:     //声明成员变量obje ...

  5. Cocos2D中使用CCDrawNode绘制几何图形崩溃的解决

    在cocos2D v3.x中已经不能像在v2.x中那样直接调用ccDrawXXX函数来绘制几何图形了. 我们可以使用CCDrawNode或者CCRenderer来绘制图形. 但是官方的Api手册中说的 ...

  6. Win10系列:C#应用控件进阶9

    RectangleGeometry 在使用RectangleGeometry控件绘制矩形时,矩形的位置和尺寸由Rect属性定义,该属性指定矩形的相对位置.高度和宽度.Rect有四个参数,前两个参数表示 ...

  7. Win10系列:C#应用控件进阶6

    路径 路径(Path)可以用来定义任意形状的曲线和几何图形,当然这种任意性也带来了复杂性.为了方便的绘制几何图形,微软在Visual Studio 2012安装包中为程序开发者提供了免费的Blend ...

  8. Win10系列:C#应用控件进阶7

    PathGeometry 前面介绍了Path的使用方法,接下来介绍PathGeometry类.PathGeometry提供了描绘由弧线.曲线和直线组成的多个复杂图形的方法.PathGeometry的核 ...

  9. HTML5绘制几何图形

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>    < ...

随机推荐

  1. arcgis 属性表字段值计算

    1 如果你用VBSCRIPT的代码,那就在对应的选择项目处选择下,如果是PYTHON代码,就在另外一点点一下.如果弄混了,显然代码会报错. 2 VBSCRIPT里面的函数非常少,但是你可以去利用这些函 ...

  2. top 命令常用操作

    1.显示进程参数 top -c 下面操作为top命令后操作 2.按cpu/mem排序 shift + p/m 3.高亮 排序列 按x键 4.高亮 变化进程行 按b键 5.显示cpu每核的运行状态 按1 ...

  3. Python数据分析-Day1-Numpy模块

    1.numpy.genfromtxt读取txt文件 import numpyworld_alcohol = numpy.genfromtxt("world_alcohol.txt" ...

  4. springboot---->获取不到yml配置文件指定的值

    import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.Spr ...

  5. hihocoder-1415 后缀数组三·重复旋律3 两个字符串的最长公共子串

    把s1,s2拼接,求Height.相邻的Height判断左右串起点是否在两个串中,另外对Height和s1.length()-SA[i-1]取min. #include <iostream> ...

  6. 通过.frm和.ibd恢复mysql数据

    .frm文件:保存了每个表的元数据,包括表结构的定义等: .ibd文件:InnoDB引擎开启了独立表空间(my.ini中配置innodb_file_per_table = 1)产生的存放该表的数据和索 ...

  7. thinkphp5的生命周期

    1.入口文件 虚拟主机目录/public/index.php 2.引入启动文件 虚拟主机目录/thinkphp/start.php 3.运行App下面的run方法 虚拟主机目录/thinkphp/li ...

  8. pycharm配置appium 提示unsrsloved reference

    1.如:进入C:\Users\Administrator\PycharmProjects\project\venv 输入:在cmd 下进入 venv  输入   Scripts\activate 回车 ...

  9. 日期在Linux与Windows下的区别

    最近遇到了这个问题,就是相同的代码在Windows与Linux下的日期转换不一致. 原因:时区问题,主要是操作系统与JVM中的时区不同导致的 在网上查了很多处理的方法:最后总结出一条简单粗暴的方法:原 ...

  10. kohana task 编写计划任务

    kohana 框架  我们经常使用gleez作为我们二次开发. 收先我们要把文件建在Task文件夹下,比如新建文件为:testcron <?phpdefined('SYSPATH') or di ...