Direct2D教程I——简介及首个例子

简介:

在博客园里,系统的Direct2D的教程比较少,只有“万一”写了一个关于Direct2D的系列(Delphi 2009)。于是,仿照其系列,写一个在VS下的Direct2D系列教程。

 

博客园中的高手还是有不少的,在写本系列教程的过程中,也会把碰到的问题或疑惑一一贴出来,期待高手的解答。以使得大家共同提高。

 

 

什么是Direct2D

一言以蔽之,就是Windows 7平台上的一个2D图形API,可以提供高性能,高质量的2D渲染。大多数人对Direct2D可能都比较陌生,以至于我之前在论坛上提到这个词的时候,有人竟然说你是不是写错了?可能大家比较熟悉的是Direct3D,因为D3D已经是当前游戏界的主流应用。在过去,3D世界是OpenGL与DirectX二分天下,但是由于OpenGL发展十分滞后,而且没有一个像微软这样强大的后台支柱,所以逐渐被DirectX所超越。回过头来说2D,过去Windows上的2D程序还主要基于GDI和GDI+,遗憾的是这两者都是软件实现,而Direct2D则不同,它基于Direct3D,所以能够使用硬件加速功能,能更大程度的发挥硬件特性,创建高性能,高质量的2D图形,这些图形包括几何图形,如矩形,椭圆等。还有位图,文本。而且更方便的是,Direct2D与GDI,GDI+和D3D都是可以交互的。

 

Direct2D运行需求

要开发和使用Direct2D程序,系统必须是Windows 7,Windows Vista SP2, Windows Server 2008 R2或者Windows Server 2008 SP2,这样的系统需求无疑会稍稍阻碍Direct2D前进的步伐,虽然Vista和Windows 7已经推出有一段时间了,但是不可否认的是,仍然有很多人在使用XP系统。甚至是Win2K。但是新技术的普及是不可阻碍的,相信不久的将来,Direct2D将会成为2D图形世界的主流。

 

VS2010下的Direct2D的运行库

首先在Windows® API Code Pack for Microsoft® .NET Framework上下载Windows API Code Pack 1.1.zip

解压后,在\Windows API Code Pack 1.1\binaries\DirectX目录下有两个子文件夹"x64"、"x86"。分别代表着64位、32位下的运行库。

在自己的项目中引用x86下的Microsoft.WindowsAPICodePack.DirectX.dll文件。就可以进行Direct2D开发了。

 

下面是用VB2010写的Direct2D的示例类。

  
Imports Microsoft.WindowsAPICodePack.DirectX 

