转载请注明出处: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. UAC

    UAC and Security Shield Icon UAC in Wiki User Account Control (UAC) is a technology and security inf ...

  2. MySQL远程訪问的两个问题

    安装MySQL后,不能远程訪问.进行例如以下配置就可以 连接后,依旧不能连接,报例如以下错误: 1042 - Can't get hostname for your address 解决方法在my.i ...

  3. Oracle之PLSQL

    PL/SQL Developer是一个集成开发环境,专门开发面向Oracle数据库的应用.PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)它是Ora ...

  4. 腾讯云安全:移动 APP 安全行业报告

    移动 APP 已逐步渗透入我们的生活,据统计,2016年,APP 发行数量仅电商.金融.游戏这三大类共计高达2万左右,国内移动互联网活跃用户数已经突破10亿,移动互联网这样快速的推移,移动互联网的安全 ...

  5. 前端笔记----类型转换display

    display属性用来在行内元素,块元素,行内块元素之间进行转化. 常用的属性有: 1.none :元素隐藏且不占位置,相当于不存在,一般用在动态展示效果:2.block :元素以块元素显示,有些行内 ...

  6. junit初探

    由于公司规模不大,所以测试方面一直不是很正规,都是做完一个功能,稍微测试一下,没有做单元测试,所以自然也没有接触过类似于junit这类测试的工具. 今天有空研究了一下junit,顾名思义,这是给jav ...

  7. mybatis转义符(转)

    第一种方法: 用了转义字符把>和<替换掉,然后就没有问题了. SELECT * FROM test WHERE 1 = 1 AND start_date  <= CURRENT_DA ...

  8. MPSOC之7——开发流程uramdisk

    用petalinux的预编译目录里有rootfs文件,选择rootfs.tar.gz作为初始输入. 1.原始文件-->uramdisk 1.1 解压原始rootfs.tar.gz,得到若干文件 ...

  9. github not authorized eclipse 关于 代码不能提交到GitHub

    eclipse/myeclipse > menu > window > preferences > general > security > content > ...

  10. 《程序设计语言——实践之路【PDF】下载

    <程序设计语言--实践之路[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382240 内容简介 <程序设计语言--实践之路(第3版 ...