在一个Dialog的OnPaint按照下面的方法实现:
void CMyDialog::OnPaint()
{
    CWnd* pWnd = GetDlgItem(IDC_STATIC1);
    CDC* pDC = pWnd->GetDC();
    pWnd->Invalidate();  //??????????
    pWnd->UpdateWindow(); //????????????
    pDC->SelectStockObject(BLACK_BRUSH);
    pDC->Rectangle(0,0,10,10);
    pWnd->ReleaseDC(pDC);
}按照MSDN上的说明,通过UpdateWindow会向窗口发送WM_PAINT的消息,
那么相应改消息的时候是否又会调用OnPaint函数呢?上面这段函数执行的顺序到底是怎么样的呢?

解决方案 »

  1.   

    在一本书上写了,为了防止WINDOWS对静态控件的重画,需要通过Invalidate和UpdateWindow配合使用才可以做到。
    但是,如何做到呢?
    想知道一个真真的过程
      

  2.   

    Invalidate设置无效区域,并且发送一个WM_PAINT消息到消息队列;但是WM_PAINT优先度不高,窗口不一定会及时处理这个消息,而UpdateWindow会让窗口及时处理WM_PAINT消息——如果已经有无效区域设置过了。
      

  3.   

    这两个函数的作用其实我也很清楚。
    但是,UpdateWindow让窗口及时处理WM_PAINT消息,
    这时窗口是否又一次调用OnPaint函数呢?
    如果是,这不就是一个死循环。另外,对话框的窗口,负责自己以及它所包含的控件的绘制。
    pDC->SelectStockObject(BLACK_BRUSH);
        pDC->Rectangle(0,0,10,10);
        pWnd->ReleaseDC(pDC);
    对某个空件的特别定制又是如何反映到对话框中的。对这些函数调用的过程,已经消息的处理过程不是太清除。
    因为,的确对WINDOWS不是太了解。
      

  4.   

    目的可能就是不断刷新IDC_STATIC1吧
      

  5.   

    dfyang() 说的不断刷新,好像没有根据。
    如果是这样,就存在一个逻辑上的死循环。
    这对系统可是比较大的负担的哦
      

  6.   

    不会,UpdateWindow的执行结果是:如果设置了无效区域,迫使窗口响应WM_PAINT消息;如果没有无效区域,则把WM_PAINT从消息队列中喀擦掉。
    OnPaint执行后会清空无效区域,直到下一次窗口状态改变或者Invalidate/InvalidateRect之类的函数设置新的无效区域。
      

  7.   

    但是如果是死循环,那么我在其中加入
    TRACE("On Paint\n"),然后调试却没有看到不断的打印信息
      

  8.   

    上面的代码虽然简单,但是要真正解释我想可能需要比较多的WINDOWS内部机制的知识,
    摆脱各位了。
      

  9.   

    我刚测试的,debug版,直接执行窗口的Edit框(我把IDC_STATIC1换成了一个Edit框的ID)有明显的闪烁。
    不设置断点,直接f5进入调试状态,用afxDump输出到Output窗口,看到不停的有信息输出
      

  10.   

    上面操作的是STATIC的空件,我测试并没有出现闪烁。
    谢谢
      

  11.   

    UpdateWindow会向窗口发送WM_PAINT的消息,
    Invalidate同样。
    上面代码调窗口的IDC_STATIC1控件重画。也就是执行IDC_STATIC1对应的静态空间的OnPaint函数。
      

  12.   

    >上面操作的是STATIC的空件,我测试并没有出现闪烁。我是为了确认闪烁状况特意改成Edit控件的。实际上我的机器上用Static也会闪烁。可能你的机器好,所以看不见闪烁状况而已。另外,我对我前面的解释还是有自信。并且经过测试,环境为XP+VC5和XP+VC6。
    你可以试试在OnPaint前声明一个全局变量:
    int xTime = 0;
    OnPaint里边
    xTime ++;然后重载OnCancel,加入下面代码:
    CString str;
    str.Format("OnPaint ran %d times!", xTime);
    AfxMessageBox(str);CDialog::OnCancel();
      

  13.   

    看看显示的次数是多少。ps,我并不觉得改不改成Edit控件对于这部分处理会造成什么不一样的结果。^_^
      

  14.   

    是不是可以这样认为:
    1、dialog处理WM_PAINT消息,即调用OnPaint
    2、在该函数中,为了对IDC_STATIC进行特殊的定制,通过pWnd->UpdateWindow由向dialog发送了WM_PAINT消息
    3、在OnPaint函数中,在调用pWnd->UpdateWindow后,继续完成函数的下面处理
        pDC->SelectStockObject(BLACK_BRUSH);
        pDC->Rectangle(0,0,10,10);
        pWnd->ReleaseDC(pDC);
       这些处理完成对IDC_STATIC的定制(画了一个黑色的矩形)
    4、当刚才发送的WM_PAINT到达dialog后,由于它消息的属主是IDC_STATIC空件,那么IDC_STATIC空件将会重画一次,而这次画出的东西,则是由
        pDC->SelectStockObject(BLACK_BRUSH);
        pDC->Rectangle(0,0,10,10);
        pWnd->ReleaseDC(pDC);
    所定制的内容上面是我自己凭个人推测的,由于对WINDOWS不是太熟悉,请大家给意见。
      

  15.   

    怎么会死循环呢,
    CWnd* pWnd = GetDlgItem(IDC_STATIC1);
        CDC* pDC = pWnd->GetDC();
        pWnd->Invalidate();  //??????????
        pWnd->UpdateWindow(); //????????????不是针对对话框的,而是针对控件发的。
      

  16.   

    如果派生了一个CStatic类,那么就不会死循环,但是没有派生类,则对话框会处理这个OnPaint消息
      

  17.   

    汗~~我乱七八糟说的话……WM_PAINT消息
      

  18.   

    我的看法:
    1、dialog处理自己的WM_PAINT消息,然后调用OnPaint
    2、在该函数中,为了刷新IDC_STATIC状态,通过pWnd->UpdateWindow由向dialog发送了WM_PAINT消息
    3、在OnPaint函数中,在调用pWnd->UpdateWindow后,继续完成函数的下面处理
        pDC->SelectStockObject(BLACK_BRUSH);
        pDC->Rectangle(0,0,10,10);
        pWnd->ReleaseDC(pDC);
       这些处理完成对IDC_STATIC的定制(画了一个黑色的矩形)
    4、当刚才发送的WM_PAINT到达dialog后,由于它消息的属主是IDC_STATIC空件,那么IDC_STATIC空件将会重画一次,而这次画出的东西,并不是则是由
        pDC->SelectStockObject(BLACK_BRUSH);
        pDC->Rectangle(0,0,10,10);
        pWnd->ReleaseDC(pDC);
    所定制的内容
      

  19.   

    mousefj(冯杰) 所描述的与我的推测大体相同。
    不知道其它同志还有别的意见不?
      

  20.   

    使IDC_STATIC1的内容更新吧。
      

  21.   

    pWnd->Invalidate();
    刷新的是子窗口。