[Win32/ATL]_[初级]_[处理WM_PAINT消息注意事项]

场景

  1. 在开发Win32/WTL程序时,遇到了使用CFolderDialog(atldlgs.h)打不开目录选择对话框的情况。具体表现是执行了窗口的DoModal,却没有窗口弹出来。 可以确定执行操作是在主线程,并不是工作线程。调试时暂停看堆栈,知道到DoModal方法里的SHBrowseForFolder就会停止,没有继续执行下去。主窗口也是卡住,但是不调用DoModal前主窗口不会卡的。偶尔情况下还是能打开CFolderDialog的,但是大部分测试都不行。什么情况?

说明

  1. CFolderDialogDoModal实现,SHBrowseForFolder<2>是打开一个选择文件的对话框。在之前的文章和课程说过,模态对话框在关闭前DoModal不会返回。主线程开启一个新的消息循环来处理模态对话框的消息。 当模态对话框没弹出来时,主界面也没有消息循环处理,自然不响应任何鼠标消息,所以看起来就是卡住了。
INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
{if(m_bi.hwndOwner == NULL)   // set only if not specified beforem_bi.hwndOwner = hWndParent;// Clear out any previous resultsm_szFolderPath[0] = 0;m_szFolderDisplayName[0] = 0;::CoTaskMemFree(m_pidlSelected);INT_PTR nRet = IDCANCEL;m_pidlSelected = ::SHBrowseForFolder(&m_bi);if(m_pidlSelected != NULL){nRet = IDOK;// If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path.// Otherwise, the caller must handle the ID-list directly.if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0){if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE)nRet = IDCANCEL;}}return nRet;
}
  1. 暂停看堆栈时,发现某个界面的OnPaint方法和SHBrowseForFolder竟然在同一个线程执行,正常情况下是不可能。看OnPaint方法,在方法内打断点,发现它一直循环执行。正常情况下只有绘制区域变更时,比如调用InvalidateRect或窗口移动时才会调用一次。所以这个OnPaint方法循环调用是有问题。 这个方法和其他窗口的绘图方法不一样的地方就是没有调用CPaintDC dc(m_hWnd);,只调用了Gdiplus::Graphics g(dc);来绘制背景。 增加CPaintDC dc(m_hWnd);后问题解决。

图1

在这里插入图片描述

  1. 看下CPaintDC的构造构造函数实现,发现调用了BeginPaint[1]。 在Win32应用程序中,处理WM_PAINT消息通常涉及调用BeginPaint来获取绘图相关的设备上下文。BeginPaint会标记缓冲区为有效,并清除重绘区域,这样在绘制时不会覆盖其他的绘图。
CPaintDC(HWND hWnd)
{ATLASSERT(::IsWindow(hWnd));m_hWnd = hWnd;m_hDC = ::BeginPaint(hWnd, &m_ps);
}~CPaintDC()
{ATLASSERT(m_hDC != NULL);ATLASSERT(::IsWindow(m_hWnd));::EndPaint(m_hWnd, &m_ps);Detach();
}
  1. 如果不调用BeginPaint,那么从InvalidateRect InvalidateRgn设置的更新区域就不会被标记,之后WM_PAINT消息就会被反复调用造成死循环。

例子

  1. 这里实现了一个错误处理WM_PAINT消息,只使用Gdiplus绘制文字的例子。

view.h

// View.h : interface of the CView class
//
/#pragma once#include "atlcrack.h"
#include <gdiplus.h>class CView : public CWindowImpl<CView>
{
public:DECLARE_WND_CLASS(NULL)BOOL PreTranslateMessage(MSG* pMsg);BEGIN_MSG_MAP_EX(CView)MESSAGE_HANDLER(WM_PAINT, OnPaint)MSG_WM_CREATE(OnCreate)END_MSG_MAP()// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);int OnCreate(LPCREATESTRUCT lpCreateStruct);protected:Gdiplus::Font* font_ = nullptr;
};

view.cpp

