窗口重画ONPaint

WM_PAINT源头:第一次创建窗口,窗口最大、最小化,窗口大小改变、窗口移动,无效区等动作,以及调用Invalidate、InvalidateRect或InvalidateRgn、Updateindow等函数。

    每个窗口(HWND)实例,在windows操作系统中,都有个上下文记录区,其中记录着当前窗口的无效区域数据。系统内核利用空闲时间检查所有窗口的无效区,如果非空,就产生一个WM_PAINT发送给此线程再转发到当前窗口来处理。当然此时,此窗口的无效区域还是存在的,通过在WM_PAINT中执行BeginPaint,就将此无效区域清空(使用ValidateRect一样效果),在执行具体的绘制操作。(这些执行都在窗口的Default中执行了,MS不给你看具体的过程,所以在MFC的系统代码中看不到。)。如果不将无效区域清空,系统将周而复始的产生WM_PAINT消息,导致OnIdle不能被执行,且当前程序CPU占用差不多100%。(由于是空闲时间处理,所以对话框的其他消息处理没被阻塞,可以按按钮等操作)。
 
   I、拖动窗口,将被全部重新绘制,因为拖动的操作调用了RedrawWindow函数,此函数不光产生整个窗口的 Invalide调用,同时接下来还直接执行窗口的绘制操作(读取窗口的无效区,如果不屏蔽CDialog::OnPaint,就在OnPaint里面绘制了)。
   II、如果是被另外一个对话框覆盖,那个对话框将会向其下的窗口(默认的窗口Z轴顺序)发生设置无效区域的指令

相关函数简介:
    InvalidateRect(hWnd,&rect,TRUE): 向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,是通过线程的消息队列来发送刷新消息,是最常用的

    Invalidate:标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行WM_PAINT.

    UpdateWindow: 直接调用窗口函数立即响应刷新消息,使窗口刷新消息优先被响应(消息队列中如果没有WM_PAINT消息就什么都不执行),UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT.一般是在ShowWindow之后调用。

    RedrawWindow:
      BOOL RedrawWindow( LPCRECT lpRectUpdate = NULL, CRgn* prgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE );
    根据fuRedraw旗标的设置,重画全部或部分窗口,相当于先调用InvalidateRect,紧接着又调用UpdateWindow,此外RedrawWindow还提供了一些前两者没法做到的功能。

 

附录A  设置窗口位置大小的2个函数:

I、void MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE );

II、

BOOL SetWindowPos( const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags );

 

附录B:静态切分窗口:当窗口第一次被创建时,窗格就已经被切分了,窗格数目、次序不在改变。

             I   重载函数OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext);

             II  在里面添加窗口静态切分函数CreateStatic(CWnd*,int,int,DWORD,UINT);

             III 为静态窗格指定一个视图类CreateView(int,col,CRuntimeClass*,SIZE,CCreateContext*);

例子:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext)
{

 // TODO: Add your specialized code here and/or call the base class
 CRect rect;
 GetWindowRect(&rect);
 BOOL bRes=m_wndSplitter.CreateStatic(this,2,1);
 m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CBombAppView),CSize(rect.Width(),rect.Height()/10),pContext);
 m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CBombAppView1),CSize(rect.Width(),rect.Height()),pContext);
// m_wndSplitter.SetColumnInfo(0,rect.Height()/2,10); //设置列长
// m_wndSplitter.SetColumnInfo(1,rect.Height()/2,10);
 m_wndSplitter.RecalcLayout();
 return bRes;

}

             

  附录c     http://hi.baidu.com/ouanan/blog/item/ad90dacf559dd13af9dc616b.html

           http://baike.baidu.com/view/1226797.htm

             http://baike.baidu.com/view/1226818.htm

               http://www.cppblog.com/OnTheWay2008/archive/2009/06/03/86615.aspx


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiven/archive/2009/06/15/4271387.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值