新建了Direct2D中的资源后,接下来初始化用于绘制图形的应用窗口。在解决方案资源管理器窗口中右键点击项目图标,在弹出的菜单栏中选中"添加", 并在"添加"的子菜单栏中选择"新建项",在出现的"添加新项"窗口中选中"C++ 文件(.cpp)",添加名为"D2DBasicAnimation.cpp"的源文件。然后使用同样的方法在"添加新项"窗口中选中"头文件(.h)",添加名为"D2DBasicAnimation.h"的头文件。在本示例中用于激活应用窗口的实现代码,绘制几何图形的实现代码以及项目的主入口函数的实现代码将添加到D2DBasicAnimation.cpp源文件中,而D2DBasicAnimation.h头文件则用于声明在D2DBasicAnimation.cpp源文件中使用到的函数和变量。

添加了D2DBasicAnimation.h头文件和D2DBasicAnimation.cpp源文件以后,接下来打开D2DBasicAnimation.h头文件,并添加如下的代码定义一个D2DBasicAnimation类。

#include "DirectXBase.h"

#include "DirectXHelper.h"

//定义类D2DBasicAnimationD2DBasicAnimation继承DirectXBase类和IFrameworkView接口

ref class D2DBasicAnimation : public DirectXBase, public Windows::ApplicationModel::Core::IFrameworkView

{

internal:

//构造函数

D2DBasicAnimation();

internal:

// 重写DirectXBase中的CreateDeviceResources函数

virtual void CreateDeviceResources() override;

public:

// 实现 IFrameworkView 中的函数

//激活应用窗口

virtual void Initialize(_In_ Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);

//初始化应用窗口

virtual void SetWindow(_In_ Windows::UI::Core::CoreWindow^ window);

//Run函数调用前加载视图所使用的资源

virtual void Load(_In_ Platform::String^ entryPoint);

//用于绘制三角形

virtual void Run();

virtual void Uninitialize();

};

在上面的代码中,首先使用include关键字引用DirectXBase.h头文件和DirectXHelper.h头文件,接着定义D2DBasicAnimation类,此类继承自DirectXBase类并实现IFrameworkView接口。在D2DBasicAnimation类中,声明构造函数D2DBasicAnimation,并重写DirectXBase类的CreateDeviceResources函数,此函数的实现代码将在第三部分进行介绍。在IFrameworkView接口中声明了Initialize函数、SetWindow函数、Load函数、Run函数和Uninitialize函数,为了实现这些函数,需要先在D2DBasicAnimation类中进行声明。

本部分将介绍Initialize函数、SetWindow函数、Load函数和Uninitialize函数的实现代码,其中SetWindow函数和Initialize函数分别用于初始化应用窗口和激活应用窗口,而在本示例中Run函数用于绘制几何图形,此函数的实现代码将在第三部分进行介绍。另外要注意的是为了避免程序出现异常,需要在CreateDeviceResources函数、Initialize函数、SetWindow函数、Load函数、Run函数和Uninitialize函数之前添加virtual关键字。

定义了D2DBasicAnimation类以后,接下来介绍如何初始化应用窗口。首先打开D2DBasicAnimation.cpp源文件,并引用如下的头文件和命名空间,在初始化和激活应用窗口时将会使用到定义在这些头文件和命名空间中的类。

#include "pch.h"

#include "D2DBasicAnimation.h"

using namespace Microsoft::WRL;

using namespace Windows::ApplicationModel;

using namespace Windows::ApplicationModel::Core;

using namespace Windows::ApplicationModel::Activation;

using namespace Windows::UI::Core;

using namespace Windows::System;

using namespace Windows::Foundation;

using namespace Windows::Graphics::Display;

using namespace D2D1;

引用上述的头文件和命名空间以后,接着在D2DBasicAnimation.cpp源文中添加Load函数和Uninitialize函数的实现代码,虽然在本示例中Load函数和Uninitialize函数并没有实现任何功能,但仍需要添加这两个函数的实现代码,保证项目运行时不会出现异常。代码如下所示:

//Load函数实现代码

void D2DBasicAnimation::Load(_In_ Platform::String^ entryPoint)

{

}

//Uninitialize函数实现代码

void D2DBasicAnimation::Uninitialize()

{

}

添加了Load函数和Uninitialize函数的实现代码以后,接下来在D2DBasicAnimation.cpp源文中添加SetWindow函数的实现代码,在此函数中将调用DirectXBase类的Initialize函数来初始化应用窗口。具体代码如下所示:

//初始化窗口

void D2DBasicAnimation::SetWindow(_In_ CoreWindow^ window)

