java repaint 重画图形,学习笔记:WINDOWS的图形重绘基础
OnPaint()与OnDraw()的区别:
OnPaint是WM_PAINT的消息响应函数,在MFC的基类里OnPaint函数调用了OnDraw()函数。
OnPaint函数另外还调用了OnPrepareDC()函数。
如果在窗口子类覆盖了OnPaint函数,当MFC调用我们重写的OnPaint函数时,就调不到OnDraw()函数了,
除非我们去调用OnDraw()函数。
Invalidate函数族介绍:
函数: Invalidate(BOOL bErase = TRUE)
函数: InvalidateRect(CRect* rect,BOOL bErase = TRUE)
函数: InvalidateRgn(CRgn* rgn,BOOL bErase = TRUE)
将一个区域放入Update Region中。[Update
Region]是窗口的无效区域。[无效区域]是需要重绘的区域。
为何需要重绘呢?
第1类事件:当需要展现某窗口的“新的”区域时,就需要重绘。
当创建一个窗口时;当把窗口从另一个窗口的背后弹到前面时;当从图标化到最大化转变时;
当滚动式的窗口,发生滚动事件时;当把遮挡在前面的窗口一点一点拖开,
让被遮挡的窗口一点一点的露出时
就需要重绘。这些动作都是由WINDOWS系统管理的,系统会很肯定的认为,在上述事件发生时,必须重绘。
注:如果把被遮挡的窗口,一点一点的遮盖住,就不需要重绘。
第2类事件:当有业务数据改变的事件发生时。
窗口是用来显示业务数据的。比如我的窗口正在显示一个椭圆,后台将业务数据变成
了三角形,我需要显示这个三角形,这时就需要重绘了。对于第2类事件,
WINDOWS不可能感知到你需要重绘。
例如:我有一个变量 int m_shape=1; 1代表椭圆,2代表三角形。
我需要让窗口的图形显示m_shape代表的形状
当我把m_shape的值由1变成2时,WINDOWS根本不知道我需要重绘一个三角形。
对于第1类事件,WINDOWS会自动发出WM_PAINT消息,窗口的对应处理函数OnPaint()就会被调用。
程序员不必关心“在何时”和“在何地”重绘。对于第2类事件,程序员必须通知WINDOWS,在何地重绘。
至于“何时”重绘,WINDOWS会挑选一个合适的时机。
Invalidate函数族同第2类事件有关。通过调用Invalidate函数族,通知windows系统,
我有一些窗口区域需要重绘。CWnd::Invalidate()是说整个窗口都需要重绘。
CWnd::InvalidateRect()是说窗口的某个矩形区域需要
重绘。CWnd::InvalidateRgn是说窗口的某个不规则区域需要重绘。
“不规则区域”可以是任意多边形,椭圆形,当然也包括矩形。
用伪代码说明上述三个函数的等价关系。
CRgn rgn;
rgn.CreateRectRgn(...);
CWnd::InvalidateRgn(&rgn,...);
等价于
CRect rect;
CWnd::InvalidateRect(&rect,...);
CRect rect;
GetClientRect(&rect);
CWnd::InvalidateRect(&rect,...);
等价于
CWnd::Invalidate(...);
Invalidate函数族中,都有一个bErase参数。此参数的含义:bErase=TRUE擦除背景,
bErase=FALSE不擦除背景
何为背景:想象窗口就是小朋友的画纸。当你把这张画纸给另一个小朋友画画时,
前一个小朋友画的东西就是
“背景”。一般我们不希望两个小朋友画的东西夹杂在一起。我们就需要擦除前一个小朋友画的“背景”。
用什么擦除背景呢?WINDOWS允许我们设置“背景刷”,就是用某种颜色的刷子把整个画纸涂抹一遍,
有点像刷白墙。
Invalidate函数族的调用不会立刻引发窗口重绘。Invalidate函数族只是累积和标记需要重绘的区域。
下一次"WM_PAINT message
occurs"时(MSDN语),一次性处理累积和标记的所有需要重绘的区域。显然从
Invalidate调用,到实际的重绘动作是异步调用的。人类视觉有延迟现象,一秒连续播放24帧就可以认为是
“动画”了,所以上述重绘方式人类是察觉不出异样的。假设每次Invalidate都同步的引发重绘OnPaint,有两个不良后果:一是程序效率太差,二是可能让人察觉出闪烁感。
那么何时下一次"WM_PAINT message occurs"呢?
当应用的消息队列没有其他消息时,并且窗口的[Update Region]不为空时,
系统就会自动产生WM_PAINT消息。
例子:演示“失效区域”是如何起作用的。
//每次重绘,会交替展现两个不同的椭圆形。
void XXX::OnPaint()
{
CPaintDC dc(this);
static
int x=0;
if
(x==0){
dc.Ellipse (0, 0, 100, 200);
//横向的椭圆形
x=1;
}
else{
dc.Ellipse (0, 0, 200, 100);
//竖向的椭圆形
x=0;
}
}
某CButton中,OnBnClicked伪代码:
CRect rect;
XXX->GetClientRect(&rect);
rect.bottom = rect.bottom/2;
XXX->InvalidateRect(&rect,true);
//擦除背景
即使我擦除了背景,仍旧能看到前一个椭圆。因为我设定的“非法区域”只是rect的上半部分。
CRect rect;
XXX->GetClientRect(&rect);
XXX->InvalidateRect(&rect,true);
//擦除背景
可以正常的展现,能交替展现两个不同的椭圆形。
Validate函数族:
作用同Invalidate函数族相反,将一个区域从[Update Region]排除,这样就不会被重绘。
当然了,Validate要在下一次"WM_PAINT message occurs"之前的调用才能起作用。
如果发生了第1类事件,会造成大面积的区域变成“需重绘区域”,Validate设定的“不需重绘区域”
又会变成“需重绘区域了”。
UpdateWindow函数:
UpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息。
UpdateWindow可以绕开应用程序消息循环,直接发送WM_PAINT消息给窗口。
RedrawWindows函数:
可以简单理解为Invlidate + UpdateWindow,但是功能更强大一些。
SetRedraw函数:
可以阻止窗口重绘。是解决窗口闪烁的一个办法
MSDN的一个例子:
m_List.SetRedraw(FALSE); //暂时阻止窗口m_List重绘
...//大规模对m_List改头换面
m_List.SetRedraw(TRUE);
//解除阻止窗口m_List重绘
m_List.Invalidate();
m_List.UpdateWindow(); //触发WM_PAINT消息
SetRedraw函数好像是戏台的前幕,后面切换场景时,先遮挡一下。
<>介绍了图形密集型程序“闪”的原因。
主要技术为:1 选用黑色背景或者背景同前景相近的颜色,作为背景刷。
2 双缓冲技术,就是先在内存设备DC里准备好需要显示的内容,然后拷贝到屏幕设备DC
3 剪裁区域的合理利用。
java repaint 重画图形,学习笔记:WINDOWS的图形重绘基础相关推荐
- 重拾JavaSE学习笔记
重拾JavaSE学习笔记 1.常用DOS命令 2.了解Java 2.1 .java特性 2.2.JDK .JRE.JVM 2.3.java的加载和执行 3.开发环境搭建 3.1.安装jdk 3.2.配 ...
- Java开发面试高频考点学习笔记(每日更新)
Java开发面试高频考点学习笔记(每日更新) 1.深拷贝和浅拷贝 2.接口和抽象类的区别 3.java的内存是怎么分配的 4.java中的泛型是什么?类型擦除是什么? 5.Java中的反射是什么 6. ...
- VC学习笔记:文本图形
VC学习笔记:文本图形 SkySeraph OCT.30th 2010 HQU Email-zgzhaobo@gmail.com QQ-452728574 Latest Modified Dat ...
- 杨晓峰-java核心技术36讲(学习笔记)- 第1讲 | 谈谈你对Java平台的理解?
杨晓峰-java核心技术36讲(学习笔记) 接下来我会分享杨晓峰-java核心技术36讲的学习笔记,内容较多,补充了其中一些牛人评论,相对详细(仅供个人学习记录整理,希望大家支持正版:https:// ...
- Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- 《Java并发编程实践》学习笔记之一:基础知识
<Java并发编程实践>学习笔记之一:基础知识 1.程序与进程 1.1 程序与进程的概念 (1)程序:一组有序的静态指令,是一种静态概念: (2)进程:是一种活动,它是由一个动作序列组成 ...
- Java程序猿的JavaScript学习笔记(汇总文件夹)
最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...
- 拉勾网《32个Java面试必考点》学习笔记之二------操作系统与网络知识
本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...
- 拉勾网《32个Java面试必考点》学习笔记之一------Java职业发展路径
本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...
- Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
最新文章
- VS2017 Pro未能找到路径“……\bin\roslyn\csc.exe”的解决方案
- 关联查询的resultMap写法示例
- DeepLearnign:windows tensorflow-cmake编译
- 华为鸿蒙harmonyos-面向全场,华为正式官宣鸿蒙手机版相约6月2日,EMUI官博更名为HarmonyOS...
- solrCloud搭建
- mysql点击计数器_MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能...
- 查看 Proxy 的 $ProxyX.class文件
- 书籍:Python游戏开发 Game Development Using Python - 2019.pdf
- Linux-文件和目录操作命令
- 第二个案例实操——创建Bean类
- 送给程序员们的经典电子书大礼包
- 昆仑通态如何连接sqlserver数据库_[其他]:MCGS与其他组态软件及ERP软件协同应用...
- BP神经网络做数据预测
- 为什么高斯滤波器被广泛用于图像处理?
- javaee图书管理系统mysql_基于Java+Jsp+Servlet+Mysql的图书馆管理系统
- php微信授权登录sdk,微信授权登录如何使用?总结微信授权登录实例用法
- CSDN如何修改用户名(CSDN ID)、用户昵称以及自定义博客域名等
- VBA 禁止在某个sheet中使用键盘Delete键
- 文本行高——line-height属性
- Android视频直播源码开发直播平台、点播播放器哪家强?
热门文章
- AI落地谁最强?AI Top 30+案例评选等你来秀
- Storm精华问答 | storm与Hadoop有什么区别?
- 企业微信_Windows版本调试
- docker gitlab-ce
- 解决Linux docker中的mysql区分大小写问题
- RabbitMQ管控台操作手册
- cnpm不是内部或外部命令 cnpm: command not found 解决方案 cnpm
- Flowable BPMN 用户手册 (v 6.5.0-SNAPSHOT)
- mybatis resultMap type属性问题 ( xx.xx.PO cannot be cast to xx.xx.BO)
- apache禁止多目录运行php文件下载,Nginx Apache下如何禁止指定目录运行PHP脚本