Direct2D教程II——绘制基本图形和线型(StrokeStyle)的设置详解-阿里云开发者社区

开发者社区> 万仓一黍> 正文

Direct2D教程II——绘制基本图形和线型(StrokeStyle)的设置详解

简介: 目前,在博客园上,相对写得比较好的两个关于Direct2D的教程系列,分别是万一的Direct2D系列和zdd的Direct2D系列。有兴趣的网友可以去看看。本系列也是介绍Direct2D的教程,是基于Windows API Code Pack 1.1的Direct2D的教程,如果要调试文中的代码的话,还得参考前文 Direct2D教程I——简介及首个例子 下载导入Windows API Code Pack 1.1的动态库   在前文 Direct2D教程I——简介及首个例子 简单介绍了Direct2D,并给了一个简单的示例。
+关注继续查看

目前,在博客园上,相对写得比较好的两个关于Direct2D的教程系列,分别是万一Direct2D系列和zddDirect2D系列。有兴趣的网友可以去看看。本系列也是介绍Direct2D的教程,是基于Windows API Code Pack 1.1的Direct2D的教程,如果要调试文中的代码的话,还得参考前文 Direct2D教程I——简介及首个例子 下载导入Windows API Code Pack 1.1的动态库

 

在前文 Direct2D教程I——简介及首个例子 简单介绍了Direct2D,并给了一个简单的示例。接下来,本文对一些基本的绘图命令做个介绍

 

绘制基本图形:直线、矩形、圆角矩形、椭圆

 

和GDI+类似,在RenderTarget对象下有各个绘图命令(GDI+是在Graphics对象下有各个绘图命令),下面是各个基本图形的绘图命令的函数原型

 

直线:
Public Sub DrawLine(firstPoint As Direct2D1.Point2F, secondPoint As Direct2D1.Point2F, brush As Direct2D1.Brush, skrokeWidth As Single, strokeStyle As Direct2D1.StrokeStyle)

 