// View.cpp : implementation of the CView class
//
/#include "stdafx.h"
#include "resource.h"#include <gdiplus.h>
#include "View.h"BOOL CView::PreTranslateMessage(MSG* pMsg)
{pMsg;return FALSE;
}int CView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{Gdiplus::FontFamily fontFamily(L"Arial");font_ = new Gdiplus::Font(&fontFamily,16,(false)?Gdiplus::FontStyleBold:Gdiplus::FontStyleRegular,Gdiplus::UnitPixel);return 0;
}LRESULT CView::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{//CPaintDC dc(m_hWnd);Gdiplus::Graphics g(m_hWnd);//Gdiplus::Graphics g(dc);static auto kMessage = L"OnPaint\n";Gdiplus::SolidBrush brush(Gdiplus::Color::Black);g.DrawString(kMessage, wcslen(L"OnPaint\n"), font_, Gdiplus::PointF(0, 0), nullptr, &brush);OutputDebugString(L"OnPaint\n");//TODO: Add your drawing code herebHandled = true;return 0;
}
LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{CFolderDialog ff(NULL, NULL, BIF_RETURNONLYFSDIRS | BIF_USENEWUI);if (IDOK == ff.DoModal()) {}return 0;
}

项目

下载地址: https://download.csdn.net/download/infoworld/90213937

在这里插入图片描述

参考

  1. beginPaint 函数

  2. SHBrowseForFolderW 函数 shlobj_core.h

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/499176.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为配置 之 RIP

简介&#xff1a; RIP&#xff08;路由信息协议&#xff09;是一种广泛使用的内部网关协议&#xff0c;基于距离向量算法来决定路径。它通过向全网广播路由控制信息来动态交换网络拓扑信息&#xff0c;从而计算出最佳路由路径。RIP易于配置和理解&#xff0c;非常适用于小型网络…

RCE-PLUS (学习记录)