{

DirectXBase::Initialize(window, DisplayProperties::LogicalDpi);

}

本示例将DirectXBase类的Initialize函数的实现代码添加在DirectXBase.cpp源文件中,为了实现此函数,首先打开DirectXBase.h头文件,并在DirectXBase类中添加如下代码用来声明window变量和Initialize函数。

protected private:

//声明成员变量window

Platform::Agile<Windows::UI::Core::CoreWindow> window;

internal:

//初始化应用窗口

void Initialize(Windows::UI::Core::CoreWindow^ window, float dpi);

声明了Initialize函数以后,接着在DirectXBase.cpp源文件中添加Initialize函数的实现代码,具体代码如下所示:

//初始化应用窗口

void DirectXBase::Initialize(CoreWindow^ coreWindow, float dpi)

{

//window变量赋值

window = coreWindow;

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

CreateDeviceIndependentResources();

//新建依赖于设备的资源

CreateDeviceResources();

//设置Direct2D设备上下文的DPI

SetDpi(dpi);

}

在上面的代码中,首先将Initialize函数的参数coreWindow赋值给window变量,然后调用CreateDeviceIndependentResources函数和CreateDeviceResources函数分别新建独立于设备的资源和依赖于设备的资源,最后调用SetDpi函数来设置Direct2D设备上下文的DPI值,DPI值即每英寸的像素,Direct2D设备上下文包含了用于绘制图形的相关信息,包括每英寸的像素等。

添加了Initialize函数的实现代码以后,接下来实现上面的SetDpi函数。在DirectXBase.h头文件的DirectXBase类中添加如下代码,声明函数SetDpi和成员变量dpi、numBuffers。

protected private:

//声明成员变量dpi

float dpi;

//声明成员变量numBuffers

unsigned int numBuffers;

internal:

//设置Direct2D设备上下文的DPI

void SetDpi(float dpi);

在初始化应用窗口的过程中将会用到dpi变量和numBuffers变量,首先需要为这两个变量赋初始值。在DirectXBase.cpp源文件中添加DirectXBase构造函数的实现代码,将dpi变量和numBuffers变量分别赋值为-1.0f和2,具体代码如下所示:

//DirectXBase构造函数

DirectXBase::DirectXBase() :

dpi(-1.0f),

numBuffers(2)

{

}

接着在DirectXBase.cpp源文件中添加SetDpi函数的实现代码,具体代码如下所示:

//设置Direct2D设备上下文的DPI

void DirectXBase::SetDpi(float dpiParameter)

{

//当前DPI值改变时更新DPI

if (dpiParameter!= dpi)

{

dpi = dpiParameter;

//更新Direct2D设备上下文对象的DPI

d2dContext->SetDpi(dpi, dpi);

//更新应用窗口的大小

UpdateForWindowSizeChange();

}

}

在上面的代码中,如果dpi变量保存的DPI值不等于参数dpiParameter保存的DPI值时,将参数dpiParameter赋值给dpi变量,并以dpi变量作为参数调用d2dContext指针所指向的对象的SetDpi函数来设置Direct2D设备上下文的DPI值。最后调用UpdateForWindowSizeChange函数更新应用窗口的大小。

添加了SetDpi函数的实现代码以后,接下来实现上面的UpdateForWindowSizeChange函数。首先在DirectXBase.h头文件的DirectXBase类中添加如下的代码:

protected private:

//声明成员变量d2dTargetBitmap

Microsoft::WRL::ComPtr<ID2D1Bitmap1> d2dTargetBitmap;

//声明成员变量renderTargetView

Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView;

//声明成员变量depthStencilView

Microsoft::WRL::ComPtr<ID3D11DepthStencilView> depthStencilView;

//声明成员变量windowBounds

Windows::Foundation::Rect windowBounds;

internal:

//更新应用窗口的大小

void UpdateForWindowSizeChange();

在上面的代码中,使用protected private关键字声明四个受保护的私有成员变量,分别为d2dTargetBitmap、renderTargetView、depthStencilView和windowBounds,其中d2dTargetBitmap为ID2D1Bitmap1类型的指针,renderTargetView为ID3D11RenderTargetView类型的指针,depthStencilView为ID3D11DepthStencilView类型的指针,windowBounds为Rect类型的变量。然后使用internal关键字声明内部访问的UpdateForWindowSizeChange函数。

声明了上述的成员变量和UpdateForWindowSizeChange函数以后,接着在DirectXBase.cpp源文件中添加UpdateForWindowSizeChange函数的实现代码,具体代码如下所示:

//更新应用窗口的大小

void DirectXBase::UpdateForWindowSizeChange()