矩形:
Public Sub DrawRectangle(rect As Direct2D1.RectF, brush As Direct2D1.Brush, strokeWidth As Single
Public Sub DrawRectangle(rect As Direct2D1.RectF, brush As Direct2D1.Brush, strokeWidth As Single, strokeStyle As Direct2D1.StrokeStyle
Public Sub FillRectangle(rect As Direct2D1.RectF, brush As Direct2D1.Brush)

 

圆角矩形:
Public Sub DrawRoundedRectangle(roundedRect As Direct2D1.RoundedRect, brush As Direct2D1.Brush, strokeWidth As Single)
Public Sub DrawRoundedRectangle(roundedRect As Direct2D1.RoundedRect, brush As Direct2D1.Brush, strokeWidth As Single, strokeStyle As Direct2D1.StrokeStyle
Public Sub FillRoundedRectangle(roundedRect As Direct2D1.RoundedRect, brush As Direct2D1.Brush)

 

椭圆:
Public Sub DrawEllipse(ellipse As Direct2D1.Ellipse, brush As Direct2D1.Brush, strokeWidth As Single)
Public Sub DrawEllipse(ellipse As Direct2D1.Ellipse, brush As Direct2D1.Brush, strokeWidth As Single, strokeStyle As Direct2D1.StrokeStyle
Public Sub FillEllipse(ellipse As Direct2D1.Ellipse, brush As Direct2D1.Brush)

 

从上面的函数原型可以看出,以Draw开头的函数都是绘制函数。以Fill开头的函数都是填充函数。绘制函数的线宽由strokeWidth参数指定,绘制函数的线型由strokeStyle参数指定(默认是实线)。和GDI+不同的是,在Direct2D中,不再区分Brush(画刷)和Pen(画笔)对象,而统一用Brush(画刷)对象,在用Brush(画刷)绘制线的时候再指定线宽和线型参数。

 

从参数strokeWidth和参数strokeStyle来看,都带有单词stroke。熟悉PS的都知道,stroke指的是描边,在PS中描边的位置分为“外部”、“内部”、“居中”。那么在Direct2D中,这里的描边的位置在哪儿呢?我们用代码实验一下。

 

说明:为了代码的复用,我们把前文中的_d2DFactory和_renderTarget修饰限定词从Private改为Protected。这样在后面的例子中直接继承前文的类,也可以直接用_d2DFactory和_renderTarget这两个对象。

 

先给出Point2FRectFRoundedRectEllipse这四个类的原型定义,参数都简介明了,不再详述


Direct2D1.Point2F(x As Single, y As Single)
Direct2D1.RectF(left As Single, top As Single, right As Single, buttom As Single)
Direct2D1.RoundedRect(rect As Direct2D1.RectF, radiusX As Single, radiusY As Single)
Direct2D1.Ellipse(point As Direct2D1.Point2F, radiusX As Single, radiusY As Single)

 

下面是实验示例代码


Public Class clsDirect2DSample2
    Inherits clsDirect2DSample

    Public Shadows Sub Render()
        If Not _renderTarget Is Nothing Then

            With _renderTarget
                .BeginDraw()

                Dim F1 As New Direct2D1.RectF(0, 0, 100, 50)
                Dim F2 As New Direct2D1.RectF(200, 200, 300, 250)
                Dim B As Direct2D1.SolidColorBrush = _renderTarget.CreateSolidColorBrush(New Direct2D1.ColorF(1, 0, 0))

                _renderTarget.DrawRectangle(F1, B, 10)
                _renderTarget.DrawRectangle(F2, B, 10)

                .EndDraw()
            End With

        End If
    End Sub

End Class

 

从上图的代码来看,在(0,0)位置上画了一个100*50的矩形,描边宽度10px。在(200,200)位置上画了一个矩形,描边宽度10px,如下图所示

image

 

从上面的效果可以看出两点:

一是左上角的矩形说明,Direct2D中的描边类型应该是“居中”;

二是右边的矩形说明Direct2D中的RectF定义和原本GDI+中的RectangleF定义不同,Direct2D中的RectF中后两个参数是右下角的坐标,而GDI+中的RectangleF中的后两个参数指的是矩形的宽和高。

 

线型(StrokeStyle)的设置

在上面的函数原型中,线型是由参数strokeStyle决定的,它是StrokeStyle类。这个类不能直接初始化,必须由D2DFactory对象的CreateStrokeStyle函数创建(Direct2D中有不少的类不能直接初始化,必须由D2DFactory或RenderTarget对象的相应的函数创建,如上面的SolidColorBrush对象就必须由RenderTarget对象的CreateSolidColorBrush函数创建)。

 

先看看CreateStrokeStyle函数的原型定义:
Public Function CreateStrokeStyle(strokeStyleProperties As Direct2D1.StrokeStyleProperties) As Direct2D1.StrokeStyle
Public Function CreateStrokeStyle(strokeStyleProperties As Direct2D1.StrokeStyleProperties, dashes() As Single) As Direct2D1.StrokeStyle

 

主要是通过strokeStyleProperties参数来设置线型,来看看StrokeStyleProperties结构及其参数对象的原型定义。

Direct2D1.StrokeStyleProperties(startCap As Direct2D1.CapStyle, endCap As Direct2D1.CapStyle, dashCap As Direct2D1.CapStyle, _
                                            lineJoin As Direct2D1.LineJoin, miterLimit As Single, _
                                            dashStyle As Direct2D1.DashStyle, dashOffset As Single)
Public Enum CapStyle
    Flat = 0
    Square = 1
    Round = 2
    Triangle = 3
End Enum
Public Enum LineJoin
    Miter = 0
    Bevel = 1
    Round = 2
    MiterOrBevel = 3
End Enum
Public Enum DashStyle
    Solid = 0
    Dash = 1
    Dot = 2
    DashDot = 3
    DashDotDot = 4
    Custom = 5
End Enum

其中CapStyle枚举指的是线端的线头类型,分别是Flat(平整,即无)、Square(方块)、Round(圆)、Triangle(三角)。和GDI+中的DashCap枚举类似,多了一个Square(方块),而在下面的例子中会说明Flat和Square的区别。参数startCap决定线起点的线头类型、endCap决定线终点的线头类型、dashCap决定中间划线端的线头类型。

而DashStyle枚举指的是线型,分别是Solid(实线)、Dash(划线)、Dot(点线)、DashDot(点划线)、DashDotDot(点点划线)、Custom(自定义)。和GDI+中的DashStyle一样。

参数dashOffset指的是点划线的偏移量

 

下面的代码是对上面的两个枚举的演示,请注意枚举CapStyle中的Flat和Square的区别。


Public Class clsDirect2DSample3
    Inherits clsDirect2DSample

    Public Shadows Sub Render()
        If Not _renderTarget Is Nothing Then

            With _renderTarget
                .BeginDraw()

                Dim B As Direct2D1.SolidColorBrush = _renderTarget.CreateSolidColorBrush(New Direct2D1.ColorF(1, 0, 0))
                Dim SP As New Direct2D1.StrokeStyleProperties()
                Dim S As Direct2D1.StrokeStyle

                SP.StartCap = Direct2D1.CapStyle.Flat
                SP.EndCap = Direct2D1.CapStyle.Flat
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 20), New Direct2D1.Point2F(200, 20), B, 8, S)

                SP.StartCap = Direct2D1.CapStyle.Square
                SP.EndCap = Direct2D1.CapStyle.Square
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 40), New Direct2D1.Point2F(200, 40), B, 8, S)

                SP.StartCap = Direct2D1.CapStyle.Round
                SP.EndCap = Direct2D1.CapStyle.Round
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 60), New Direct2D1.Point2F(200, 60), B, 8, S)

                SP.StartCap = Direct2D1.CapStyle.Triangle
                SP.EndCap = Direct2D1.CapStyle.Triangle
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 80), New Direct2D1.Point2F(200, 80), B, 8, S)

                SP.StartCap = Direct2D1.CapStyle.Flat
                SP.EndCap = Direct2D1.CapStyle.Flat
                SP.DashCap = Direct2D1.CapStyle.Round

                SP.DashStyle = Direct2D1.DashStyle.Solid
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 120), New Direct2D1.Point2F(200, 120), B, 6, S)

                SP.DashStyle = Direct2D1.DashStyle.Dash
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 140), New Direct2D1.Point2F(200, 140), B, 6, S)

                SP.DashStyle = Direct2D1.DashStyle.Dot
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 160), New Direct2D1.Point2F(200, 160), B, 6, S)

                SP.DashStyle = Direct2D1.DashStyle.DashDot
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 180), New Direct2D1.Point2F(200, 180), B, 6, S)

                SP.DashStyle = Direct2D1.DashStyle.DashDotDot
                S = _d2DFactory.CreateStrokeStyle(SP)
                _renderTarget.DrawLine(New Direct2D1.Point2F(10, 200), New Direct2D1.Point2F(200, 200), B, 6, S)

                .EndDraw()
            End With
        End If
    End Sub
