转载请注明出处:http://www.cnblogs.com/Ray1024

一、问题描述

在MFC中使用Direct2D有现成的方法,在Visual Studio 2010 SP1及以上环境中MFC封装了Direct2D,我们就可以更加方便、更加简洁地使用Direct2D来进行高效率绘图了,详细教程见msdnhttps://msdn.microsoft.com/zh-cn/library/gg482848.aspx
但是在实际项目中遇到一个问题:MFC项目编码方式为unicode时,CRenderTarget::DrawText()方法正常;但是编码方式为多字节编码时,CRenderTarget::DrawText()绘制中文出现乱码。如下图:
 

二、问题分析

这个问题出现之后,我设置断点定位到CRenderTarget::DrawText()调用处,F11进入afxrendertarget.cpp文件中的函数CRenderTarget::DrawText() 内部,查看函数如下:

void CRenderTarget::DrawText(const CString& strText,
const CD2DRectF& rect, CD2DBrush* pForegroundBrush,
CD2DTextFormat* textFormat,
D2D1_DRAW_TEXT_OPTIONS options,
DWRITE_MEASURING_MODE measuringMode)
{
USES_CONVERSION; if (m_pRenderTarget == NULL)
{
ASSERT(FALSE);
return;
} if (!VerifyResource(pForegroundBrush))
{
return;
} if (textFormat == NULL)
{
// Use default text format
if (m_pTextFormatDefault == NULL)
{
NONCLIENTMETRICS NonClientMetrics;
NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS); ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, NonClientMetrics.cbSize, &NonClientMetrics, 0); m_pTextFormatDefault = new CD2DTextFormat(this, NonClientMetrics.lfMenuFont.lfFaceName, (FLOAT)abs(NonClientMetrics.lfMenuFont.lfHeight));
} textFormat = m_pTextFormatDefault;
} if (!textFormat->IsValid())
{
ASSERT(FALSE);
return;
} m_pRenderTarget->DrawText(T2CW(strText), strText.GetLength(), textFormat->m_pTextFormat, &rect,
*pForegroundBrush, options, measuringMode);
}

这是CRenderTarget封装的DrawText,内部使用ID2D1RenderTarget对象调用DrawText函数,第一个参数为宽字节字符串,第二个参数为宽字节字符串的长度。

但是这里有一个问题,假如字符串为"中文中文123", 当工程编码为Unicode时,CString使用wchar_t初始化,GetLength获取的长度是7 ;当工程编码为多字节时,CString使用char初始化,GetLength获取的长度是11(因为多字节编码只能用两个ANSI字符表示一个中文字符) 。而你的工程是多字节编码,下面的第一个参数为宽字节字符串,长度为7;但是第二个参数获取到的长度却是11,所以会出现乱码 。这里应该是CRenderTarget中的一个bug,正确的第二个参数应该是第一个参数T2CW(strText)的实际长度wcslen(T2CW(strText)) 。
到这里我们验证了一个结论,这种情况下中文显示出现乱码是因为MFC中CRenderTarget类内部的一个BUG,这样我们就找到了问题的根源。
 

三、解决方案

然而,知道了这个BUG并没有什么卵用,因为afxrendertarget.cpp文件是MFC内部的只读文件,我们并不能对CRenderTarget类做任何改动(摊手)。
但是,我们可以绕个路来解决这个问题:可以使用Direct2D原生API(ID2D1RenderTarget::DrawText())来实现绘制中文,我们在这里把第二个参数改成wcslen(T2CW(strText)),就可以正常地显示中文了,如下:
CString strText(_T("中文Hello, World!"));

//pRenderTarget->DrawText(strText, rect, m_pBlackBrush, m_pTextFormat);

// 把原来的DrawText替换成这个
USES_CONVERSION;
pRenderTarget->GetHwndRenderTarget()->DrawText(
T2CW(strText),
wcslen(T2CW(strText)),
m_pTextFormat->Get(),
&D2D1::Rect(rect.left, rect.top, rect.right, rect.bottom),
m_pBlackBrush->Get());

当然,我们也可以直接改工程编码方式为Unicode编码,这样也不会出现乱码(简单粗暴,哈哈),只是有些工程出于种种原因只能用多字节编码方式,这样就可以使用上面的方法了。

搞定!