{

//当应用窗口大小改变时,更新应用窗口的大小,重新新建应用窗口资源

if (window->Bounds.Width != windowBounds.Width || window->Bounds.Height != windowBounds.Height)

{

//d2dTargetBitmap指针设为空指针

d2dTargetBitmap = nullptr;

//renderTargetView指针设为空指针

renderTargetView = nullptr;

//depthStencilView指针设为空指针

depthStencilView = nullptr;

//更新应用窗口的大小

windowBounds = window->Bounds;

//新建与应用窗口大小相关的资源

CreateWindowSizeDependentResources();

}

}

在上面的代码中,首先判断window->Bounds属性的Width成员和Height成员是否等于windowBounds变量的Width属性和Height属性,即应用窗口的大小是否发生改变。如果应用窗口的大小发生了改变,将d2dTargetBitmap指针、renderTargetView指针和depthStencilView指针都赋值为空指针,然后将windowBounds变量赋值为window->Bounds属性来更新应用窗口的大小,并调用CreateWindowSizeDependentResources函数新建与应用窗口大小相关的资源。

接下来实现上面的CreateWindowSizeDependentResources函数。首先在DirectXBase.h头文件的DirectXBase类中添加如下的代码,用来声明CreateWindowSizeDependentResources函数。

internal:

//新建与应用窗口大小相关的资源

void CreateWindowSizeDependentResources();

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

//新建与应用窗口大小相关的资源

void DirectXBase::CreateWindowSizeDependentResources()

{

// 避免在大小相同的情况下重新生成所有内容

if (swapChain != nullptr)

{

// 如果交换链已存在,调整其后台缓存大小

DX::ThrowIfFailed(

swapChain->ResizeBuffers(numBuffers, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)

);

}

else

{

// 否则,使用与现有 Direct3D 设备相同的适配器新建一个

DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};

// 设置成员变量Width

swapChainDesc.Width = 0;

// 设置成员变量Height

swapChainDesc.Height = 0;

// 设置成员变量Format

swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;

// 设置成员变量Stereo

swapChainDesc.Stereo = false;

// 设置成员变量SampleDesc

swapChainDesc.SampleDesc.Count = 1;

swapChainDesc.SampleDesc.Quality = 0;

// 设置成员变量BufferUsage

swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

// 设置成员变量BufferCount

swapChainDesc.BufferCount = numBuffers;

// 设置成员变量Scaling

swapChainDesc.Scaling = DXGI_SCALING_NONE;

// 设置成员变量SwapEffect

swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;

// 设置成员变量Flags

swapChainDesc.Flags = 0;

// 创建Device设备

ComPtr<IDXGIDevice1> dxgiDevice;

DX::ThrowIfFailed(

d3dDevice.As(&dxgiDevice)

);

// 创建适配器

ComPtr<IDXGIAdapter> dxgiAdapter;

DX::ThrowIfFailed(

dxgiDevice->GetAdapter(&dxgiAdapter)

);

// 创建工厂

ComPtr<IDXGIFactory2> dxgiFactory;

DX::ThrowIfFailed(

dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))

);

// 创建交换链

CoreWindow^ coreWindow = window.Get();

DX::ThrowIfFailed(

dxgiFactory->CreateSwapChainForCoreWindow(d3dDevice.Get(),reinterpret_cast<IUnknown*>(coreWindow),&swapChainDesc,nullptr,&swapChain)

);

DX::ThrowIfFailed(

dxgiDevice->SetMaximumFrameLatency(numBuffers-1)

);

}

// 创建交换链后台缓冲区的呈现目标视图

ComPtr<ID3D11Texture2D> backBuffer;

DX::ThrowIfFailed(

swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))

);

// 创建渲染目标

DX::ThrowIfFailed(

d3dDevice->CreateRenderTargetView(backBuffer.Get(),nullptr,&renderTargetView)

);

D3D11_TEXTURE2D_DESC backBufferDesc = {0};

backBuffer->GetDesc(&backBufferDesc);

CD3D11_TEXTURE2D_DESC depthStencilDesc(DXGI_FORMAT_D24_UNORM_S8_UINT,backBufferDesc.Width,backBufferDesc.Height,1,1,D3D11_BIND_DEPTH_STENCIL);

//创建一组2D纹理

ComPtr<ID3D11Texture2D> depthStencil;

DX::ThrowIfFailed(

d3dDevice->CreateTexture2D(&depthStencilDesc,nullptr,&depthStencil)

);

//创建深度视图

CD3D11_DEPTH_STENCIL_VIEW_DESC viewDesc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D);

