场景

  1. 有一次开发WTL窗口时,使用GDICMemoryDC来绘制中文文字显示不出来,但是文字改为英文就绘制出来的,确认字符集,字体,坐标都没问题,那是什么情况?

说明

  1. 在开发WTL程序时, 我们有时候会容易混合使用GDIGDI+,比如使用GDICDC的方法RoundRect绘制圆角矩形,而GDI+没有类似的方法。同样,使用GDI+轻松绘制png图片,而GDI绘制需要繁琐的转换。但是,实际上,微软MSDN文档说明GDIGDI+是不能混用的,上边的绘制不出来中文就是混用导致的结果之一。

  2. 微软的文档说明 GDI 和 GDI + 之间的互操作性 介绍了4种需要互操作性的情况,我们最常用的就是第三种情况在 GDI HDC 上使用 GDI +. 也就是说在创建Gdiplus::Graphics(HDC)之后如果需要使用HDC,那么有两种方式:

    2.1. 请先销毁Graphics再使用HDC.

    2.2. 使用Graphics.GetHDC()来创建新的HDC,之后直到调用Graphics.ReleaseHDC()之前不要使用Graphics对象.

您可以通过使用采用 HDC 作为参数的图形构造函数来协助在 HDC 上使用 GDI +。 可以使用此方法在 HDC 上绘制 Graphics 类的绘图成员。 将 Graphics 对象附加到 HDC 后,不应在 HDC 上执行任何 GDI 操作,直到 Graphics 对象损坏或超出范围。 如果在 HDC 上需要 GDI 输出,请先销毁 Graphics 对象,然后再使用原始 HDC 或使用 Graphics::GetHDC() 获取新的 hdc,然后按照本文前面所述的规则进行互操作,同时对 GDI + 对象使用 gdi。

例子

  1. 以下例子说明如何使用GDIGDI+混用的方式,它是微软官方说明的第三种情况,也有3种用法。

View.h

// View.h : interface of the CView class
//
/#pragma once#include <GdiPlus.h>
#include <atlmisc.h>class CView : public CWindowImpl<CView>
{public:DECLARE_WND_CLASS(NULL)BOOL PreTranslateMessage(MSG* pMsg);BEGIN_MSG_MAP_EX(CView)MSG_WM_CREATE(OnCreate)MSG_WM_DESTROY(OnDestroy)MESSAGE_HANDLER(WM_PAINT, OnPaint)END_MSG_MAP()LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);int OnCreate(LPCREATESTRUCT lpCreateStruct);void PaintImage(CDC& cdc,CRect& rect);void OnDestroy();private:Gdiplus::Font* font_;HFONT font_normal_;Gdiplus::Bitmap* bitmap_;
};

View.cpp

