这一篇距离上一篇整整隔了3个月,主要的原因大部分在学习绘图和DirectX2D的用法,学习C++,学习各种东西,另外部分原因是工作忙,不过这是借口。我学习DirectX2D的过程并不很愉快,经常看到不理解的古怪的行为,这可能是我没有开发过图形界面,现在把我学习到的总结出来,请高人们指正。
关于绘图方法应该有很很话题可以讨论,第0篇只是简单把基础的封装类作个说明,下一篇开始讨论多线程绘图和优化的一些方法作个铺垫。我用的平台是Win7+VC2010+SDK7.0a+DirectX June 2010
1.CDxFactorys对工厂封装
首先用CDxFactorys对几个工厂作个封装,他的工作有:
1 初始化的时候生成ID2D1Factory,IWICImagingFactory,IDWriteFactory的实例。
2.创建ID2D1HwndRenderTarget
3.获取屏幕Dpi
CDxFactorys应是Sigleton模式,在程序的各处都可以访问到唯一的实例。
这个类很平常,没有太多可说的。
1 class WARMGUI_API CDxFactorys {
2 private:
3 CDxFactorys();
4 ~CDxFactorys();
5
6 public:
7 HRESULT CreateRenderTarget(HWND hwnd, ID2D1HwndRenderTarget ** pHwndRenderTarget);
8 ID2D1Factory* GetD2DFactory();
9 IWICImagingFactory* GetImgFactory();
10 IDWriteFactory* GetDWriteFactory();
11
12 HRESULT InitDxFactory();
13 void ReleaseResource();
14
15 static CDxFactorys * GetInstance();
16 public:
17 float m_dpiScaleX;
18 float m_dpiScaleY;
19
20 protected:
21 ID2D1Factory * m_pD2DFactory;
22 IWICImagingFactory * m_pImgFactory;
23 IDWriteFactory * m_pDWriteFactory;
24 };
2. eArtist对绘图函数作封装
MFC用CDC类对绘制图形和文本作封装,我对应的类叫做艺术家,前面加个e表示电子艺术家eArtist,以区别传统的作画方法,以后会有特效动画什么的,但目前我用到的,还仅仅是对绘图和文字部分作的封装.有几点需要说明:
1. 在Direct2D的文档中特别强调绘图资源在GPU上的时间开销很大,因此建议尽量保留已有的绘图资源,不要频繁的创建和删除绘图资源。这写在文档Improving the Performance of Direct2D Applications中,因此上eArtist初始化如下的资源,直到应用程序退出再销毁他们:一个Hwnd-RenderTarget和从他派生出来的Bitmap-RenderTarget,默认的画刷SolidColorBrush,一个默认的StrokeStyle,以及默认的TextFormat等等。
2. Dx2D的绘图要在ID2D1RenderTarget接口的BeginDraw()和EndDraw()之中完成,这两个函数成对出现。如果想要在屏幕上看到图形,则必须在Hwnd-RT的调用EndDraw之后,才会把结果呈现出来。
3. 坐标变换在绘图过程中经常用到,最好在GPU上完成,必须小心的使用才能在正确的位置画出图形,我现在还经常被这个搞晕菜,这点在后面的例程中再讨论。
4. 指定artist当前使用Hwnd-RT或Bitmap-RT,Bitmap-RT有点类似于以前常用的MemoryDC,这两种RenderTarget各种用场,要参考DX2D的文档。
5. 用CreateBitmap创建一个位图,用CopyFromRenderTarget从当前的RenderTarget上拷贝到位图,Again,创建资源是消耗GPU时间的,应尽量避免,创建之后尽可能多的使用CopyFromXXX函数
eArtist的代码看起来是这样的:
1 class WARMGUI_API eArtist
2 {
3 public:
4 eArtist(void);
5 ~eArtist(void);
6
7 ///初始化
8 void Init(HWND hwnd);
9 ///重新设置RenderTarget大小
10 inline HRESULT ResizeRenderTarget(int cx, int cy);
11
12 ///设定资源属性
13 inline HRESULT SetStrokeStyle(.);
14 inline HRESULT SetSolidColorBrush();
15 inline HRESULT SetTextFormat();
16
17 ///绘图函数
18 inline void DrawText();
19 inline void DrawLine();
20 inline void DrawBitmap();
21 inline void DrawRectangle();
22 inline void FillRectangle();
23 inline void DrawEllipse();
24 inline void FillEllipse();
25
26 ///用默认的Bitmap-RenderTarget绘图
27 inline void BeginBmpDraw(bool clear = false);
28 inline HRESULT EndBmpDraw();
29 ///用默认的Hwnd-RenderTarget绘图
30 inline void BeginDraw(bool clear = false);
31 inline HRESULT EndDraw();
32
33 ///设定当前使用的RenderTarget为Hwnd-RenderTarget
34 inline void UsingHwndRT();
35 ///设定当前使用的RenderTarget为Bitmap-RenderTarget
36 inline void UsingBmpRT();
37 ///执行所有阻塞的绘图动作
38 inline HRESULT Flush();
39
40 ///坐标变换
41 inline void SetTransform(MATRIX_2D_t* trans, bool bIsHwndRT = true);
42 inline void GetTransform(MATRIX_2D_t* trans, bool bIsHwndRT = true);
43
44 ///创建一个Bitmap
45 inline HRESULT CreateBitmap(ID2D1Bitmap** pBitmap, RECT& rect);
46 ///拷贝RenderTarget图形到位图
47 inline HRESULT CopyFromRenderTarget(ID2D1Bitmap* pBitmap, POINT pointDest, RECT rectSrc);
48
49
50 private:
51 ID2D1HwndRenderTarget* _pHwndRT;
52 ID2D1BitmapRenderTarget* _pDefaultBmpRT;
53 ID2D1SolidColorBrush* _pscBrush;
54 ID2D1StrokeStyle* _pStroke;
55 IDWriteTextFormat* _pTextFormat;
56 IDWriteTextLayout* _pTextLayout;
57 HWND _hwnd;
58 };
59