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的图形重绘基础相关推荐

  1. 重拾JavaSE学习笔记

    重拾JavaSE学习笔记 1.常用DOS命令 2.了解Java 2.1 .java特性 2.2.JDK .JRE.JVM 2.3.java的加载和执行 3.开发环境搭建 3.1.安装jdk 3.2.配 ...

  2. Java开发面试高频考点学习笔记(每日更新)

    Java开发面试高频考点学习笔记(每日更新) 1.深拷贝和浅拷贝 2.接口和抽象类的区别 3.java的内存是怎么分配的 4.java中的泛型是什么?类型擦除是什么? 5.Java中的反射是什么 6. ...

  3. VC学习笔记:文本图形

    VC学习笔记:文本图形  SkySeraph OCT.30th 2010  HQU Email-zgzhaobo@gmail.com  QQ-452728574 Latest Modified Dat ...

  4. 杨晓峰-java核心技术36讲(学习笔记)- 第1讲 | 谈谈你对Java平台的理解?

    杨晓峰-java核心技术36讲(学习笔记) 接下来我会分享杨晓峰-java核心技术36讲的学习笔记,内容较多,补充了其中一些牛人评论,相对详细(仅供个人学习记录整理,希望大家支持正版:https:// ...

  5. Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  6. 《Java并发编程实践》学习笔记之一:基础知识

    <Java并发编程实践>学习笔记之一:基础知识 1.程序与进程 1.1 程序与进程的概念 (1)程序:一组有序的静态指令,是一种静态概念:  (2)进程:是一种活动,它是由一个动作序列组成 ...

  7. Java程序猿的JavaScript学习笔记(汇总文件夹)

    最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...

  8. 拉勾网《32个Java面试必考点》学习笔记之二------操作系统与网络知识

    本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...

  9. 拉勾网《32个Java面试必考点》学习笔记之一------Java职业发展路径

    本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...

  10. Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

最新文章

  1. VS2017 Pro未能找到路径“……\bin\roslyn\csc.exe”的解决方案
  2. 关联查询的resultMap写法示例
  3. DeepLearnign:windows tensorflow-cmake编译
  4. 华为鸿蒙harmonyos-面向全场,华为正式官宣鸿蒙手机版相约6月2日,EMUI官博更名为HarmonyOS...
  5. solrCloud搭建
  6. mysql点击计数器_MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能...
  7. 查看 Proxy 的 $ProxyX.class文件
  8. 书籍:Python游戏开发 Game Development Using Python - 2019.pdf
  9. Linux-文件和目录操作命令
  10. 第二个案例实操——创建Bean类
  11. 送给程序员们的经典电子书大礼包
  12. 昆仑通态如何连接sqlserver数据库_[其他]:MCGS与其他组态软件及ERP软件协同应用...
  13. BP神经网络做数据预测
  14. 为什么高斯滤波器被广泛用于图像处理?
  15. javaee图书管理系统mysql_基于Java+Jsp+Servlet+Mysql的图书馆管理系统
  16. php微信授权登录sdk,微信授权登录如何使用?总结微信授权登录实例用法
  17. CSDN如何修改用户名(CSDN ID)、用户昵称以及自定义博客域名等
  18. VBA 禁止在某个sheet中使用键盘Delete键
  19. 文本行高——line-height属性
  20. Android视频直播源码开发直播平台、点播播放器哪家强?

热门文章

  1. AI落地谁最强?AI Top 30+案例评选等你来秀
  2. Storm精华问答 | storm与Hadoop有什么区别?
  3. 企业微信_Windows版本调试
  4. docker gitlab-ce
  5. 解决Linux docker中的mysql区分大小写问题
  6. RabbitMQ管控台操作手册
  7. cnpm不是内部或外部命令 cnpm: command not found 解决方案 cnpm
  8. Flowable BPMN 用户手册 (v 6.5.0-SNAPSHOT)
  9. mybatis resultMap type属性问题 ( xx.xx.PO cannot be cast to xx.xx.BO)
  10. apache禁止多目录运行php文件下载,Nginx Apache下如何禁止指定目录运行PHP脚本