// View.cpp : implementation of the CView class
//
/#include "stdafx.h"
#include "resource.h"
#include <GdiPlus.h>
#include <atlmisc.h>
#include <string>
#include "View.h"using namespace std;
using namespace Gdiplus;static HFONT GetHFONT(int em,int charset = DEFAULT_CHARSET,bool bold = false,const wchar_t* fontName = L"Arial")
{LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); // zero out structure lf.lfHeight = em; // request a 8-pixel-height fontlf.lfCharSet = charset;lstrcpy(lf.lfFaceName,fontName); // request a face name "Arial"if(bold)lf.lfWeight = FW_BOLD;elself.lfWeight = FW_NORMAL;HFONT font = ::CreateFontIndirect(&lf);return font;
}static Gdiplus::Font* GetGDIFont(HDC hdc,int em,int charset = DEFAULT_CHARSET,bool bold = false,const wchar_t* fontName = L"Arial")
{LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); // zero out structure lf.lfHeight = em; // request a 8-pixel-height fontlf.lfCharSet = charset;lstrcpy(lf.lfFaceName,fontName); // request a face name "Arial"if(bold)lf.lfWeight = FW_BOLD;elself.lfWeight = FW_NORMAL;return new Gdiplus::Font(hdc,&lf);
}int CView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{auto one = GetDC();font_ = GetGDIFont(one,16);ReleaseDC(one);font_normal_= GetHFONT(16);bitmap_ = new Bitmap(L"res\\toolbar.bmp");return 0;
}BOOL CView::PreTranslateMessage(MSG* pMsg)
{pMsg;return FALSE;
}void CView::PaintImage(CDC& cdc,CRect& rect)
{static std::wstring title(L"学院课程: C++17语言特性和标准库-第一部");static std::wstring url(L"https://edu.csdn.net/course/detail/30136");CSize size;cdc.GetTextExtent(title.c_str(),title.size(),&size);CRect rectText(CPoint(100,130),size);cdc.DrawText(title.c_str(),title.size(),rectText,DT_LEFT);// 2. 可以用大括号进行包括graphics进行绘制,当语句块结束时,graphics会销毁.// 接着再使用原HDC.{Gdiplus::Graphics graphics(cdc);graphics.DrawImage(bitmap_,100,180);// 混淆GDI+和GDI方式3// 如果需要使用HDC,通过GetHDC()方法来锁定graphics,之后再通过方法ReleaseHDC释放锁定graphics.auto hdc = graphics.GetHDC();CDCHandle dc(hdc);rectText.MoveToY(200);dc.DrawText(title.c_str(),title.size(),rectText,DT_LEFT);graphics.ReleaseHDC(hdc);graphics.DrawImage(bitmap_,100,220);}cdc.GetTextExtent(url.c_str(),url.size(),&size);rectText = CRect(CPoint(100,160),size);cdc.DrawText(url.c_str(),url.size(),rectText,DT_LEFT);
}void CView::OnDestroy()
{delete font_;DeleteObject(font_normal_);
}// 第三种情况. hdc作为Graphics的参数传入,在Graphics销毁之前不要使用hdc.
LRESULT CView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{CPaintDC dc(m_hWnd);CMemoryDC mdc(dc,dc.m_ps.rcPaint);mdc.SelectFont(font_normal_);CRect rect;GetClientRect(&rect);mdc.FillSolidRect(rect,RGB(255,255,255));static std::wstring temp(L"https://blog.csdn.net/infoworld");// 混淆GDI+和GDI方式1.PaintImage(mdc,rect);// 混淆GDI+和GDI方式2,放到最后再使用graphics绘制.Graphics graphics(mdc);RectF rectf_text;rectf_text.X = 100;rectf_text.Y = 100;graphics.MeasureString(temp.c_str(),temp.size(),font_,rectf_text,&rectf_text);auto sf = StringFormat::GenericDefault();Color color;color.SetFromCOLORREF(RGB(0,0,0));SolidBrush sb(color);graphics.DrawString(temp.c_str(),temp.size(),font_,rectf_text,sf,&sb);return 0;
}

截图

下载地址

项目代码

参考

  1. 中文有些翻译的不正确,可以结合英文看。比如这句
如果在 HDC 上需要 GDI 输出,请先销毁 Graphics 对象,然后再使用原始 HDC 或使用 Graphics::GetHDC() 获取新的 hdc...

原英文是:

 If GDI output is required on the HDC, either destroy the Graphics object before using the original HDC or use Graphics::GetHDC() to get a new HDC...

应该是:

如果在 HDC 上需要 GDI 输出,请先销毁 Graphics 对象,然后再使用原始 HDC; 或者使用 Graphics::GetHDC() 获取新的 hdc...

GDI 和 GDI + 之间的互操作性

Interoperability between GDI and GDI+