Public  Class  clsDirect2DSample 
     Private _d2DFactory  As Direct2D1. D2DFactory 
     Private _renderTarget  As Direct2D1. RenderTarget 

     Public  Sub  New() 
        _d2DFactory = Direct2D1. D2DFactory.CreateFactory() 
     End  Sub 

     Public  Sub CreateDeviceResource(Target  As  Control
         If _renderTarget  Is  Nothing  Then 
            _renderTarget = _d2DFactory.CreateHwndRenderTarget( _ 
                                                       New Direct2D1. RenderTargetProperties, _ 
                                                       New Direct2D1. HwndRenderTargetProperties( _ 
                                                                            Target.Handle, _ 
                                                                             New Direct2D1. SizeU(Target.Width, Target.Height), _ 
                                                                            Direct2D1. PresentOptions.None) _ 
                                                      ) 
         End  If 
     End  Sub 

     Public  Sub Render() 
         If  Not _renderTarget  Is  Nothing  Then 
            _renderTarget.BeginDraw() 

             Dim E  As  New Direct2D1. Ellipse( New Direct2D1. Point2F(50, 50), 30, 40) 
             Dim B  As Direct2D1. SolidColorBrush = _renderTarget.CreateSolidColorBrush( New Direct2D1. ColorF(0, 1, 0)) 
            _renderTarget.DrawEllipse(E, B, 4) 

            _renderTarget.EndDraw() 
         End  If 
     End  Sub 
End  Class

首先引入Microsoft.WindowsAPICodePack.DirectX命名空间,实际上还可以更进一步引入Direct2D1命名空间。只是为了区分某些类是在Direct2D下还是在原本的System下,没有引入Direct2D1命名空间。凡是在类前有Direct2D1前缀的说明该类是在Direct2D1命名空间下。

 

从上面的代码可以看出,要想使用Direct2D,得分下面几步走

1、创建D2DFactory,相当于Direct2D的总管类,必须首先被创建。在类的初始化函数中,用CreateFactory函数创建D2DFactory。该函数有3个重载方式,在以后的文章有机会再详细介绍

2、创建RenderTarget,相当于GDI+中的Graphics类,只有在创建后,才能进行后面的绘图操作。在本例中,用D2DFactory类的CreateHwndRenderTarget方法创建一个和指定句柄Hwnd绑定的RenderTarget。在该方法中有两个参数:RenderTargetProperties类,设置RenderTarget的一些属性(DPI等,在该类重载初始化函数中可以设置);HwndRenderTargetProperties类设置绑定的Hwnd的属性(Hwnd、宽、高等属性)

3、在完成上面两步后,可以开始绘图操作了。为了演示方便,把所有的绘图操作放在Render函数中。在Render函数中,先调用RenderTarget类的BeginDraw方法,表示要开始绘图了,再调用RenderTarget类的EndDraw方法表示绘图结束。Direct2D会把结果绘制到绑定的设备上

 

 

本例中,在Render函数中,先创建了一个Ellipse对象(椭圆),再创建一个SolidColorBrush对象(纯色笔刷),然后用RenderTarget类的DrawEllipse方法绘制一个椭圆。三个参数分别表示:椭圆、笔刷、线宽。

 

同时,在WinForm中,有下面的代码。把Panel1作为绑定的控件,传给示例类,并在该空间的Paint事件中调用示例类的Render方法

Public Class Form1 
    Private _D As clsDirect2DSample 

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgsHandles MyBase.Load 
        _D = New clsDirect2DSample 
        _D.CreateDeviceResource(Me.Panel1) 
    End Sub 

    Private Sub Panel1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgsHandles Panel1.Paint 
        _D.Render() 
    End Sub 
End Class

 

下图是程序运行的结果

image

 

在Windows API Code Pack的官网上,有Windows API Code Pack的Visual Basic的示例代码,只不过比较简单,而且是WPF的示例代码。有兴趣的可以去看看。

 

注意:如果直接运行的话,会出现红色大叉,表示运行错误。在项目属性中勾选调试中的“启用非托管代码调试”。会出现下面的对话框

在网友Launcher提示下,按照“混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。”一文中给出的解决方案,解决上面的错误。

解决方案是:在项目根目录下,新建app.config文件,并包含到项目中,在其中打上如下的内容

  
<? xml   version =" 1.0" ?> 
< configuration > 
  < startup   useLegacyV2RuntimeActivationPolicy =" true" > 
    < supportedRuntime   version =" v4.0"   sku  = " .NETFramework,Version=v4.0" /> 
    < supportedRuntime   version =" v2.0.50727" /> 
  </ startup > 
</ configuration >

 

 

接下来,把调试中遇到的三个问题写在下方。希望网友不吝赐教

 

问题一:引入64位的DLL,在运行时会出错。

在引入64位的DLL后,运行的时候就会出错。是在新建项目的时候,有什么设置不对么?之前的MediaInfo的64位DLL也是同样的问题。机器和操作系统都是64位的。

 

问题二:在窗口界面出现后,用别的窗口覆盖一下再显示,等于重新调用了一次Render。可是第二次的效果图和第一次的效果相差好多,锯齿明显了很多。在Render函数中,并没写设置锯齿的代码,为何同样的代码两次执行的效果不一致。下图是第二次的效果图。(可是如果第一次效果图出来后,最小化窗口,再恢复,也等于调用一次Render函数,效果还是和原来一样好)

image

 

问题三:在首次运行的时候,会弹出对话框,找寻h文件(或者是cpp文件),没找到会直接报错。此时,到Debug目录下,运行一遍程序后,上述的现象消失了。后面在多次运行,也不会问询文件了


    本文转自万仓一黍博客园博客,原文链接:http://www.cnblogs.com/grenet/p/3249664.html,如需转载请自行联系原作者

相关文章
|
4月前
|
算法
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
|
6月前
|
机器学习/深度学习 人工智能 数据处理
人工智能平台PAI产品使用合集之对于有多个raw_feature,如何进行区分
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
6月前
|
图形学
【unity实战】如何更加规范的创建各种Rogue-Lite(肉鸽)风格的物品和BUFF效果(附项目源码)
【unity实战】如何更加规范的创建各种Rogue-Lite(肉鸽)风格的物品和BUFF效果(附项目源码)
91 0
|
7月前
火山中文编程(PC) -- 类的介绍
火山中文编程(PC) -- 类的介绍
60 0
火山中文编程(PC) -- 类的介绍
|
存储 测试技术 开发工具
基础了解·创建第一个SwiftUI项目
基础了解·创建第一个SwiftUI项目
178 0
|
存储 数据可视化 Ubuntu
bcftools学习笔记丨软件简介、安装方式、使用方法、核心功能、参数解释等一文速览
bcftools学习笔记丨软件简介、安装方式、使用方法、核心功能、参数解释等一文速览
|
算法 数据安全/隐私保护 芯片
快速入门数字芯片设计,UCSD ECE111(十一)Project的一些注意事项
快速入门数字芯片设计,UCSD ECE111(十一)Project的一些注意事项
140 0
|
API 流计算 Python
《ACE 区域技术发展峰会:Flink Python Table API入门及实践》电子版地址
ACE 区域技术发展峰会:Flink Python Table API入门及实践
145 0
《ACE 区域技术发展峰会:Flink Python Table API入门及实践》电子版地址
|
机器学习/深度学习 存储 前端开发
【算法社区】从零开始的DS生活 轻松从0基础实现多种队列
本文详细介绍了队列的概念和性质,简要的介绍了队列ADT并附三种实现方式(链式、顺序api、顺序+动态扩容),对循环、双端、阻塞、优先级队列进行简单的应用与jdk源码分析,供读者理解与学习,适合点赞+收藏。有什么错误希望大家直接指出~
【算法社区】从零开始的DS生活 轻松从0基础实现多种队列
|
机器学习/深度学习 存储 编解码
DL之RefineNet:RefineNet和Light-Weight RefineNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之RefineNet:RefineNet和Light-Weight RefineNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之RefineNet:RefineNet和Light-Weight RefineNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略