zoukankan      html  css  js  c++  java
  • 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.1inariesDirectX目录下有两个子文件夹"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.EventArgs) Handles MyBase.Load
            _D = New clsDirect2DSample
            _D.CreateDeviceResource(Me.Panel1)
        End Sub

        Private Sub Panel1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles 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目录下,运行一遍程序后,上述的现象消失了。后面在多次运行,也不会问询文件了

  • 相关阅读:
    BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
    BZOJ 2134: 单选错位( 期望 )
    BZOJ 1030: [JSOI2007]文本生成器( AC自动机 + dp )
    BZOJ 2599: [IOI2011]Race( 点分治 )
    BZOJ 3238: [Ahoi2013]差异( 后缀数组 + 单调栈 )
    ZOJ3732 Graph Reconstruction Havel-Hakimi定理
    HDU5653 Bomber Man wants to bomb an Array 简单DP
    HDU 5651 xiaoxin juju needs help 水题一发
    HDU 5652 India and China Origins 并查集
    HDU4725 The Shortest Path in Nya Graph dij
  • 原文地址:https://www.cnblogs.com/grenet/p/3249664.html
Copyright © 2011-2022 走看看