[ATL/WTL]_[Gdiplus]_[关于混用GDI和GDI+(GDIPlus)导致显示不正常的解决方案]相关推荐

  1. [WTL/ATL]_[Gdiplus]_[绘制虚线并设置破折号空格的宽度]

    场景 WTL界面开发时,有些情况下需要绘制虚线,比如圆角矩形的虚线,默认的破折号和点之间的空格特别小,看着比较密集,那么如何增加点线之间的空格,或者增加破折号的长度? 说明 使用Gdiplus绘制圆角 ...

  2. [ATL/WTL]_[初级]_[自定义多列TreeView]

    场景 在开发 Win32,WTL,MFC 程序时,经常会用到 ListView 这个表格控件,ListView 的数据是按照行来显示的,行与行之间没有并没有什么关系.但是如果行之间有父子关系,比如像树 ...

  3. MATLAB_4-形态学_腐蚀_膨胀_灰度图的腐蚀以及膨胀_开运算_闭运算_文章末尾有几个素材例子

    素材链接: MATLAB_4-形态学_课程需要的素材 记住单词拼写: 腐蚀 erode 膨胀 dilate 开运算 open 闭运算 close 图像重建 imreconstruct reconstr ...

  4. 计算机会计课程试题及答案,计算机会计第2次作业_报表_附答案

    计算机会计第2次作业_报表_附答案 (6页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 . . . . .<计算机会计>课程作业 ...

  5. java语言仅支持单重继承_java语言程序设计基础篇习题_复习题_第十一章

    java语言程序设计基础篇习题_复习题_第十一章 11.1 下面说法是真是假?一个子类是父类的子集. 11.2 使用什么关键字来定义一个子类 11.3 什么是单一继承?什么是多重继承?java支持多重 ...

  6. 宏定义中的#、##操作符和... 、 _ _VA_ARGS_ _解析

    #   #符号作为一个预处理运算符,它可以把语言符号转化成字符串.例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串.该过程称为字符串化(stringizing). 例子 #incldu ...

  7. 计算机软件专业 课程,_计算机软件_专业的课程设置.pdf

    _计算机软件_专业的课程设置.pdf 机械职业教育 2007.5 专业建设 - - 27 计算机软件 专业的课程设置 < > ◎ 方一新 王 竝 摘 要 职业教育必须坚持以就业为导向 加快 ...

  8. C++语言程序设计视频教程_清华大学_郑莉(基础篇+进阶篇)

    C++语言程序设计视频教程_清华大学_郑莉(基础篇) 第一章:绪论 1.1 导学 1.2 计算机系统简介 1.3计算机语言和程序设计方法的发展 1.4 面向对象的基本概念 1.5 程序的开发过程 1. ...

  9. 统计_statistics_不同的人_大样本_分析_统计方法_useful ?

    统计_statistics_不同的人_大样本_分析_ 转载于:https://www.cnblogs.com/books2read/p/11313825.html

  10. 作业调度算法--高响应比优先 操作系统_处理器管理_编程题

    操作系统_处理器管理_编程题 作业调度算法–高响应比优先 输入N个作业,输入每个的作业名字,到达的时间,服务的时间,根据高响应比优先算法,计算出每个作业的完成的时间,周转的时间,带权周转的时间(其中保 ...

最新文章

  1. PAT甲级1108 Finding Average :[C++题解]stof、字符串变成浮点数、try和catch捕获异常、C++语法题
  2. ArcEngine的鼠标事件中按键判断~
  3. 转载:LINQ to SQL更新数据库操作
  4. BZOJ-1192-鬼谷子的钱袋
  5. 多版本JDK切换方式
  6. 自定义jackson序列化_Jackson中的自定义反序列化程序和验证
  7. 庆祝西安.NET俱乐部成立,请申请加入的朋友在这里报到
  8. 用HTML5实现人脸识别
  9. linux系统中命令执行的优先级以及命令格式
  10. 关于qt+vs2019报错的奇葩问题,无法定位程序输入点
  11. 使用jQuery播放/暂停 HTML5视频
  12. python实现新年倒计时代码
  13. 6个优秀的图片素材网站,全部免费
  14. wsl Java开发_WSL2 + Docker + IDEA 开发到发布一步到位
  15. 移动端web设计尺寸_手机移动端网页按钮设计尺寸及间距规范
  16. 谁买了方舟正版火影服务器,《方舟》火影服再次被玩家恶搞!漩涡鸣人:我不要面子的吗!...
  17. 简单理解椭圆曲线的非对称加密应用
  18. SQL修改表结构写法
  19. C++中this的理解
  20. git删除目录下的所有文件并提交

热门文章

  1. [转]网络安全设备Bypass功能介绍及分析 - [网络编程]
  2. 提取swf素材_swf素材提取工具
  3. 开源cnc软件_带有开源软件的CNC铣削
  4. php web开发实用教程答案,PHP Web开发实用教程
  5. 三天研读《中兴电路设计规范》精华总结
  6. python github 12306 文贤平_GitHub排名第一!免费最强“抢票神器”在手,程序员抢票再不用跪求加速包...
  7. 疯狂的程序员阅读笔记
  8. webview的使用
  9. 2009年02月《安全天下事》、2009年02月《安全天下事之12月,辩证法之月》、《2008信息安全技术与产业大盘点》...
  10. 2022保密教育线上培训考试参考答案 02