源码 <?php error_reporting(0); highlight_file(__FILE__); function strCheck($cmd) {if(!preg_match("/\;|\&|\\$|\x09|\x26|more|less|head|sort|tail|sed|cut|awk|strings|od|php|ping|flag/i", $cmd)){return($cmd);}else{die("i hate this"…

Unity Mesh生成Cube

1. 配置一个Cube的每个面的数据 一共是6个面&#xff0c;每个面包含的数据包括4个顶点的相对顶点坐标&#xff08;Cube的中心为原点&#xff09;&#xff0c;法线方向&#xff0c;UV坐标&#xff0c;顶点渲染顺序&#xff0c;以及这个面用到的材质&#xff0c;因为这里是Top&am…

【YOLO算法改进】ALSS-YOLO:无人机热红外图像|野生动物小目标检测

目录 论文信息 论文创新点 1.自适应轻量通道分割和洗牌&#xff08;ALSS&#xff09;模块 2.轻量坐标注意力&#xff08;LCA&#xff09;模块 3.单通道聚焦模块 4.FineSIOU损失函数 摘要 架构设计 轻量高效网络架构 - ALSS模块 LCA模块 单通道聚焦模块 损失函数优…

【亚马逊云】基于Amazon EC2实例部署 NextCloud 云网盘并使用 Docker-compose 搭建 ONLYOFFICE 企业在线办公应用软件

文章目录 1. 部署EC2实例2. 安装 Docker 服务3. 安装docker-compose4. 创建Docker-compose文件5. 创建nginx.conf文件6. 运行docker-compose命令开始部署7. 访问ONLYOFFICE插件8. 访问NextCloud云盘9. 下载并启用ONLYOFFICE插件10. 上传文件测试11. 所遇问题12. 参考链接 1. 部…

使用爬虫技术获取网页中的半结构化数据

目录 前言1. 半结构化数据与爬虫技术简介1.1 半结构化数据的定义与特性1.2 爬虫技术的基本原理 2. 爬取半结构化数据的实现过程2.1 明确目标与准备2.2 发送HTTP请求2.3 解析网页内容2.4 动态内容的处理2.5 数据存储与清洗 3. 技术挑战与应对策略3.1 处理反爬机制3.2 提高爬取效…

win10、win11-鼠标右键还原、暂停更新

系统优化 win 10jihuo win 11jihuo鼠标右键还原暂停更新 update 2024.12.28win 10 jihuo winx&#xff0c;打开powershell管理员&#xff0c;输入以下命令,选择1并等待 irm https://get.activated.win | iex参考&#xff1a;https://www.bilibili.com/video/BV1TN411M72J/?sp…

【蓝桥杯选拔赛真题87】python输出字符串 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python输出字符串 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python输出字符串 第十五届蓝桥杯青少年组python比赛选拔赛真题详细解析…

有什么AI辅助阅读文献工具推荐?

AI的发展速度非常快&#xff0c;在很多方面都已经可以提供货真价实的辅助能力。 比如AI辅助阅读方面&#xff0c;可以获取、分析和理解大量文献资料。这可以帮助我们快速浏览和理解PDF文件和其他文档&#xff0c;提高我们的工作效率和学习效率&#xff0c;达到降本增效。 作为…

各个Spring Cloud版本有何主要差异

Spring Cloud 的各个版本之间确实存在一些关键差异&#xff0c;这些差异主要体现在功能更新、性能优化、对新技术的支持以及对旧有技术的替代等方面。 1. Spring Cloud Dalston 这是 Spring Cloud 的一个早期版本&#xff0c;它提供了微服务架构所需的基本组件&#xff0c;如服…

【翻译】审慎对齐:推理使更安全的语言模型成为可能

原文&#xff1a;https://arxiv.org/abs/2412.16339 出自OpenAI 摘要 随着大规模语言模型对安全关键领域的影响越来越大&#xff0c;确保它们可靠地遵守定义良好的原则仍然是一个基本挑战。本文提出慎思校准&#xff0c;一种新的范式&#xff0c;直接教模型安全规范&#xff…

1、ELK的架构和安装

ELK简介 elk&#xff1a;elasticsearch logstash kibana&#xff0c;统一日志收集系统。 elasticsearch&#xff1a;分布式的全文索引引擎的非关系数据库&#xff0c;json格式&#xff0c;在elk中存储所有的日志信息&#xff0c;架构有主和从&#xff0c;最少需要2台。 …

使用连字符容易出错,尽量使用驼峰式的

在<Select>组件中&#xff0c;存在一个拼写错误。在option - value属性中&#xff0c;正确的写法应该是option - value&#xff08;使用连字符&#xff09;或者optionValue&#xff08;如果是按照Vue组件属性的驼峰命名法&#xff09;&#xff0c;这里写成了option - val…

CentOS7 解决ping:www.baidu.com 未知的名称或服务

CentOS7 解决ping&#xff1a;www.baidu.com“未知的名称或服务 在VM查看网络配置 查看虚拟网络编辑器 编辑网络配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33注意&#xff1a;不同机器的配置文件名可能不相同&#xff0c;通过 ip addr 命令查看 将 ONBOOT 从 no 改…

QT----------文件系统操作和文件读写

一、输入输出设备类 功能&#xff1a; Qt 提供了一系列的输入输出设备类&#xff0c;用于处理不同类型的 I/O 操作&#xff0c;如文件、网络等。 二、文件读写操作类 QFile 类&#xff1a; 提供了对文件的读写操作&#xff0c;可以打开、读取、写入和关闭文件。示例&#x…

Android14 CTS-R6和GTS-12-R2不能同时测试的解决方法

背景 Android14 CTS r6和GTS 12-r1之后&#xff0c;tf-console默认会带起OLC Server&#xff0c;看起来olc server可能是想适配ATS(android-test-station)&#xff0c;一种网页版可视化、可配置的跑XTS的方式。这种网页版ATS对测试人员是比较友好的&#xff0c;网页上简单配置下…

2024-12-29-sklearn学习(26)模型选择与评估-交叉验证:评估估算器的表现 今夜偏知春气暖,虫声新透绿窗纱。

文章目录 sklearn学习(26) 模型选择与评估-交叉验证&#xff1a;评估估算器的表现26.1 计算交叉验证的指标26.1.1 cross_validate 函数和多度量评估26.1.2 通过交叉验证获取预测 26.2 交叉验证迭代器26.2.1 交叉验证迭代器–循环遍历数据26.2.1.1 K 折26.2.1.2 重复 K-折交叉验…

免费容器镜像服务--统信容器镜像平台

原文链接&#xff1a;免费容器镜像服务--统信容器镜像平台 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于 免费容器镜像服务——统信容器镜像平台 的文章。统信容器镜像平台是由统信软件推出的免费容器镜像服务&#xff0c;遵循 OCI&#xff08;Open Containe…

Vue 3.0 中 template 多个根元素警告问题

在 Vue 2.0 中&#xff0c;template 只允许存在一个根元素&#xff0c;但是这种情况在 Vue 3.0 里发生了一些变化。 在 Vue 3.0 中开始支持 template 存在多个根元素了。但是因为 VSCode 中的一些插件没有及时更新&#xff0c;所以当你在 template 中写入多个根元素时&#xf…