End Class

 

image

上面四条线是演示枚举CapStyle的四种类型,注意第一条线是Flat,第二条线是Square。虽然都是方形,但是很明显第二条线比第一条线两边还多出一点(方形线帽)

下面五条线是演示枚举DashStyle表示的五个线型。注意:上面代码中红色的部分,DashCap不能设置为Direct2D1.CapStyle.Flat,如果设置为Flat,则所有的点都不见了;设置其他三种类型分别代表不同的点(方形点、圆点、菱形点)。

 

再说说枚举DashStyle中的Custom线型。设定为Custom后,必须用一个数组来指定自定义划线的线型。数组按照{实、空、实、空……}顺序来指定各部分的长度,单位是线宽。

例如{2,2}表示2线宽长的实线和2线宽长的空白组成的划线,也就是枚举DashStyle中的Dash

{0,2}表示0线宽长的实线和2线宽长的空白组成的划线,就是枚举DashStyle中的Dot。这也解释了DashCap设置为Direct2D1.CapStyle.Flat时,为何点不见了(设置为其他值时,点实际上是由线头组成的,点本身的长度为0)。

以此类推,{2,2,0,2}表示DashStyle中的DashDot,{2,2,0,2,0,2}表示DashStyle中的DashDotDot

要注意的是,只有枚举DashStyle设置为Custom时,才能传递数组,否则会直接报错的。

 

