前段时间研究duilib绘图机制,由于忙了一段时间,感觉又忘记了不少,写个博客,记录一下,免得以后又看源码。直接翻博客就行了。
WM_PAINT 分为两部分,第一部分为: 控件 布局, 第二部分为:界面更新。
控件布局
duilib里面最上层的 是容器 , 容器里面主要包含各种控件,当然也可以嵌套容器。
如果最上层的容器需要布局,那就更新最上层容器 位置,即setpos函数。
容器的setpos函数 一个责任那就是维护子控件的位置,为以后更近控件做准备。
if( m_bUpdateNeeded ) { m_bUpdateNeeded = false; RECT rcClient = { 0 }; ::GetClientRect(m_hWndPaint, &rcClient); if( !::IsRectEmpty(&rcClient) ) { if( m_pRoot->IsUpdateNeeded() ) { m_pRoot->SetPos(rcClient); if( m_hDcOffscreen != NULL ) ::DeleteDC(m_hDcOffscreen); if( m_hDcBackground != NULL ) ::DeleteDC(m_hDcBackground); if( m_hbmpOffscreen != NULL ) ::DeleteObject(m_hbmpOffscreen); if( m_hbmpBackground != NULL ) ::DeleteObject(m_hbmpBackground); m_hDcOffscreen = NULL; m_hDcBackground = NULL; m_hbmpOffscreen = NULL; m_hbmpBackground = NULL; } else { CControlUI* pControl = NULL; while( pControl = m_pRoot->FindControl(__FindControlFromUpdate, NULL, UIFIND_VISIBLE | UIFIND_ME_FIRST) ) { pControl->SetPos( pControl->GetPos() ); } } // We'll want to notify the window when it is first initialized // with the correct layout. The window form would take the time // to submit swipes/animations. if( m_bFirstLayout ) { m_bFirstLayout = false; SendNotify(m_pRoot, DUI_MSGTYPE_WINDOWINIT, 0, 0, false); } } }
布局完成之后就是刷新界面,刷新界面机制和布局一样,使用的是DoPaint函数,同样容器维护期子类的更新。
这里就不在多描述了,DoPaint函数原型是这样的:
void CContainerUI::DoPaint(HDC hDC, const RECT& rcPaint)
熟悉mfc对话框的都知道有一个OnPaint函数,我们绘图就是在这里面进行的。
这个DoPaint函数和OnPaint函数函数类似,我们可以进行一些 绘图操作。
duilib的控件也是在这个hdc上面绘图。
在MFC里面,写一个gif控件 ,分下面几个步骤
1.继承cwnd 写一个控件控件
2使用settimer函数添加一个定时器
3.定时器里面添加 InvaldateRect函数
4.在OnPaint函数里面 绘制当前帧
模仿我们在mfc里面的使用操作,我们可以再duilib里面做一些动画操作。