记一个CRenderTarget中的BUG及解决办法的更多相关文章

  1. 表与表的关系把RD搞乱了,记一个Procedure中的bug

    就是6张表的关联查询,写了一个存储过程,使用4层for来处理 bug:最后一个for中,两张表的关联条件少了一个,结果数据多查了. 排查办法:使用dbms_output.printline('');每 ...

  2. 记CRenderTarget:DrawText()绘制中文乱码的BUG及解决办法

    原文:记CRenderTarget:DrawText()绘制中文乱码的BUG及解决办法 转载请注明出处:http://www.cnblogs.com/Ray1024 一.问题描述 在MFC中使用Dir ...

  3. 【转载】IE浏览器常见的9个css Bug以及解决办法

    IE浏览器常见的9个css Bug以及解决办法 我们在浏览网页的时候经常看见这样的现象:某个网页在IE6浏览器中打开很正常,但是在IE8里面打开可能完全变形了.或者也有可能出现完全相反的现象.这让We ...

  4. vsftp在REDHAT,CENTOS 5中登录慢的解决办法

    vsftp在REDHAT,CENTOS 5中登录慢的解决办法 vsftp在REDHAT,CENTOS 5中不仅登录慢,至少花30秒左右,而且上传文件的速度也受影响, 经过摸索,根本原因在DNS解析上花 ...

  5. linux中tomcat内存溢出解决办法

    用命令 tail -f /root/apache-tomcat-6.0.20/logs/catalina.out(需要找到tomcat路径) 查看日志,查看是否有错误 linux中tomcat内存溢出 ...

  6. Dumpzilla工具第615行bug的解决办法

    Dumpzilla工具第615行bug的解决办法   在Dumpzilla使用选项frequency时,会提示SQL语法错误.这是由于其中SQL语句编写错误.需要将615行中: where url l ...

  7. ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务解决办法

    ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务解决办法: 1.首先打开cmd命令 查看本地TNSPING配置 是否ok?然后找到 Oracle 安装文件 中 listener. ...

  8. .net core, docker 在vs2019开发过程中的问题以及解决办法

    .net core, docker 在vs2019开发过程中的问题以及解决办法 记录下来,帮助Ta人~ 1.vs调试,快Build完后提示Docker 端口:xxxx,xxxx,xxxx占用 解决办法 ...

  9. Silverlight:telerik RadControls中RadGridView的一个Bug及解决办法(转载)

    当RadGridView中嵌套RadComboBox,且RadGridView的高度不够出现滚动条时,上下拉动滚动条后,RadComboBox中的选中值将丢失! 如下图: 滚动条未拖动前 滚动条上下拖 ...

随机推荐

  1. 从 Bridge 到 OVS,探索虚拟交换机

    Linux Bridge 和物理网络一样,虚拟网络要通信,必须借助一些交换设备来转发数据.因此,对于网络虚拟化来说,交换设备的虚拟化是很关键的一环. 上文「网络虚拟化」已经大致介绍了 Linux 内核 ...

  2. uva 1378 - A Funny Stone Game(组合游戏)

    题目链接:uva 1378 - A Funny Stone Game 题目大意:两个人玩游戏,对于一个序列,轮流操作.每次选中序列中的i,j,k三个位置要求i<j≤k,然后arr[i]减1,对应 ...

  3. UVA - 11082 Matrix Decompressing(最大流+行列模型)

    题目大意:给出一个R行C列的矩阵,如今给出他的前1-R行和 && 前1-C列和,问这个矩阵原来是如何的,要求每一个元素大小在1-20之间 解题思路:将每一行连接到超级源点,容量为该行的 ...

  4. iOS 力学动画生成器UIKit Dynamics 之碰撞效果解说

    UIKit Dynamic是iOS7 新增的一组类和方法.可赋予UIView逼真的行为和特征,不须要写动画效果那些繁琐的代码,让开发者可以轻松地改善应用的用户体验.一共同拥有6个可用于定制UIDyna ...

  5. Ajax 学习总结

    Ajax 技术在 JavaWeb 应用中随处可见,比如购物车中根据商品数量及时更新等应用,那么我们今天就来说说 Ajax 的一些小应用! Ajax 技术也就是允许浏览器与服务器通信而无需刷新当前页面, ...

  6. OS X第三方类库管理工具cocoapods入门

    一.简介 什么是cocoapods?--是OS X和iOS下一个第三方类库管理工具.通过cocoapods,可以为项目添加"Pods"依赖库,并且管理其版本. cocoapods好 ...

  7. strus2项目中百度编辑器运用的几点细节

    百度编辑器的运用可以参考我之前写的一篇文章,在java项目中加入百度富文本编辑器.这篇文章是以maven+spring mvc项目进行的,总得来说配置比较简单,但是如果是想在strus2项目中配置ue ...

  8. Spring Boot整合 JdbcTemplate

    (1) 在pom.xml加入jdbcTemplate的依赖: (2) 编写DemoDao类,声明为:@Repository,引入JdbcTemplate (3) 编写DemoService类,引入De ...

  9. 关于Idea中右边的maven projects窗口找不到了如何调出来

    关于Idea中右边的maven  projects窗口找不到了如何调出来? 具体的idea版本我不太清楚,我用的是2016版,其他版本应该也是一样的. 首先idea自带了maven控件,不像Eclip ...

  10. CSS3渐变相关

    背景渐变 background: -moz-linear-gradient( top,#f24652,#da2c3c); background: -o-linear-gradient(top,#f24 ...