DX::ThrowIfFailed(

d3dDevice->CreateDepthStencilView(depthStencil.Get(),&viewDesc,&depthStencilView)

);

//设置用于确定整个窗口的呈现视区

CD3D11_VIEWPORT viewport(0.0f,0.0f,static_cast<float>(backBufferDesc.Width),static_cast<float>(backBufferDesc.Height));

d3dContext->RSSetViewports(1, &viewport);

D2D1_BITMAP_PROPERTIES1 bitmapProperties = BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),dpi,dpi);

ComPtr<IDXGISurface> dxgiBackBuffer;

DX::ThrowIfFailed(

swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))

);

DX::ThrowIfFailed(

d2dContext->CreateBitmapFromDxgiSurface(dxgiBackBuffer.Get(),&bitmapProperties,&d2dTargetBitmap)

);

d2dContext->SetTarget(d2dTargetBitmap.Get());

//将文本抗锯齿模式设为使用灰度抗锯齿

d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);

}

在上述的代码中,首先判断swapChain指针是否为空指针,如果swapChain指针不为空指针,调用swapChain指针所指向的对象的ResizeBuffers函数来调整交换链后台缓存的大小。这里的交换链主要用于更新前台缓存和后台缓存,使用Direct2D所绘制的图形保存在后台缓存中,前台缓存则用于将所绘制的图形显示到应用窗口中。

如果swapChain指针为空指针,定义一个DXGI_SWAP_CHAIN_DESC1结构体的变量swapChainDesc,并设置swapChainDesc结构体变量中的成员变量用来描述交换链中的信息。然后以swapChainDesc结构体变量作为参数调用CreateSwapChainForCoreWindow函数,得到一个IDXGISwapChain1类型的对象,使用swapChain指针指向这个对象。接着声明一个ID3D11Texture2D类型的指针backBuffer,并调用swapChain指针所指向的对象的GetBuffer函数来得到交换链的后台缓存对象,使用backBuffer指针指向这个后台缓存对象。然后以backBuffer指针作为参数调用CreateRenderTargetView函数得到一个ID3D11RenderTargetView类型的对象,使用renderTargetView指针指向这个对象。

接下来定义一个D3D11_TEXTURE2D_DESC结构体的变量backBufferDesc,并将此结构体变量的Width属性和Height属性赋值给renderTargetView指针所指向的对象的Width属性和Height属性。接着创建一个CD3D11_TEXTURE2D_DESC类的对象depthStencilDesc,并声明一个ID3D11Texture2D类型的指针depthStencil。然后以depthStencilDesc对象作为参数调用d3dDevice指针所指向的对象的CreateTexture2D函数得到一个ID3D11Texture2D类型的对象,使用depthStencil指针指向这个对象。

继续定义一个CD3D11_DEPTH_STENCIL_VIEW_DESC结构体的变量viewDesc,并以此结构体变量作为参数调用d3dDevice指针所指向的对象的CreateDepthStencilView函数,得到一个ID3D11DepthStencilView类型的对象,使用depthStencilView指针指向这个对象。然后创建一个CD3D11_VIEWPORT类的对象viewport,并将这个对象作为参数传递给d3dContext指针所指向的对象的RSSetViewports函数。

接着调用d2dContext指针所指向的对象的CreateBitmapFromDxgiSurface函数得到一个ID2D1Bitmap1类型的对象,使用d2dTargetBitmap指针指向这个对象,并将d2dTargetBitmap指针作为参数传递给d2dContext指针所指向的对象的SetTarget函数。最后调用d2dContext指针所指向的对象的SetTextAntialiasMode函数设置文本的抗锯齿模式为D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,表示使用灰度抗锯齿。

初始化应用窗口以后,接下来激活这个应用窗口,这部分的实现代码将添加在D2DBasicAnimation.cpp源文件中。打开D2DBasicAnimation.cpp源文件,并添加Initialize函数的实现代码,为applicationView参数的Activated事件添加事件处理函数OnActivated用于激活应用窗口,具体代码如下所示:

void D2DBasicAnimation::Initialize(_In_ CoreApplicationView^ applicationView)

{

//激活窗口,调用OnActivated方法

applicationView->Activated +=

ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &D2DBasicAnimation::OnActivated);

}

接下来在D2DBasicAnimation.h头文件的D2DBasicAnimation类中添加如下的代码,用来声明OnActivated函数。

private:

//激活应用窗口

void OnActivated(_In_ Windows::ApplicationModel::Core::CoreApplicationView^ applicationView,_In_ Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);

添加了OnActivated函数的声明代码以后,接下来在D2DBasicAnimation.cpp源文件中添加OnActivated函数的实现代码,调用window指针所指向的对象的Activate函数来激活应用窗口,具体代码如下所示:

void D2DBasicAnimation::OnActivated(_In_ CoreApplicationView^ applicationView,_In_ IActivatedEventArgs^ args)

{

//激活窗口

window->Activate();

}

到此已经实现了初始化应用窗口和激活应用窗口,下面的部分将介绍如何在这个应用窗口中绘制三角形。

转载于:https://www.cnblogs.com/finehappy/p/6645578.html

Win10系列:VC++绘制几何图形2相关推荐

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

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

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

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

  3. html5 绘制图形,HTML5绘制几何图形

    绘制几何图形 var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext(" ...

  4. 【OpenCV 4开发详解】图像上绘制几何图形

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  5. eeglab教程系列(15)-绘制独立成分ERP贡献

    要完成该操作,必须保证已加载数据和电极位置数据,同时还要对数据进行提取epoch,并对数据进行ICA处理,操作如下: 加载数据文件:eeglab教程系列(2)-加载.显示数据 加载位置文件:eegla ...

  6. eeglab教程系列(4)-绘制通道光谱图

    在进行通道光谱图绘制前,需要先按照eeglab教程系列(3)-绘制脑电头皮图进行先操作(只需操作完第二步后点击OK即可). 绘制通道光谱图 在eeglab界面进行如下操作:Plot > Chan ...

  7. eeglab中文教程系列(15)-绘制独立成分ERP贡献

    目录 独立成分的ERP 对数据的ERP 的贡献 绘制Component ERP-image 本教程为脑机学习者Rose发表于公众号:脑机接口社区 .QQ交流群:903290195 要完成该操作,必须保 ...

  8. eeglab中文教程系列(3)-绘制通道光谱图

    目录 绘制通道光谱图 本教程为脑机学习者Rose发表于公众号:脑机接口社区 .QQ交流群:903290195 在进行通道光谱图绘制前,需要先按照eeglab教程系列(2)-绘制脑电头皮图进行先操作(只 ...

  9. 【Android开发】图形图像处理技术-绘制几何图形

    常见的几何图形包括点.线.弧.矩形等.在Android中,Canvas类提供了丰富的绘制几何图形的方法,通过这些方法,可以绘制出各种几何图形.常用的几何图形的绘制方法如下所示: 1. 画一个圆使用的是 ...

最新文章

  1. android fm 耳机,Android杂谈:音频调试小计
  2. Nginx-05:Nginx配置实例之反向代理2
  3. python窗口居中_Python: tkinter窗口屏幕居中,设置窗口最大,最小尺寸实例
  4. 阶段2 JavaWeb+黑马旅游网_15-Maven基础_第1节 基本概念_01maven概述
  5. ppp协议c语言,ppp协议是用于拨号上网和路由器之间通信的点到点通信协议,是属于(1)协议,它不具有(2)的功能。( - 信管网...
  6. lamp一键安装包不安装mysql_LAMP一键安装包-CentOS 5/6下自动编译安装Apache,MySQL,PHP...
  7. 信息系统项目管理师必背核心考点(四十八)合同类型的选择
  8. HTTP传输大文件的方法
  9. Egret Engine(二十六):MovieClip序列帧动画
  10. 计算机硬盘怎么整理,w7怎么整理磁盘碎片_如何清理win7电脑磁盘碎片
  11. what is denoise
  12. AnnotationConfigApplicationContext@xxxx has not been refreshed yet
  13. How to clone a brach from github
  14. iTools安装软件
  15. 表格在线生成SQL工具
  16. Python中利用海龟绘图(Turtle方法)画个钟表盘
  17. 大学生计算机适合用苹果笔记本吗,2019学生党笔记本推荐 苹果笔记本适合大学生吗...
  18. 计算机程序设计工程师技术水平证书 java 考试试卷_关于程序设计工程师技术水平证书(JAVA).doc...
  19. 性能分析之 PHP 应用进程过多导致的 page faults
  20. 【算法】考前整理复习

热门文章

  1. java 反射 构造器_Java之类的构造器(反射)
  2. 收集:Hibernate中常见问题 No row with the given identifier exists问题的原因及解决
  3. spring boot 教程(六)多数据源配置与使用
  4. 机器学习、数据挖掘之中国大牛
  5. java 子类 同名参数_Java -- 父类和子类拥有同名变量
  6. 决策树(一)--ID3
  7. 蓝牙学习笔记(五)——AC692x_BLE工具make_gatt_services
  8. Python 列表实现原理
  9. clickhouse CollapsingMergeTree表引擎
  10. TCP/IP与HTTP的区别