实战经验:使用ClipChildren属性减少界面闪烁

实战经验:使用ClipChildren属性减少界面闪烁

作者:BlogUpdater |  时间:2018-08-05 |  浏览:2840 |  评论已关闭 条评论

我们先做一个实验,来说明ClipChildren属性对界面绘制的影响。

新建一个基于对话框的MFC工程,我们在对话框模板的右下角,添加一个测试按钮,这个按钮代表对话框上的一个子控件。

我们分别在对话框的OnPaint和OnSize处理函数中,添加一段绘制矩形框的代码。用以模拟对话框重绘的操作。

void CClipChildrenTestDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting
		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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
	{
		CPaintDC dc(this); // device context for painting
		CRect rect;
		GetClientRect(rect);

		rect.DeflateRect(CSize(100, 100));
		dc.Rectangle(rect);
	}
}
void CClipChildrenTestDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	

	CDC * pDC = GetDC();
	CRect rect;
	GetClientRect(rect);

	rect.DeflateRect(CSize(100, 100));
	pDC->Rectangle(rect);

	ReleaseDC(pDC);
}

好了,实验开始了。

1) 设置ClipChildren属性为False(它的默认属性也是False),然后拖动对话框右下角使其大小发生改变,我们可以看到,绘制的矩形框遮住了右下角的测试按钮。

2) 设置ClipChildren属性为True,然后拖动对话框右下角使其大小发生改变,我们可以看到,绘制的矩形框并没有遮住右下角的测试按钮。

ClipChildren原理
ClipChildren主要用于父窗口,当该属性设置后,父窗口将不负责绘制子窗口,子窗口的绘制工作将由其自身负责,也即父窗口在绘制的过程中,”剪裁”掉了子窗口所在的区域。所以,在以上实验中,我们看到如果ClipChildren设置为False,父窗口绘制界面过程中会遮住子窗口。如果设置为True,就不会遮住。

当绘制复杂界面时,如果没有开启此属性(False),则界面的绘制逻辑如下:
父窗口绘制自身,也包含子窗口区域 -> 子窗口绘制自身 // 子窗口会先被遮盖,然后在自绘出来

如果开启了此属性(True),则绘制逻辑变为:
父窗口绘制自身,但剪裁掉了子窗口所在的矩形区域 -> 子窗口绘制自身 // 子窗口不会被遮盖

结论
善用ClipChildren属性,可以有效减少界面绘制过程中的闪烁,特别是当界面中有很多自绘的子控件时。

标签:

评论已关闭。