[ATL/WTL]_[Gdiplus]_[关于混用GDI和GDI+(GDIPlus)导致显示不正常的解决方案]
场景
- 有一次开发
WTL
窗口时,使用GDI
的CMemoryDC
来绘制中文文字显示不出来,但是文字改为英文就绘制出来的,确认字符集,字体,坐标都没问题,那是什么情况?
说明
在开发
WTL
程序时, 我们有时候会容易混合使用GDI
和GDI+
,比如使用GDI
的CDC
的方法RoundRect
绘制圆角矩形,而GDI+
没有类似的方法。同样,使用GDI+
轻松绘制png
图片,而GDI
绘制需要繁琐的转换。但是,实际上,微软MSDN
文档说明GDI
和GDI+
是不能混用的,上边的绘制不出来中文就是混用导致的结果之一。微软的文档说明 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。
例子
- 以下例子说明如何使用
GDI
和GDI+
混用的方式,它是微软官方说明的第三种情况,也有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;
}
截图
下载地址
项目代码
参考
- 中文有些翻译的不正确,可以结合英文看。比如这句
如果在 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)导致显示不正常的解决方案]相关推荐
- [WTL/ATL]_[Gdiplus]_[绘制虚线并设置破折号空格的宽度]
场景 WTL界面开发时,有些情况下需要绘制虚线,比如圆角矩形的虚线,默认的破折号和点之间的空格特别小,看着比较密集,那么如何增加点线之间的空格,或者增加破折号的长度? 说明 使用Gdiplus绘制圆角 ...
- [ATL/WTL]_[初级]_[自定义多列TreeView]
场景 在开发 Win32,WTL,MFC 程序时,经常会用到 ListView 这个表格控件,ListView 的数据是按照行来显示的,行与行之间没有并没有什么关系.但是如果行之间有父子关系,比如像树 ...
- MATLAB_4-形态学_腐蚀_膨胀_灰度图的腐蚀以及膨胀_开运算_闭运算_文章末尾有几个素材例子
素材链接: MATLAB_4-形态学_课程需要的素材 记住单词拼写: 腐蚀 erode 膨胀 dilate 开运算 open 闭运算 close 图像重建 imreconstruct reconstr ...
- 计算机会计课程试题及答案,计算机会计第2次作业_报表_附答案
计算机会计第2次作业_报表_附答案 (6页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 . . . . .<计算机会计>课程作业 ...
- java语言仅支持单重继承_java语言程序设计基础篇习题_复习题_第十一章
java语言程序设计基础篇习题_复习题_第十一章 11.1 下面说法是真是假?一个子类是父类的子集. 11.2 使用什么关键字来定义一个子类 11.3 什么是单一继承?什么是多重继承?java支持多重 ...
- 宏定义中的#、##操作符和... 、 _ _VA_ARGS_ _解析
# #符号作为一个预处理运算符,它可以把语言符号转化成字符串.例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串.该过程称为字符串化(stringizing). 例子 #incldu ...
- 计算机软件专业 课程,_计算机软件_专业的课程设置.pdf
_计算机软件_专业的课程设置.pdf 机械职业教育 2007.5 专业建设 - - 27 计算机软件 专业的课程设置 < > ◎ 方一新 王 竝 摘 要 职业教育必须坚持以就业为导向 加快 ...
- C++语言程序设计视频教程_清华大学_郑莉(基础篇+进阶篇)
C++语言程序设计视频教程_清华大学_郑莉(基础篇) 第一章:绪论 1.1 导学 1.2 计算机系统简介 1.3计算机语言和程序设计方法的发展 1.4 面向对象的基本概念 1.5 程序的开发过程 1. ...
- 统计_statistics_不同的人_大样本_分析_统计方法_useful ?
统计_statistics_不同的人_大样本_分析_ 转载于:https://www.cnblogs.com/books2read/p/11313825.html
- 作业调度算法--高响应比优先 操作系统_处理器管理_编程题
操作系统_处理器管理_编程题 作业调度算法–高响应比优先 输入N个作业,输入每个的作业名字,到达的时间,服务的时间,根据高响应比优先算法,计算出每个作业的完成的时间,周转的时间,带权周转的时间(其中保 ...
最新文章
- PAT甲级1108 Finding Average :[C++题解]stof、字符串变成浮点数、try和catch捕获异常、C++语法题
- ArcEngine的鼠标事件中按键判断~
- 转载:LINQ to SQL更新数据库操作
- BZOJ-1192-鬼谷子的钱袋
- 多版本JDK切换方式
- 自定义jackson序列化_Jackson中的自定义反序列化程序和验证
- 庆祝西安.NET俱乐部成立,请申请加入的朋友在这里报到
- 用HTML5实现人脸识别
- linux系统中命令执行的优先级以及命令格式
- 关于qt+vs2019报错的奇葩问题,无法定位程序输入点
- 使用jQuery播放/暂停 HTML5视频
- python实现新年倒计时代码
- 6个优秀的图片素材网站,全部免费
- wsl Java开发_WSL2 + Docker + IDEA 开发到发布一步到位
- 移动端web设计尺寸_手机移动端网页按钮设计尺寸及间距规范
- 谁买了方舟正版火影服务器,《方舟》火影服再次被玩家恶搞!漩涡鸣人:我不要面子的吗!...
- 简单理解椭圆曲线的非对称加密应用
- SQL修改表结构写法
- C++中this的理解
- git删除目录下的所有文件并提交
热门文章
- [转]网络安全设备Bypass功能介绍及分析 - [网络编程]
- 提取swf素材_swf素材提取工具
- 开源cnc软件_带有开源软件的CNC铣削
- php web开发实用教程答案,PHP Web开发实用教程
- 三天研读《中兴电路设计规范》精华总结
- python github 12306 文贤平_GitHub排名第一!免费最强“抢票神器”在手,程序员抢票再不用跪求加速包...
- 疯狂的程序员阅读笔记
- webview的使用
- 2009年02月《安全天下事》、2009年02月《安全天下事之12月,辩证法之月》、《2008信息安全技术与产业大盘点》...
- 2022保密教育线上培训考试参考答案 02