在OnPaint中必须调用一次BeginPaint和EndPaint,且也只能调用一次

2024-06-08 03:08

本文主要是介绍在OnPaint中必须调用一次BeginPaint和EndPaint,且也只能调用一次,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于对话框的程序(mfc默认生成),重载OnEraseBkgnd函数,其它不动,若在OnPaint函数中不调用其基类的OnPaint函数,即注释掉CDialog::OnPaint();,代码如下:

[cpp] view plaincopyprint?

1. void CDDDDlg::OnPaint()  

2. {  

3.     if (IsIconic())  

4.     {  

5.         CPaintDC dc(this); // device context for painting   

6.   

7.         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);  

8.   

9.         // Center icon in client rectangle   

10.         int cxIcon = GetSystemMetrics(SM_CXICON);  

11.         int cyIcon = GetSystemMetrics(SM_CYICON);  

12.         CRect rect;  

13.         GetClientRect(&rect);  

14.         int x = (rect.Width() - cxIcon + 1) / 2;  

15.         int y = (rect.Height() - cyIcon + 1) / 2;  

16.   

17.         // Draw the icon   

18.         dc.DrawIcon(x, y, m_hIcon);  

19.     }  

20.     else  

21.     {  

22.         //CDialog::OnPaint();   

23.     }  

24. }  


 则执行后界面没有问题,如下图:

但是,如果将此界面隐藏后再显示,则上面的控件都不能显示了,如下图:

 

跟踪程序会发现,第一次生成界面时候,进入过OnCtlColor函数(TRACE("OnCtlColor\n");语句输出),

当隐藏界面再显示后,就再也没进过OnCtlColor函数。当然看不见原先界面的控件了,因为根本没有重绘出来。原因见下篇

 

A:在OnPaint中注释此句CDialog::OnPaint();为什么会不停地调用OnPaint函数呢(不断执行TRACE("OnPaint\n");语句)?

 

Q:如果自己的OnPaint代码什么也没做的话(至少没有声明过CPaintDC类型的变量),还必须调用一下CDialog::OnPaint,否则BeginPaintEndPaint就没有办法被调用了。
总之,在响应WM_PAINT消息的时候,必须调用一遍BeginPaintEndPaint。调用的方法有三种:
1、声明一个CPaintDC类型的变量(即使你什么也不画),CPaintDC的构造函数就是调用BeginPaint,析构函数就是调用EndPaint
2、调用基类的OnPaint(实际上就是调用APIDefWindowProc,它会自动调用BeginPaintEndPaint)。
3、自己直接调用BeginPaintEndPaint
上述三种方法,必须选择其一,而且也只能选择其一(因为在一个WM_PAINT消息内不能调用两次BeginPaintEndPaint)。

 

正如我猜想的,因为你调用了CDialog::OnPaint();
你把这句注释掉就可以了。
所以说凡事总有因果,CDialog::OnPaint()调用默认的窗口过程来绘制,也会调用BeginPaint/EndPaint()。而这两个函数的作用,是获取DC、剪裁区域和从消息队列中移走WM_PAINT消息(因此,如果不用上述三种方法的一种调用一遍BeginPaintEndPaint的话,WM_PAINT消息就不会从消息队列里面移走,系统就会不停的发送WM_PAINT,这就是问题中所提到的不停的调用OnPaint函数的原因了)。这两个函数,必须在WM_PAINT消息中调用,而且只能调用一次!

 

这篇关于在OnPaint中必须调用一次BeginPaint和EndPaint,且也只能调用一次的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1041058

相关文章

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef‘ of undefined“

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef’ of undefined” 最近用vue做的一个界面,引入了一个子组件,在父组件中调用子组件的方法时,报错提示: [Vue warn]: Error in v-on handler: “TypeError: Cannot read property ‘methods

(function() {})();只执行一次

测试例子: var xx = (function() {     (function() { alert(9) })(); alert(10)     return "yyyy";  })(); 调用: alert(xx); 在调用的时候,你会发现只弹出"yyyy"信息,并不见弹出"10"的信息!这也就是说,这个匿名函数只在立即调用的时候执行一次,这时它已经赋予了给xx变量,也就是只是

【微服务】Ribbon(负载均衡,服务调用)+ OpenFeign(服务发现,远程调用)【详解】

文章目录 1.Ribbon(负载均衡,服务调用)1.1问题引出1.2 Ribbon负载均衡1.3 RestTemplate整合Ribbon1.4 指定Ribbon负载均衡策略1.4.1 配置文件1.4.2 配置类1.4.3 定义Ribbon客户端配置1.4.4 自定义负载均衡策略 2.OpenFeign面向接口的服务调用(服务发现,远程调用)2.1 OpenFeign的使用2.1 .1创建

BeginPaint EndPaint 与GetDC ReleaseDC的区别

1.    绘图一般在WM_PAINT消息里面绘图, 一般用BeginPaint( HWND hwnd, LPPAINTSTRUCT lpPaint) 与BOOL EndPaint(   HWND hWnd,     CONST PAINTSTRUCT *lpPaint)   <1> BeginPaint自动设置裁剪区域,把不更新的区域设置到更新区域外面,  此消息只绘制无效区域,更

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位 一、背景二、定位问题三、解决方法 一、背景 flume系列之:定位flume没有关闭某个时间点生成的tmp文件的原因,并制定解决方案在博主上面这篇文章的基础上,在机器内存、cpu资源、flume agent资源都足够的情况下,flume agent又出现了tmp文件无法关闭的情况 二、

类和对象的定义和调用演示(C++)

我习惯把类的定义放在头文件中 Student.h #define _CRT_SECURE_NO_WARNINGS#include <string>using namespace std;class student{public:char m_name[25];int m_age;int m_score;char* get_name(){return m_name;}int set_name