1)当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再发送WM_PAINT消息。

如果处理WM_ERASEBKGND消息时返回FALSE,BeginPaint标记pt.fErase 为TRUE,如果处理WM_ERASEBKGND时返回TRUE,BeginPaint标记pt.fErase为FALSE。

2)当WM_PAINT由InvalidateRect产生时,先发送WM_PAINT消息(异步),如果InvalidateRect的bErase为TRUE,BeginPaint检查到更新区域需要删除背景,向窗口发送一个WM_ERASEBKGND消息,如果处理WM_ERASEBKGND消息时返回FALSE,BeginPaint标记pt.fErase 为TRUE,如果处理WM_ERASEBKGND时返回TRUE,BeginPaint标记pt.fErase为FALSE。

如果pt.fErase标记为TRUE,指示应用程序应该处理背景,但是应用程序不一定需要处理,pt.fErase只是作为一个标记。

补充:DefWindowProc(hWnd, message, wParam, lParam)处理WM_ERASEBKGND消息时默认用下面的画刷清除背景
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

WM_ERASEBKGND返回TRUE和返回FALSE是一个规范,一般情况下没有什么区别,但是如果什么时候用到了,会根据函数返回值判断后续处理。因此最好按照要求返回数据。

最后再提供一些测试代码,让大家更好的理解上面的内容。
// WM_ERASEBKGNDTest.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "WM_ERASEBKGNDTest.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WM_ERASEBKGNDTEST, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WM_ERASEBKGNDTEST));

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}

//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WM_ERASEBKGNDTEST));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
// wcex.hbrBackground = NULL;
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WM_ERASEBKGNDTEST);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_LBUTTONDOWN:
RECT rect;
GetClientRect(hWnd, &rect);
InvalidateRect(hWnd, &rect, TRUE);
MessageBeep(2);
break;

//case WM_ERASEBKGND:
// OutputDebugString(_T("Enter WM_ERASEBKGND\n"));
// return 1;
// break;

case WM_PAINT:
OutputDebugString(_T("Enter WM_PAINT\n"));
hdc = BeginPaint(hWnd, &ps);

if (ps.fErase == TRUE)
OutputDebugString(_T("ps.fErase == TRUE\n\n"));
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
if (WM_ERASEBKGND == message)
OutputDebugString(_T("Enter WM_ERASEBKGND\n"));
return DefWindowProc(hWnd, message, wParam, lParam);
}

// DefWindowProc(hWnd, message, wParam, lParam);
return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

http://www.articleswriting.net/article/3946748807/

WM_PAINT与WM_ERASEBKGND(用户操作和API这两种情况产生消息的顺序有所不同)的更多相关文章

  1. Jmix 中 REST API 的两种实现

    你知道吗,在 Jmix 中,REST API 有两种实现方式! 很多应用是采取前后端分离的方式进行开发.这种模式下,对前端的选择相对灵活,可以根据团队的擅长技能选择流行的 Angular/React/ ...

  2. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  3. [转载]Java操作Excel文件的两种方案

    微软在桌面系统上的成功,令我们不得不大量使用它的办公产品,如:Word,Excel.时至今日,它的源代码仍然不公开已封锁了我们的进一步应用和开发.在我们实际开发企业办公系统的过程中,常常有客户这样子要 ...

  4. redis使用bit做只有两种情况的“状态“统计(如是否在线的用户统计)

    1 记录在线用户数(活跃用户)? 比如redis中键a的value数据的二进制码是 0110 0110 0001 它总共有12位,在redis的位操作中,二进制中的第几位称为offset. 我们可以这 ...

  5. 获取用户当前位置信息的两种方法——H5、微信

    在之前的 调用百度地图API的总结 中获取当前位置信息我用的是 H5 ,其实微信也提供了获取用户地理位置的方法,现将这两种方法都贴出来,看情况选择使用. 一.H5 获取当前地理位置得到经纬度 // H ...

  6. java操作excel常用的两种方式

    Excel是我们平时工作中比较常用的用于存储二维表数据的,JAVA也可以直接对Excel进行操作,在这篇博客中将为大家介绍两种操作Excel的方式,分别为:jxl和poi. 对于两者的区别网上有测试如 ...

  7. linux中添加一个用户到指定用户组的两种方式,修改一个用户到指定用户组的一种方式

    添加一个用户到指定用户组: gpasswd –a 用户名 组名usermod –G 组名 用户名 //第一种:gpasswd –a 用户名 组名 [root@localhost ~]# id user ...

  8. Spring的核心api和两种实例化方式

    一.spring的核心api Spring有如下的核心api BeanFactory :这是一个工厂,用于生成任意bean.采取延迟加载,第一次getBean时才会初始化Bean Applicatio ...

  9. WM_PAINT产生原因有2种(用户操作和API)——WM_PAINT和WM_ERASEBKGND产生时的先后顺序不一定(四段讨论)

    1. 当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再 ...

随机推荐

  1. sed学习笔记整理

    1.sed简介 sed (Stream Editor)是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处 ...

  2. (Problem 16)Power digit sum

    215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. What is the sum of the digits of th ...

  3. grid.Column INT 所对应的文本

    grid.Column("RoleId", "角色名称", (p) => { var role = string.Empty; if (p.RoleId ...

  4. JavaScript 、ECMAScript、commonJS 发展历史 与标准化发展

    本文介绍下JavaScript和 ECMAScript的诞生及发展历史,以及标准化过程. 一.JavaScript诞生 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版. ...

  5. Codeforces Round #312 (Div. 2)

    好吧,再一次被水题虐了. A. Lala Land and Apple Trees 敲码小技巧:故意添加两个苹果树(-1000000000, 0)和(1000000000, 0)(前者是位置,后者是价 ...

  6. Java For循环效率试验

    非常奇怪的结果! ..! 测试方法如以下 public class Main { public static void main(String[] args){ long ti = System.cu ...

  7. VS2013配置opencv3.0.0 (win8.1)

    今天下载了最新版本的opencv3.0.0,之前一直是opencv2.4.8 点击.exe文件,我将解压后的文件夹放在D:\盘,取名opencv30,D:\opencv30 添加环境变量:D:\ope ...

  8. Python3 正则表达式特殊符号及用法(详细列表) http://bbs.fishc.com/thread-57691-1-1.html (出处: 鱼C论坛)

    http://bbs.fishc.com/thread-57691-1-1.html 留待查询用

  9. JVM --需要知道的一些术语

    1. Java堆中各代分布: Young:主要是用来存放新生的对象. Old:主要存放应用程序中生命周期长的内存对象. Permanent:是指内存的永久保存区域,主要存放Class和Meta的信息, ...

  10. (step6.1.5)hdu 1233(还是畅通工程——最小生成树)

    题目大意:输入一个整数n,表示有n个村庄,在接下来的n*(n-1)/2中,每行有3个整数beigin.end.weight,分别表示路的起始村庄,结束村庄和村庄之间的距离. 求索要修的路的最短距离 解 ...