C++ Invalidaterect()函数作用案例详解

函数原型:

BOOLInvalidateRect(
HWND hWnd, // handle of window withchanged update region 窗口句柄。
CONST RECT *lpRect, // address ofrectangle coordinates rect结构体的指针。
BOOL bErase // erase-background flag 是否要发送WM_ERASEBKGND消息从而擦除原来的背景
);

这个函数的作用是,使得Client的一个矩形区域变得无效,rect结构体可以自己编辑,也可以使用GetClientRcet()来填充(这里的矩形大小Client的大小),最主要的是第三个参数,第三个参数决定了是否发送WM_ERASEBKGND消息,从而决定了是否擦除Client原有的图形。当然InvalidateRect发送WM_PAINT的形式是一种POST形式(即发送到程序消息队列),而不是像SendMessage一样直接让操作系统带着消息,调用WndProc。

当然如果想像SendMessage一样的。可以在后面接着使用UpdateWindow()直接绕过程序消息队列直接发送消息到WndProc函数,来重绘窗口。

分析一下下面的程序会更加的清晰:

    case WM_RBUTTONDOWN:

        hdc = GetDC(hwnd);
        GetClientRect(hwnd, &rect);
        DrawText(hdc, TEXT("右键键被单机咯!"), 13, &rect, DT_VCENTER | DT_SINGLELINE);
        ReleaseDC(hwnd, hdc);
        InvalidateRect(hwnd, NULL, true);
        //UpdateWindow(hwnd);
        Sleep(1000);
        return 0;
    case WM_LBUTTONDOWN:
        hdc = GetDC(hwnd);
        GetClientRect(hwnd, &rect);
        DrawText(hdc, TEXT("左键被单机咯!"), 13, &rect, DT_CENTER | DT_SINGLELINE);
        ReleaseDC(hwnd, hdc);
        return 0;

这里为了能看到效果我使用了Sleep。在实际编程处理消息,不是在多线程时,这样的使用是十分愚蠢的,因为,消息循环的机制,如果你不快速的处理每一条消息。用户的体验将会受到很大的影响。比如,,无法操作,,这是最尴尬的。

1,这里如果UpdateWindow(hwnd)被注释掉的情况下,单机左键后,客户区屏幕打印出左键被单机咯,单机右键后打印出右键被单机咯。随后,调用了InvalidateRect()发送了WM_PAINT和WM_ERASEBKGND消息到消息队列,因为Invalidate第三个参数是true所以背景被重画,并且使rect的矩形范围失效。从而延迟1000ms后,处理WM_PAINT消息后,窗口上的左键…右键…..的字样都被清除。

2,如果UpdateWindow(hwnd) 没被注释掉。左键单机,右键单机,出现两条提示后,立即都消失(一般情况看不到右键点击的提示,而是直接擦除左键点击的提示的效果),为什么呢,因为UpdateWindow的作用,直接绕过队列,带到WndProc中去。所以直接重绘了。

3.如果InvalidateRect里面是false则结果将是没有任何效果。难道真的是没有效果吗。当然不是,实际上是有效果的。因为,这里InvalidateRect还是使得rect的区域失效了,只是不会擦除背景也就是原来打印在屏幕上的提示都不会被清除。而且还是发送了WM_PAINT消息,所以WM_PINT消息内的处理,会执行一次。

4.第三种情况,不就是使得区域无效,而且发送了WM_PAINT消息吗。实际上,就算不发送WM_PAINT消息,系统也会派送WM_PAINT消息。因为无效了。我又想到UpdateWindow不也是给WndPro带来了WM_PAINT消息吗?窗口不会重绘吗?答案是不会。因为窗口没有无效的区域,所以WM_PAINT内部的代码也没有执行。(为什么没有执行,原因是UpdateWindow内部检测了是否有无效区域,如果没有则不发送消息)。

