Direct2D+MFC学习笔记
2015-09-08 15:13
447 查看
0.学习初衷
做三角剖分的时候所计算的顶点都是float或者double型变量,而在GDI里画图都是INT型输入参数,这便产生了精度损失的矛盾。找了一圈浮动绘图渲染引擎,发现还是MS的Direct2D更方便些,而且还支持硬件加速,理论上渲染效率比GDI软解的要高。1.环境配置
1.1开发平台
-win8.1 x64-VS2010
-MFC
1.2D2D SDK
可以从MS官网上下载最新的DXSDK1.3环境配置
我这里嫌弃这个SDK太大(600MB)没直接安装,而是从中提取了lib和include文件夹来配置,一样可以使用。整个环境配置如下:a. 在站内下载头文件和库文件压缩包
b. 新建MFC对话框工程
c. 解压缩到该工程目录
d. 工程右键-Properties-Configuration Properties-VC++ Directories的include Directories里添加$(ProjectDir)Include
e. library Directories里添加$(ProjectDir)lib
f. 工程右键-Properties-Configuration Properties-Linker-Additional Deppendencies里添加d2d1.lib;dxguid.lib;dwrite.lib
2.CD2D简单操作类
这里写了一个很简单的封装D2D的类,可以创建销毁各种资源,画文本,画矩形等。代码如下2.1 CD2D.h
[code]#ifndef _CD2D_H #define _CD2D_H #include <D2D1.h>// header for Direct2D #include <Dwrite.h> #define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;} class CD2D { public: CD2D(); ~CD2D(); public: BOOL CreateD2DResource(HWND hWnd); BOOL DrawText(CString sFontName,FLOAT fFontSize, FLOAT left,FLOAT top,FLOAT right,FLOAT bottom,CString sText); BOOL DrawRectangle(FLOAT left,FLOAT top,FLOAT right,FLOAT bottom); void Cleanup(void); protected: private: ID2D1Factory* pD2DFactory; // Direct2D factory ID2D1HwndRenderTarget* pRenderTarget; // Render target ID2D1SolidColorBrush* pBlackBrush; // A black brush, reflect the line color IDWriteFactory* pDWriteFactory; //Dwrite RECT rc ; // Render area HWND hwnd ; // Window handle }; #endif
2.2 CD2D.cpp
[code]#include "stdafx.h" #include "CD2D.h" CD2D::CD2D() { pD2DFactory = NULL; pRenderTarget = NULL; pBlackBrush = NULL; pDWriteFactory = NULL; hwnd = NULL; } CD2D::~CD2D() { if (hwnd) { Cleanup(); } } BOOL CD2D::CreateD2DResource(HWND hWnd) { if (!pRenderTarget) { HRESULT hr ; hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory) ; if (FAILED(hr)) { AfxMessageBox(_T("创建factory失败!")); return (FALSE) ; } hwnd = hWnd; // Obtain the size of the drawing area GetClientRect(hWnd, &rc) ; // Create a Direct2D render target hr = pD2DFactory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( hWnd, D2D1::SizeU(rc.right - rc.left,rc.bottom - rc.top) ), &pRenderTarget ) ; pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); if (FAILED(hr)) { AfxMessageBox(_T("创建target失败!")); return (FALSE) ; } // Create a brush hr = pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &pBlackBrush ) ; if (FAILED(hr)) { AfxMessageBox(_T("创建brush失败!")); return (FALSE) ; } // // Create DirectWrite Factory hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pDWriteFactory) ); if(FAILED(hr)) { AfxMessageBox(_T("创建DirectWrite失败!")); return (FALSE) ; } return (TRUE) ; } return (FALSE) ; } BOOL CD2D::DrawText(CString sFontName,FLOAT fFontSize, FLOAT left,FLOAT top,FLOAT right,FLOAT bottom,CString sText) { IDWriteTextFormat* g_pTextFormat = NULL; HRESULT hr ; CreateD2DResource(hwnd) ; GetClientRect(hwnd, &rc) ; hr = pDWriteFactory->CreateTextFormat( sFontName, // Font family name NULL, // Font collection(NULL sets it to the system font collection) DWRITE_FONT_WEIGHT_REGULAR, // Weight DWRITE_FONT_STYLE_NORMAL, // Style DWRITE_FONT_STRETCH_NORMAL, // Stretch fFontSize, // Size 50.0f L"en-us", // Local &g_pTextFormat // Pointer to recieve the created object ); if(FAILED(hr)) { AfxMessageBox(_T("创建DirectWrite失败!")); return(FALSE); } // Create text layout rect D2D1_RECT_F textLayoutRect = D2D1::RectF(left,top,right,bottom); // Draw text pRenderTarget->BeginDraw() ; pRenderTarget->DrawText( sText, // Text to render sText.GetLength(), // Text length g_pTextFormat, // Text format textLayoutRect, // The region of the window where the text will be rendered pBlackBrush // The brush used to draw the text ); pRenderTarget->EndDraw() ; return (TRUE) ; } BOOL CD2D::DrawRectangle(FLOAT left,FLOAT top,FLOAT right,FLOAT bottom) { CreateD2DResource(hwnd) ; pRenderTarget->BeginDraw() ; // Clear background color white pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White)); // Draw Rectangle pRenderTarget->DrawRectangle( D2D1::RectF(left,top,right,bottom), pBlackBrush ); HRESULT hr = pRenderTarget->EndDraw() ; if (FAILED(hr)) { AfxMessageBox(_T("创建Direct失败!")); return (FALSE); } return (TRUE); } void CD2D::Cleanup(void) { SAFE_RELEASE(pRenderTarget) ; SAFE_RELEASE(pBlackBrush) ; SAFE_RELEASE(pD2DFactory) ; SAFE_RELEASE(pDWriteFactory) ; }
3.在MFC里画图
3.1 XXXDlg.h里声明变量
[code]#include "CD2D.h" ..... private: CD2D m_D2DC; ......
3.2 XXXDlg.cpp里
[code]BOOL CxxxDlg::OnInitDialog() { ...... HWND hwnd = GetSafeHwnd(); m_D2DC.CreateD2DResource(hwnd); ...... } void CxxxDlg::OnPaint() { .... else { if (GetSafeHwnd() != NULL) { m_D2DC.DrawRectangle(50.0,50.0,75.0,75.0); m_D2DC.DrawText(_T("微软雅黑"),20.0,30.0,30.0,250.0,25.0,_T("D2D Hello World!")); CPaintDC dc(this);//GDI画图 dc.MoveTo(300,150); dc.LineTo(250 ,200); dc.LineTo(350 ,300); dc.LineTo(300 ,150); } CDialogEx::OnPaint(); } }
4.结果
根据[code]pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
的设置,得到2个结果
可以看到D2D的抗锯齿效果还是很好的,不过注意,这是以效率下降为代价的,虽然这种损失在工作量小的时候基本感觉不到。
5.参考文献
Direct2D教程(外篇)环境配置Direct2D入门
Direct2D
direct2D 画出来的图形为什么会发虚
6.后记
6.1 高DPI下Direct2D显示不全问题
现在MS系统里默认的是96DPI,但目前很多设备高分辨率在这个DPI下字体很小,根本看不清,只能调高DPI,我的15寸笔记本分辨率是1080p,调整到150% 即使120DPI就很舒服了,但随之而来了一个问题就是MFC里的视图也跟着缩放了150%,解决方法很简单,在D2D初始化的时候添加一行命令[code]pRenderTarget->SetDpi(96.0,96.0);
参考文献
1.Direct2D and High-DPI
2.How to Ensure That Your Application Displays Properly on High-DPI Displays
3.ID2D1DeviceContext::SetUnitMode method
相关文章推荐
- expect中的close,wait,exit,return
- JSON转换工具:fastjson与jackson
- python可变长参数
- WebView
- android 组件设置屏幕大小
- AWK print学习
- 15_09_08 Eclipse导入Android时出现红色感叹号的异常
- MFC改变static text颜色和内容
- swift 下拉图片变大 coreData 声明数组变量
- 微信公众帐号开发教程第10篇-解析接口中的消息创建时间CreateTime
- 今天看了一个利用MYeclipse进行Struts讲解的视频和大家分享一下
- redis剖析(一)redis性能
- codeforces 267A A. Subtractions(辗转相除)
- 零基础学python-12.5 修改列表的误区以及使用for和range修改列表
- 零基础学python-12.5 修改列表的误区以及使用for和range修改列表
- 把linux的man手册转化为windows下可读的格式
- cocos2d-x 接入android ,登录第三方SDK时屏幕不断闪烁刷屏的问题解决
- 微信公众帐号开发教程第9篇-QQ表情的发送与接收
- MongoDB 索引简单使用技巧
- Unity Surface Shader输入结构体的定义