最后说说LineJoin枚举,指的是连接两条线的连接方式。分别是Miter(折角)、Bevel(倒角)、Round(圆角)、MiterOrBevel(折角或倒角)。和GDI+中的LineJoin枚举类似,只是MiterOrBevel好像对应GDI+中LineJoin枚举中的MiterClipped。

说说MiterOrBevel,当折角的值没有超过指定的值(系统指定)时,是Miter(折角),反之超过的话是Bevel(倒角)。

参数miterLimit是指折角的限制,低于限制时会自动添加倒角。参数miterLimit最小是1。注意的是miterLimit参数并不是配合LineJoin使用。当miterLimit设置为1的时候,下面的例子中,LineJoin枚举设置成Miter、Bevel、MiterOrBevel效果是一样的。当miterLimit设置为3的时候,LineJoin枚举设置成Miter、Bevel、MiterOrBevel效果才是不一样的

 

下面是LineJoin的示例,由于是演示两条线的连接,故用了一些后面才会详述的代码。不过,不影响我们理解枚举LineJoin的各个设置值的意义。

左上是Miter,右上是Bevel,左下是Round,右下是MiterOrBevel

 
Public Class clsDirect2DSample4
    Inherits clsDirect2DSample

    Public Shadows Sub Render()
        If Not _renderTarget Is Nothing Then

            With _renderTarget
                .BeginDraw()

                Dim B As Direct2D1.SolidColorBrush = _renderTarget.CreateSolidColorBrush(New Direct2D1.ColorF(1, 0, 0))
                Dim SP As New Direct2D1.StrokeStyleProperties()
                Dim S As Direct2D1.StrokeStyle

                Dim PG As Direct2D1.PathGeometry
                Dim sink As Direct2D1.GeometrySink

                PG = _d2DFactory.CreatePathGeometry
                sink = PG.Open

                sink.BeginFigure(New Direct2D1.Point2F(17, 17), Direct2D1.FigureBegin.Hollow)

                sink.AddLine(New Direct2D1.Point2F(45, 85))
                sink.AddLine(New Direct2D1.Point2F(85, 45))
                sink.AddLine(New Direct2D1.Point2F(85, 125))
                sink.AddLine(New Direct2D1.Point2F(165, 17))

                sink.EndFigure(Direct2D1.FigureEnd.Open)
                sink.Close()

                SP.LineJoin = Direct2D1.LineJoin.Miter
                SP.MiterLimit = 3
                S = _d2DFactory.CreateStrokeStyle(SP)

                .DrawGeometry(PG, B, 10, S)



                PG = _d2DFactory.CreatePathGeometry
                sink = PG.Open

                sink.BeginFigure(New Direct2D1.Point2F(217, 17), Direct2D1.FigureBegin.Hollow)

                sink.AddLine(New Direct2D1.Point2F(245, 85))
                sink.AddLine(New Direct2D1.Point2F(285, 45))
                sink.AddLine(New Direct2D1.Point2F(285, 125))
                sink.AddLine(New Direct2D1.Point2F(365, 17))

                sink.EndFigure(Direct2D1.FigureEnd.Open)
                sink.Close()

                SP.LineJoin = Direct2D1.LineJoin.Bevel
                SP.MiterLimit = 3
                S = _d2DFactory.CreateStrokeStyle(SP)

                .DrawGeometry(PG, B, 10, S)


                PG = _d2DFactory.CreatePathGeometry
                sink = PG.Open

                sink.BeginFigure(New Direct2D1.Point2F(17, 217), Direct2D1.FigureBegin.Hollow)

                sink.AddLine(New Direct2D1.Point2F(45, 285))
                sink.AddLine(New Direct2D1.Point2F(85, 245))
                sink.AddLine(New Direct2D1.Point2F(85, 325))
                sink.AddLine(New Direct2D1.Point2F(165, 217))

                sink.EndFigure(Direct2D1.FigureEnd.Open)
                sink.Close()

                SP.LineJoin = Direct2D1.LineJoin.Round
                SP.MiterLimit = 3
                S = _d2DFactory.CreateStrokeStyle(SP)

                .DrawGeometry(PG, B, 10, S)


                PG = _d2DFactory.CreatePathGeometry
                sink = PG.Open

                sink.BeginFigure(New Direct2D1.Point2F(217, 217), Direct2D1.FigureBegin.Hollow)

                sink.AddLine(New Direct2D1.Point2F(245, 285))
                sink.AddLine(New Direct2D1.Point2F(285, 245))
                sink.AddLine(New Direct2D1.Point2F(285, 325))
                sink.AddLine(New Direct2D1.Point2F(365, 217))

                sink.EndFigure(Direct2D1.FigureEnd.Open)
                sink.Close()

                SP.LineJoin = Direct2D1.LineJoin.MiterOrBevel
                SP.MiterLimit = 3
                S = _d2DFactory.CreateStrokeStyle(SP)

                .DrawGeometry(PG, B, 10, S)

                .EndDraw()
            End With

        End If
    End Sub


