WM_PAINT与WM_ERASEBKGND

原创 2007年09月13日 21:03:00

本文最新链接地址:http://lifepeak.net/it-jishu/wm_paint-wm_erasebkgnd.html

    

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

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


    当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;
}

关于WM_ERASEBKGND和WM_PAINT的深刻理解

一直以来,对于WM_PAINT和WM_ERASEBKGND消息不是很清楚,从书上和网上找了很多资料,大体上有以下几点说法: 1>WM_PAINT先产生,WM_ERASEBKGND后产生 2.WM_...
  • sdeeds
  • sdeeds
  • 2011年10月10日 15:59
  • 16214

WM_PAINT 和 WM_ERASEBKGND 消息的区别 .

先看看,如何获得HDC(设备句柄)   1.调用BeginPaint()。绘制范围是窗口的无效区域。通常是在WM_PAINT中调用。这个api获得HDC,在EndPaint()以后,会将窗口的无效...
  • lifu119
  • lifu119
  • 2011年11月29日 09:57
  • 917

深度分析WM_PAINT和WM_ERASEBKGND消息

做windows开发这么久了,一直以来对WM_PAINT和WM_ERASEBKGND消息总是感觉理解的不准确,每次要自绘一个窗口都因为知其然不知其所以然,偶然发现一篇文章,详细透彻地分了这个两个消息的...
  • analogous_love
  • analogous_love
  • 2015年11月25日 17:10
  • 763

WINCE MFC 自绘控件的WM_PAINT与WM_ERASEBKGND、WM_TIMER 问题总结

MFC的控件简直丑陋无比,因此往往会使用贴图的方式进行。于是自己也尝试开发一套UI控件。那么在把控件运用到APP的时候发现有刷新的问题。 一.WM_PAINT消息问题     一般情况我是认为通过...
  • lan120576664
  • lan120576664
  • 2016年05月18日 19:53
  • 704

WM_PAINT详解和WM_ERASEBKGND

WM_PAINT简介: WM_PAINT消息在Windows程序设计中是很重要的。当窗口显示区域的一部分显示内容或者全部变为“无效”,以致于必须“更新画面”时,将由这个消息通知程序。 WM_PAINT...
  • rankun1
  • rankun1
  • 2016年01月27日 22:29
  • 1411

sendmessage WM_PAINT 无效(6月19日)

今天意外发现替一哥们做的程序还有漏洞,点击弹出来的对话框的BUTTON时,发现主窗口(实际是VIEW啦)不自动重绘以产生相应图形。我就纳闷了,我明明已经给VIEW类发送WM_PAINT重绘消息了啊,怎...
  • Randyqiu
  • Randyqiu
  • 2009年06月29日 15:46
  • 3837

WM_ERASEBKGND与WM_PAINT

最近开发一个Wtl自绘界面程序。我在WM_ERASEBKGND消息中绘制背景图,在客户区域的右上角绘制控制按钮。最初对话框是不可改变大小的,后来由于需求需要支持拖拉改变对话框大小,相应的控制按钮的位置...
  • xbgprogrammer
  • xbgprogrammer
  • 2016年11月17日 18:10
  • 290

WM_PAINT与WM_ERASEBKGND补充

本文最新链接地址:http://lifepeak.net/it-jishu/wm_paint-wm_erasebkgnd.html 在做窗口界面优化的时候,正确的处理WM_PAINT和WM_ERASE...
  • World7th
  • World7th
  • 2007年12月21日 21:19
  • 4440

WM_PAINT与WM_ERASEBKGND

当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再发送W...
  • MaDashu
  • MaDashu
  • 2013年11月15日 13:42
  • 247

WM_PAINT 与 WM_ERASEBKGND

一直对这两个消息的关系
  • zxm342698145
  • zxm342698145
  • 2014年05月21日 19:37
  • 641
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:WM_PAINT与WM_ERASEBKGND
举报原因:
原因补充:

(最多只允许输入30个字)