如何进行绘制
首先我们来看一下CBkDialogViewImpl类的绘制过程:
CBkDialogViewImpl含有一个CBkImage类成员m_imgMem用于双缓冲绘制,在WM_SIZE消息处理函数中进行创建:
m_imgMem.CreateBitmap(rcClient.Width(), rcClient.Height(), RGB(0,0, 0));
CBkDialogViewImpl含有一个CRgn类成员m_rgnInvalidate用于脏区域描述,在_InvalidateRect方法内创建(绘制之前):
m_rgnInvalidate.CreateRectRgnIndirect(rcInvalidate);
我们来看看CBkDialogViewImpl类的OnPrint方法,在处理WM_PAINT消息时会调用这个函数,首先获取一个兼容DC,并将双缓冲的图像渲染兼容DC:
CDCdcMem;
CDCHandledcMemHandle;
HDChDCDesktop = ::GetDC(NULL);
dcMem.CreateCompatibleDC(hDCDesktop);
::ReleaseDC(NULL, hDCDesktop);
HBITMAPhbmpOld = dcMem.SelectBitmap(m_imgMem);
然后设置兼容DC的脏区域:
dcMem.SelectClipRgn(m_rgnInvalidate);
之后在这个DC上面进行绘制操作,
if(m_bHasHeader)
m_bkHeader.RedrawRegion(dcMemHandle,m_rgnInvalidate);
if(m_bHasBody)
m_bkBody.RedrawRegion(dcMemHandle,m_rgnInvalidate);
if(m_bHasFooter)
m_bkFooter.RedrawRegion(dcMemHandle,m_rgnInvalidate);
最后将这个双缓冲图像整体绘制到窗口DC上面:
m_imgMem.Draw(dc, 0, 0);
CBkDialogViewImpl的方法_InvalidateRect用于绘制指定区域,合并现有脏区域,重绘指定区域。_InvalidateControl方法用于重绘指定控件,即获取此控件位置并重绘此位置
可见现在绘制转入了控件层的RedrawRegion方法。
控件中用于处理绘制的方法有哪些呢:
CBkWindow:
RedrawRegion(只有控件在重绘区域内时才进行):调用DrawBkgnd,发送WM_PAINT消息
DrawBkgnd:在兼容DC中绘制背景,如果Skin存在,用Skin绘制,否则用Style中颜色绘制。
OnPaint:只有绘制文字的过程,一般不被调用
CBkPanel:
RedrawRegion:调用父类CBkWindow的RedrawRegion方法,重绘自身背景,循环调用每个子节点的RedrawRegion方法。
OnPaint:原来有处理,现在被return掉了。
在CBkPanel 类的RedrawRegion方法中调用了BeforePaint和AfterPaint两个方法,BeforePaint用来设置BkMode、BkColor、Font和TextColor并保存原始信息,AfterPaint用于将这些环境重置回原值。