到此这篇关于C++ Invalidaterect()函数作用案例详解的文章就介绍到这了,更多相关C++ Invalidaterect()函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • VSCODE调试RDKit内核的方法步骤(C++)

    目录 安装 RDKit 所需环境 配置 VSCode 使其能 Debug 配置 Intellisense 配置 CMake 新建调试文件进行调试 Anaconda 环境问题 参考资料 在研究 RDKit 的一些算法的时候,总希望能够"进入到代码中"看这些变量到底是什么,哪些代码块会被执行.可 RDKit 的编译比较复杂,如果是 Python 的部分,那么可以直接在 VSCode 中进行调试,记得在 launch 中设置 "justMyCode: false",详见该

  • C++实现控制台随机迷宫的示例代码

    我全程使用TCHAR系列函数,亲测可以不改动代码兼容Unicode/ANSI开发环境,功能正常.大概有100行代码是来自网络的,我也做了改动,侵权请联系删除. 这个代码不能算是完美,还是会有轻微的闪屏现象,懒得再加双缓存了,大家可以自行修改.这里用的是SetConsoleCursorPosition函数和cls刷新屏幕. 好了,上代码!VS2015编译通过无警告.其他版本应该也没问题 // C++ Maze main code // Copyright (c) 2020 szx0427 #inc

  • C++ random_shuffle()方法案例详解

    假设你需要指定范围内的随机数,传统的方法是使用ANSI C的函数random(),然后格式化结果以便结果是落在指定的范围内.但是,使用这个方法至少有两个缺点. 首先,做格式化时,结果常常是扭曲的,所以得不到正确的随机数(如某些数的出现频率要高于其它数) 其次,random()只支持整型数:不能用它来产生随机字符,浮点数,字符串或数据库中的记录. 对于以上的两个问题,C++中提供了更好的解决方法,那就是random_shuffle()算法.不要着急,下面我就会告诉你如何用这种算法来产生不同类型的随

  • 神奇的c/c++小游戏((提高你的编程兴趣)

    目录 神奇的c/c++ 神奇的c/c++ 以下代码在Dev,codeblocks,VC上都能运行 #include<stdio.h> #include<time.h> #include<stdlib.h> #include<conio.h> #include<windows.h> //下面Sleep()函数的头文件 #include<mmsystem.h> void menu() { printf(" ***********

  • C++中的STL中map用法详解(零基础入门)

    目录 一.什么是 map ? 二.map的定义 2.1 头文件 2.2 定义 2.3 方法 三.实例讲解 3.1 增加数据 3.2 删除数据 3.3 修改数据 3.4 查找数据 3.5 遍历元素 3.6 其它方法 四.总结 map 在编程中是经常使用的一个容器,本文来讲解一下 STL 中的 map,赶紧来看下吧! 一.什么是 map ? map 是具有唯一键值对的容器,通常使用红黑树实现. map 中的键值对是 key value 的形式,比如:每个身份证号对应一个人名(反过来不成立哦!),其中

  • C++ GetDlgItem用法案例详解

    GetDlgItem的用法小结 GetDlgItem用于获得指定控件ID的窗体指针,函数原型如下: HWND GetDlgItem( HWND hDlg, int nIDDlgItem ); CWnd* GetDlgItem(int nID) const; 它的使用说明中有这样一行字,**The returned pointer may be temporary and should not be stored for later use. **,那说明,它返回的指针有可能是有效的,有可能是无效

  • 最短时间学会基于C++实现DFS深度优先搜索

    目录 前言 1.迷宫找出口,区分dfs,bfs: 一.DFS经典放牌可能组合 二.leetcode 员工的重要性 三.leetcode 图像渲染 四.leetcode 被围绕的区域 五.岛屿数量 六. 小练习:岛屿的最大面积 总结 前言 同学们肯定或多或少的听到过别人提起过DFS,BFS,却一直都不太了解是什么,其实两个各为搜索算法,常见使用 深度优先搜索(DFS) 以及 广度优先搜索(BFS) ,今天我们就来讲讲什么是深度优先搜索,深度优先就是撞到了南墙才知道回头,才会往上一层返回. 1.迷宫

  • protobuf c++编程笔记

    目录 字段内容的定义 修饰符 字段类型 引用方式 不同字段的方法 1)optional修饰的基本类型: 2)optional修饰的对象类型: 3)repeated修饰的基本类型: 4)repeated修饰的对象类型: 序列化 反序列化 总结 字段内容的定义 //文件名:addressbook.proto syntax = "proto2";//proto版本 //.proto文件新增一个可选的package声明符,用来防止不同的消息类型有命名冲突. //包的声明符会根据使用语言的不同影

  • C++ Invalidaterect()函数作用案例详解

    函数原型: BOOLInvalidateRect( HWND hWnd, // handle of window withchanged update region 窗口句柄. CONST RECT *lpRect, // address ofrectangle coordinates rect结构体的指针. BOOL bErase // erase-background flag 是否要发送WM_ERASEBKGND消息从而擦除原来的背景 ); 这个函数的作用是,使得Client的一个矩形区域

  • C++ assert()函数用法案例详解

    1. 简介 assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行. 原型定义: #include <assert.h> void assert( int expression ); assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行.请看下面的程序清单badptr.c: #include <stdio.h> #incl

  • SQL IDENTITY_INSERT作用案例详解

    一般情况下,当数据表中,莫一列被设置成了标识列之后,是无法向标识列中手动的去插入标识列的显示值.但是,可以通过设置SET IDENTITY_INSERT属性来实现对标识列中显示值的手动插入. 写法: SET IDENTITY_INSERT 表名 ON :表示开启对标识列显示值插入模式,允许对标识列显示值进行手动插入数据. SET IDENTITY_INSERT 表名 OFF:表示关闭对标识列显示值的插入操作,标识列不允许手动插入显示值. 注意:IDENTITY_INSERT的开启ON和关闭OFF

  • C++ seekg函数用法案例详解

    C++ seekg函数用法详解 很多时候用户可能会这样操作,打开一个文件,处理其中的所有数据,然后将文件倒回到开头,再次对它进行处理,但是这可能有点不同.例如,用户可能会要求程序在数据库中搜索某种类型的所有记录,当这些记录被找到时,用户又可能希望在数据库中搜索其他类型的所有记录. 文件流类提供了许多不同的成员函数,可以用来在文件中移动.其中的一个方法如下: seekg(offset, place); 这个输入流类的成员函数的名字 seekg 由两部分组成.首先是 seek(寻找)到文件中的某个地

  • Java web.xml之contextConfigLocation作用案例详解

    在web.xml中通过contextConfigLocation配置spring,contextConfigLocation参数定义了要装入的 Spring 配置文件. 部署applicationContext.xml文件         如果不写任何参数配置,默认的是在/WEB-INF/applicationContext.xml        如果指定了要加载的文件,则会去加载相应的xml,而不会去加载/WEB-INF/下的applicationContext.xml.如果没有指定的话,默认

  • StretchBlt函数和BitBlt函数用法案例详解

    StretchBlt和BitBlt都用在双缓冲视图中,用来显示一幅图像 一.StretchBlt 函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩.也即是将内存中的位图拷贝到屏幕上,并且可以根据屏幕画图区的大小来进行伸缩,适应响应的屏幕(或图像控件) BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, in

  • SQLServer日期函数总结案例详解

    目录 一,日期的格式化 二,日期和时间的结构 三,日期操作 四. 日期函数 SQL Server发展至今,关于日期的格式的控制方法,有传统的方法,比如CONVERT(),也有比较便利的新方法,比如FORMAT():同样,关于日期的操作函数,也分为传统方法:DATEADD()等,也有便利的新方法:EOMonth()等. 一,日期的格式化 格式化是指把日期类型(Date).日期和时间类型转化为字符类型,通常使用CONVERT()和FORMAT()函数. 1,传统的CONVERT() SQL Serv

  • Python threading Local()函数用法案例详解

    目录 前言 local() 函数是什么? local()函数如何用? 1. 不做标记,不做隔离 2.使用local()函数加以控制 3. 模拟实现local()的功能,创建一个箱子 4. 简化代码操作,进一步模拟实现local()函数 总结 前言 当多线程访问同一个公共资源时,如果涉及到修改该公共资源的操作就可能会出现由于数据不同步导致的线程安全问题.一般情况下我们可以通过给公共资源加互斥锁的方式来处理该问题. 当然,除非必须将多线程使用的资源设置为公共资源的情况.如果一个资源不需要在多个线程之

  • C++ atoi()函数用法案例详解

    目录 1 功能 2 格式 3 注意事项 3.1 关于参数的注意事项 3.2 关于返回值的注意事项 3.3 判断转换是否成功 4 宽字符的转换 1 功能 atoi()函数将数字格式的字符串转换为整数类型.例如,将字符串"12345"转换成数字12345. 2 格式 该函数的格式为 int atoi(const char* str) 其中,参数str是要转换的字符串,返回值是转换后的整数. 3 注意事项 3.1 关于参数的注意事项 在"2 格式"中提到,atoi()函数

  • C++ 转换函数用法案例详解

    1.标准数据之间会进行隐式类型安全转换,规则如下:  在这里主要探讨c++中类类型与普通类型的转换: 1.类类型转换普通类型 class Fraction { public: Fraction(int num,int den=1); ~Fraction(); //转换函数 /* 转换函数语法规则: operator Type() { Type ret ; ........ return ret; } */ operator double() const { return (double)(m_N

随机推荐