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


    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是一个规范,一般情况下没有什么区别,但是如果什么时候用到了,会根据函数返回值判断后续处理。因此最好按照要求返回数据.

    http://note.sdo.com/u/432181446/NoteContent/pMF36~jDXzSFnM1rg001sf

    ------------------------------------------------------------------------------------------

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

    当WM_PAINT由InvalidateRect产生时,先发送WM_PAINT消息,OnPaint()这个执行内部向窗口发送了 WM_ERASEBKGND消息来刷新背景。在OnPaint()函数中会首先调用BeginPaint()函数,在BeginPaint 函数中会发送WM_ERASBKGND.
    OnEraseBkgnd函数内部不要使用 UpdateWindow MoveWindow SetWindowPos RedrawWindow等引起调用wm_paint的函数,如果在 OnEraseBkgnd 函数处理过程中 产生了需要刷新的无效区,导致系统产生wm_paint消息,这样就产生了死循环!

    要在程序中想要把背景色设置成其他颜色(不是默认的),那这个代码一般在WM_ERASEBKGND 的消息响应函数中执行,而当我们想在界面上画个图形之类的,一般在WM_PAINT的消息响应函数如OnPain中执行。凡事无绝对,就是你也可以把 背景的设置放在OnPain中绘制

    WM_ERASEBKGND如果返回非0,说明已经重画背景,如果返回0,程序将继续试图重画背景。

     
    http://qiusuoge.com/10860.html
    ------------------------------------------------------------------------------------------

    问题:Windows系统没有发出WM_ERASEBKGND消息
    根据MSDN的描述,当windows被最小化时,系统需要绘制icon。
    通常,系统会首先发送WM_ICONERASEBKGND给窗口,然后再发送WM_PAINTICON消息给窗口。MSDN又说,如果应用程序的WNDCLASS结构的hIcon成员如果为NULL,那么系统会发送WM_ERASEBKGND消息来替代
    WM_ICONERASEBKGND消息,然后再发送WM_PAINT消息。为此应用程序应该在自己的代码中,
    通过IsIconic()函数来判断当前是否application处于miminized状态。如果是,那么在
    其OnEraseBkGnd函数和OnPain函数中都应该根据其minimized状态来绘制图标背景和图标。当然,MFC程序会封装WNDCLASS结构,为此我们看不到RegisterClass函数。为此我通过
    GetClassInfo函数来获取WNDCLASS结构,结果发现hIcon域为NULL。根据MSDN的描述,在窗口minimized的情况下,系统应该会发出WM_ERASEBKGND消息,但是我通过
    打印TRACE信息发现,系统根本没有在minimized情况下发出WM_ERASEBKGND消息。另外,根据MSDN的描述,WM_ICONERASEBKGND消息仅仅在Windows NT 3.51 and earlier有效。请高手指点,谢谢!!

    The WM_ERASEBKGND message is sent when the window background must be erased (for example, when a window is resized). The message is sent to prepare an invalidated portion of a window for painting.
    -------------
    个人觉得最小化(IsIconic函数调用为TRUE),图标化了,就没有必要发送WM_ERASEBKBND消息来绘制窗口背景,可能是为了效率。

    刚刚搜索到一个老外的描述:他说IsIconic是win16和NT3.x以前的东西,现在已经可以不需要这个分支了。另外,在百度上看到这篇文章:觉得分析得有道理。当窗口最小化时,此时已经不需要绘制client area,为此不会发出WM_PAINT消息。实际上,仅仅当application client area有update region时,系统才会在message queue为空时,才会发出WM_PAINT消息。而当application接收到WM_PAINT消息时,会首先调用BeginPaint函数来准备display device context(在CDialog::OnPaint => CPaintDC dc(this)构造函数之中),如果update region被标记为erasing,那么BeginPaint又会发出WM_ERASEBKGND消息。为此,既然在最小化时系统没有发送WM_PAINT消息给窗口,为此更不会发出WM_ERASEBKGND消息。
    我曾在最小化时,故意发出WM_PAINT消息,此时该消息会进入到OnPaint的IsIconic分支。但是,如果你故意发出WM_ERASEBKGND消息,那么该消息必须在Cdialog::OnSysCommand函数之前,否则会被系统丢弃,为此不会进入OnEraseBkGnd函数。

    谢谢VisualEleven的回复,系统确实为了优化client area operation而限制了某些不必要消息的发送。

    http://www.debugease.com/vc/1246693.html

    ------------------------------------------------------------------------------------------

    请问MFC的一个代码简单却功能奇怪的问题?
    if (IsIconic())
    {
    CPaintDC dc(this); // device context for painting

    SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

    // Center icon in client rectangle
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2;

    // Draw the icon
    dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
    CDialog::OnPaint();
    }
    上面这个代码是MCF向导自动生成的,我跟踪了一下在最小化,最大化的过程发现没有被执行到,去掉 发现出也没出现什么不同,为何MFC要默认的帮我们生产上面的代码,有哪位高手知道上面的代码正真的目的是什么?在什么情况下会被执行到?

    这段代码是有用的,尽管通常情况下不会被调用。他的作用是在最小化状态下重绘窗口图标。

    IsIconic()作用是判断窗口是否处于最小化状态(点击了最小化按钮之后)。

    对于普通的对话框来说,如果你在if (IsIconic()) 下面加入AfxMessageBox("haha") ,你会发现消息框并不会弹出。

    原因是,if (IsIconic()) 这段代码是在OnPaint()函数内,当你最小化了对话框之后,虽然IsIconic()的值是TRUE,但是OnPaint()函数并不会运行。因为OnPaint()响应的是WM_PAINT消息,而WM_PAINT消息是针对客户区的。一个最小化了的窗口不需要重绘客户区。

    为了验证这一点,可以设置一定时器,在OnTimer()函数里写上
    if(IsIconic()) MessageBeep(MB_OK);
    当你点击最小化按钮后,你会听见嘟嘟声。

    那么这段代码究竟有什么用?它是不是永远不会被执行呢?当然不是。举两个例子。
    第一,如果你强行发送WM_PAINT消息,它会执行。
    第二,特殊的对话框。比如一个ToolBox风格的对话框。这个对话框不显示在任务栏,在最小化之后它会变成一个很小的一条显示在桌面上。这时如果它被遮挡,就会出发WM_PAINT消息,从而执行那段代码。

    总之,一般情况下可以不要这段代码,它的特殊用途我也不是很了解,但是我们至少可以知道它是怎么样工作的。

    http://zhidao.baidu.com/question/50297340

    ------------------------------------------------------------------------------------------
     
     
  • 相关阅读:
    SAP Spartacus 自定义Popover指令,如何实现弹出对话框自动关闭功能
    SAP Spartacus B2B 页面信息提示图标的弹出窗口显示实现逻辑
    一个好用的 SAP UI5 本地打包(build)工具,自动生成Component-preload.js
    什么是 SAP UI5 的 Component-preload.js, 什么是Minification和Ugification
    云小课 | 一个三分钟快速定制OCR应用的神器,要不?
    JavaScript实现:如何写出漂亮的条件表达式
    想做测试工程师,这7件事你必须先知道
    比物理线程都好用的C++20的协程,你会用吗?
    解读 SSDB、LevelDB 和 RocksDB 到 GaussDB(for Redis) 的迁移
    数据中心太耗电,送你一个节能神器
  • 原文地址:https://www.cnblogs.com/findumars/p/5356751.html
Copyright © 2020-2023  润新知