VC++中的窗口样式、窗口重绘、显示顺序

来源:互联网 发布:mac磁盘工具在哪里 编辑:程序博客网 时间:2024/06/05 12:23

Invalidate、UpdateWindow、Z-order、显示顺序

转自:http://blog.pfan.cn/yuqiexing/51146.html

在一个Dialog的OnPaint按照下面的方法实现:

voidCMyDialog::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 函数呢?

上面这段函数执行的顺序到底是怎么样的呢?

MSDN的解释如下:如果刷新区域不为空,UpdateWindow 会绕过消息队列直接发送 WM_PAINT 消息给子窗口。之所以要首先调用 pWnd->Invalidate,是因为首先要设置刷新区域。刷新之后,再开始static的自身绘制.

关于控件自身的重绘还包括很多,例如处理 WM_ERASEBKND,同时在每次绘制时,最好要重新用双缓冲绘制背景,而不是调用 Invalidate(TRUE),因为这样,仍然会引起轻微的闪烁。

但是有时候,我们会发现UpdateWindow 会引起子窗口的更新。要避免这一点,最好把父窗口的属性加上 WS_CLIPCHILDREN.

WS_CLIPCHILDREN 和 WS_CLIPSIBLINGS 的作用还有很多。

例如这样一个问题。创建一个基本的对话框程序,在界面上先放置一个按钮,再次放置一个 ClistCtrl 的对象,其中按钮和 ClistCtrl 部分重叠在一起。

在VC或者VS中提供的对话框编辑器中,可以看到:


运行程序的时候,看到按钮和ClistCtrl 重叠的部分被遮住,在ClistCtrl 对象内鼠标点击按钮和此对象重叠的部分,按钮就出现了,可以看到效果是点击到了按钮。

如果我们交换按钮和ClistCtrl 的tab顺序,就会发现按钮可以看见,但是却不能响应了。这说明 ClistCtrl的z-order更靠前,但是显示的顺序却恰恰相反。

原因在于:Windows 的资源文件里并没有存储 Tab Order 的值,而是以控件出现的先后顺序体现,此先后顺序决定了对话框管理器创建控件的顺序(也顺便决定了兄弟窗口之间的初始 Z-Order)。各个控件依次添加到一个内部的管理链表中,而发生鼠标事件时,会从链表头开始逐项检查鼠标事件发生的位置是否处于某控件的窗口范围内,一旦测试命中,显然就不会再往后遍历了。而显示时则不同,显然所有的控件都是要显示的,后绘制的控件如果与前绘制的有重叠,显然最终会是后绘制的控件的样子。

当然,我们可以通过转发消息来实现,即在 PreTranslateMessage 中来进行控制。不过实际上利用WS_CLIPSIBLINGS可以很巧妙的解决这个问题。我们仍然按最先放置的顺序来看。这种情况下,按钮是可以被响应的,只是被遮住了。因此我们把listctrl的风格中加入WS_CLIPSIBLINGS,这样它就可以不刷新绘制按钮区域,按钮就可以被看见,也可以响应了。

GetDlgItem(IDC_LIST1)->ModifyStyle(0,WS_CLIPSIBLINGS);

 

参考:

UpdateWindow

Updates the client area by sendingaWM_PAINT message if the update region is not empty. The UpdateWindow memberfunction sends a WM_PAINT message directly, bypassing the application queue. Ifthe update region is empty, WM_PAINT is not sent.

WS_CLIPSIBLINGS

Clips child windows relative to each other;that is, when a particular child window receives a paint message, theWS_CLIPSIBLINGS style clips all other overlapped child windows out of theregion of the child window to be updated. (If WS_CLIPSIBLINGS is not given andchild windows overlap, when you draw within the client area of a child window,it is possible to draw within the client area of a neighboring child window.)For use with the WS_CHILD style only.

WS_CLIPCHILDREN

Excludes the area occupied by child windowswhen you draw within the parent window. Used when you create the parent window.



关于WS_CLIPCHILDREN和WS_CLIPSIBLINGS的理解

转自:http://tech.ddvip.com/2009-06/1243872103121916.html

1.1 WS_CLIPCHILDREN

WS_CLIPCHILDREN样式从字面上可以理解成ClipChildren,裁减子窗口。

MSDN里的E文解释:Excludesthe area occupied by child windows when drawing occurs within the parentwindow. This style is used when creating the parent window.

读E文是一件困难的事,为了不让大家再重复我的痛苦,我就越俎代庖翻译一下:WS_CLIPCHILDREN样式主要是用于父窗口,也就是说当在父窗口绘制的时候,父窗口上还有一个子窗口,那么设置了这个样式的话,子窗口区域父窗口就不负责绘制。

那么按照MSDN的理解,可以用下面这幅图来表示:

 

图 1‑1 WS_CLIPCHILDREN样式的初理解

1.1 WS_CLIPSIBLINGS

WS_CLIPSIBLINGS样式从字面上可以理解成ClipSiblings,裁减兄弟窗口。

MSDN里的E文解释:Clipschild windows relative to each other; that is, when a particular child windowreceives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all otheroverlapping child windows out of the region of the child window to be updated.If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible,when drawing within the client area of a child window, to draw within theclient area of a neighboring child window.

中文意思是:子窗口间相互裁减。也就是说当两个窗口相互重叠时,设置了WS_CLIPSIBLINGS样式的子窗口重绘时不能绘制被重叠的部分。反之没有设置WS_CLIPSIBLINGS样式的子窗口重绘时是不考虑重叠不重叠,统统重绘。

 

图 1‑2 WS_CLIPSIBLINGS样式的初理解

0 0
原创粉丝点击