End Class

 

下面是效果图

image

 

从上图能看出四种类型的不同。左上是Miter,右上是Bevel,左下是Round,右下是MiterOrBevel

 

在网上搜到的官网的Direct2D的帮助文档。http://msdn.microsoft.com/zh-cn/library/windows/desktop/dd370990(v=vs.85).aspx,可以参考一下。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)
通过《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBalancerClient接口来获取某个服务的具体实例,并根据实例信息来发起服务接口消费请求。
2600 0
或许是 Nginx 上配置 HTTP2 最实在的教程了
从 2015 年 5 月 14 日 HTTP/2 协议正式版的发布到现在已经快有一年了,越来越多的网站部署了 HTTP2,HTTP2 的广泛应用带来了更好的浏览体验,只要是 Modern 浏览器都支持,所以部署 HTTP2 并不会带来太多困扰。
35353 0
Directx11教程38 纹理映射(8)
上篇日志中,我们用纹理和光照颜色调制的方式得到最终颜色,本章我们尝试用纹理采样的颜色,直接做为材质的漫反射系数Kd,并用它来做光照计算,最后再做个gamma校正,如果不做的话,效果会偏亮。      lighttex.
716 0
SharpDX之Direct2D教程I——简单示例和Color(颜色)
研究Direct2D已经有一段时间了,也写了一个系列的文章 Direct2D ,是基于Windows API Code Pack 1.1。在前文 Direct2D教程VIII——几何(Geometry)对象的运算,本系列的终结篇 中介绍,由于Windows API Code Pack 1.1有错误问题,加上长时间没有更新(可以看出是2010年推出的),于是终止了该系列的教程。
898 0
Directx11教程(46) alpha blend(3)
现在我们尝试改变box的贴图,使用一张带alpha的dds文件wirefence.dds, 用directx texture tool打开文件界面如下:       实际上,这幅图中一些像素有alpha值,一些像素alpha值为0,我们点击View-alpha channel only,可以看到下面的图,其中黑色部分的alpha值为0:      现在我们把这幅图贴到box上,程序运行效果如下: 我们在lighttex.ps中增加以下代码,需要注意clip函数的使用。
683 0
Directx11教程(47) alpha blend(4)-雾的实现
除了用来实现透明效果之外,我们还可以用alpha blend来实现雾(fog)的效果。通过逐渐清晰的雾气效果,可以增加场景的真实感。      雾的效果实现很简单,首先我们要一种颜色来表示雾,通常使用用灰色。
736 0
Directx11教程(48) depth/stencil buffer的作用
在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所示,framebuffer中一个像素,有相对应的depth buffer和stencil buffer值:         D3D11中,depth buffer和stencil buffer一起定义,比如DXGI_FORMAT_D24_UNORM_S8_UINT,是指用一个无符号24位的值做为像素的深度缓冲值,并把它映射到[0,1],用一个8位的值表示像素stencil值,并把它映射到[0,255]。
818 0
《手机测试Robotium实战教程》—第2章2.1节JDK安装及其环境变量配置
因为要用到Java语言,所以JDK是首先需要安装的。可以通过下面的链接,选择对应平台的JDK版本进行下载。
1361 0
超实用的 Nginx 极简教程
概述 什么是 Nginx? Nginx (engine x) 是一款轻量级的 Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。 什么是反向代理? 反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
1741 0
+关注
万仓一黍
算法研究
151
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载