[C#] Direct2D 学习笔记 (一)

写在前面:最近要做一个有关于地图的项目[C#],开始选择 GDI+ 作图,不知是算法问题还是 GDI+ 本身问题,加载非常慢而且拖动各种闪烁。迫于无奈最终放弃了 GDI+ 方式而尝试 Direct2D。但是让我意外的是网上有关 Direct2D 的教程很少,而且为数不多的教程中大多数是用 C++写的(据说是因为效率高),少部分是用VB.NET ,用 C# 的几乎没有(我是真的没找到)。最终我选择了一个VB.NET的教程为蓝本进行学习,将他的 VB 代码转化成 C# 代码。(之前自学过一点C++和VB,也多亏这点基础我还能看懂)

一、什么是Direct2D

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

二、VS2013 的 Direct2D 运行库
首先需要下载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开发了。

三、示例
新建一个空的winform工程,引用dll。(引用x86下的dll)
添加如下命名空间:

using Microsoft.WindowsAPICodePack.DirectX;
using Microsoft.WindowsAPICodePack.DirectX.Direct2D1;
using Microsoft.WindowsAPICodePack.DirectX.Graphics;

在Form.cs里的namespace xxxx里添加如下类:

public class clsDirect2DSample
{
    //D2D工厂对象,ID2D1Factory接口。
    private D2DFactory _d2dFactory;
    //渲染窗口,ID2D1HwndRenderTarget接口。
    private RenderTarget _renderTarget;

    //构造函数
    public clsDirect2DSample()
    {
        //创建一个D2D工厂对象
        _d2dFactory = D2DFactory.CreateFactory();

    }

    public void CreateDeviceResource(Control Target)
    {
        //如果_renderTarget没有初始化
        if(_renderTarget==null)
        {
            //初始化,在_d2dFactory创建渲染缓冲区并与Target绑定
             _renderTarget=_d2dFactory.CreateHwndRenderTarget(
                    new RenderTargetProperties(),
                    new HwndRenderTargetProperties(
                        Target.Handle,
                        new SizeU((uint)Target.Width,(uint)Target.Height),
                        PresentOptions.None
                        )
                        );
        }
    }

    public void Render()
    {
        if(_renderTarget!=null)
        {
            //开始绘制
            _renderTarget.BeginDraw();

            //椭圆
            Ellipse E = new Ellipse(new Point2F(50, 50), 30, 40);
            //定义一个画刷
            SolidColorBrush B = _renderTarget.CreateSolidColorBrush(
                    new Microsoft.WindowsAPICodePack.DirectX.Direct2D1.ColorF(0, 1, 0));

            //将椭圆绘制在渲染缓冲区
            _renderTarget.DrawEllipse(E, B, 4);

            //结束绘制
            _renderTarget.EndDraw();
        }
    }
 }

在窗体上放置一个名称为:panel1的panel控件
在窗体类 Form1: Form 中生命一个全局变量:

private clsDirect2DSample _D;

在Form1_Load函数里添加:

    _D = new clsDirect2DSample();
    _D.CreateDeviceResource(this.panel1);

在Form1_Paint函数里添加:

    _D.Render();

至此代码部分完成。
启用“启用非托管代码调试”(启用本机代码调试):
项目->xxxx属性->“调试”选项卡->勾选“启用本机代码调试”。

修改App.config内容如下


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

运行效果如图:
[C#] Direct2D 学习笔记 (一)_第1张图片

上述过程就是:
在D2D工厂对象(_d2dFactory)的渲染缓冲区/窗口(_renderTarget)中绘制图形(各种Draw方法)并最终显示(EndDraw方法)在其绑定的控件/窗体(Target)上。
so,实际使用需要分几步走:
1,创建D2DFactory且必须首先被创建。在类的构造函数中,用CreateFactory函数创建D2DFactory。
2,创建RenderTarget,渲染缓冲区,相当于画板,在其上进行绘图操作。本例中用D2DFactory类的CreateHwndRenderTarget方法创建。两个参数:RenderTargetProperties类,设置RenderTarget的一些属性(DPI等,在该类重载初始化函数中可以设置);HwndRenderTargetProperties类设置绑定的Hwnd的属性(Hwnd、宽、高等属性)(这里有个疑问,为什么要传入Hwnd的宽和高?既然有句柄,这些属性应该可以直接获取到啊。。。)
3,进行绘图,要注意绘图顺序导致的层叠关系,最后调用EndDraw显示在窗口/控件上。

后记:网上说 C# 的效率很低因此不适合做界面渲染,具体怎样我不清楚。其实对于我这种初学者来说,语言效率什么的并不重要,因为我能做到的效果还涉及不到效率问题,我仅仅要求是“能实现效果”。因此, 仅以此系列文章 献给那些和我一样的小白们。

参考:http://www.cnblogs.com/grenet/p/3249664.html
参考:http://www.cnblogs.com/graphics/category/412802.html

你可能感兴趣的:(C#,Direct2D)