Windows窗口相关的一些概念解释
发布日期:2021-10-20 09:40:03 浏览次数:25 分类:技术文章

本文共 3917 字,大约阅读时间需要 13 分钟。

原文出处:

    最近工作中关于UI开发方面的东西多了些,碰到问题的时候查阅了很多资料,对Windows窗口的一些概念的理解也慢慢深入了很多。在这篇中把一些比较容易混淆和相关资料比较少的概念做一个总结,可能你用到这些概念的几率不大,但是一旦你遇到相关问题,解决起来还真是要费一番功夫。

 

    一、窗口的分类

    Windows定义了3种窗口类型:
    #define WS_OVERLAPPED       0x00000000L
    #define WS_POPUP            0x80000000L
    #define WS_CHILD            0x40000000L
    顾名思义,CHILD是从属于其他窗口的子窗口;POPUP是弹出窗口;OVERLAPPED为重叠式窗口,MSDN中并没有给出该窗口的确切定义,只提到该类型的窗口一般都有标题栏和边框。其实从WS_OVERLAPPEDWINDOW宏的定义我们可以知道,OVERLAPPED窗口通常拥有标题栏、边框、客户区、图标、可调整尺寸边框、最小化和最大化按钮。
    看上去这3种类型的窗口我们已经解释清楚了,但是其实还有很多概念需要阐述,下一节我们再仔细研究。
    现在考虑一个问题:一个窗口能不能具有多个类型?这个问题在这篇文章里作者做了探讨),不过好像最后并没有明确的答案,这里总结一些比较确切的结论:
    1、OVERLAPPED类型窗口适合作为应用程序的主窗口,或者POPUP类型也可以,如基于对话框的应用程序;
    2、OVERLAPPED类型和POPUP类型比较类似,但是OVERLAPPED类型默认具有标题栏等元素,而且即使你显示去掉WS_CAPTION和WS_BORDER这些风格,Windows还是会加上标题栏和边框,POPUP类型没有这个特点;另外在CreateWindow函数中对于CW_USEDEFAULT默认值的取值是不同的;
    3、OVERLAPPED类型不能和CHILD类型同时设置,原因后面说明;
    4、事实上这3种类型的窗口不应该混合应用,虽然Windows会对他们的混合做处理,但是并没有官方的说明,我们无从确切的知道这样的行为的结果。

 

    二、窗口的parent和owner

    上一节只是大概介绍了窗口的3种类型,还有很多概念需要我们仔细弄个明白。
    1、Desktop窗口
    简单的说就是桌面窗口。desktop窗口是Windows产生的第一个窗口,上面的图画就是壁纸。desktop窗口是一个特殊的窗口,不属于上面3种窗口类型中的任何一种。你可以把Windows的所有窗口想象成一个树结构,而这棵树的根就是desktop窗口。
    2、Top-Level窗口
    top-level窗口是指没有WS_CHILD属性的窗口,它们的parent通常为desktop窗口或者为NULL。top-level窗口是desktop窗口的下一级。
    3、子窗口(child window)
    具有WS_CHILD属性的窗口为子窗口,它们必须有父窗口(parent),同时子窗口可以拥有自己的子窗口。子窗口只能出现在父窗口的客户区之内,子窗口不能成为活动窗口,也不能显示在任务栏上。建立子窗口时的区域坐标是以父窗口客户区左上角为原点的,而非子窗口是屏幕坐标。子窗口显示在父窗口显示之后,隐藏在父窗口隐藏之前,销毁在父窗口销毁之前。
    4、重叠式窗口(overlapped)
    具有WS_OVERLAPPED属性的窗口为重叠式窗口。重叠式窗口一定是top-level窗口,因此它们不能再具有WS_CHILD属性。
    5、弹出窗口(popup)
    具有WS_POPUP属性的窗口为弹出窗口,弹出窗口也是top-level窗口,它和重叠式窗口都可以显示在桌面的任何地方。
    6、parent和owner
    这两个概念是本节需要重点阐述的。Windows中上下级窗口的关系有两种:parent-child和owner-owned,一个窗口在有parent窗口的情况下还可能有owner窗口。这两种关系有什么联系和区别呢?
    这篇文章中写得比较清楚),截取其中一段:

 

    如果一个窗口数据的owner域非NULL,则它和该窗口建立了owner-owned 关系,拥有关系决定了:

    (1)被拥有的窗口永远显示在拥有它的那个窗口的前面;
    (2)当所有者窗口最小化的时候,它所拥有的窗口都会被隐藏;
    (3)当所有者窗口被销毁的时候,它所拥有的窗口都会被销毁。
    需要注意的是,隐藏所有者窗口并不会影响它所拥有的窗口的可见状态。比如:如果窗口 A 拥有窗口B,窗口B拥有窗口C,则当窗口A最小化的时候,窗口B被隐藏,但是窗口 C还是可见。

    如果一个窗口的parent域非NULL,则它和该窗口之间就建立了parent-child关系。父子决定了:

    (1)窗口在屏幕上面的显示位置。父窗口提供了用来定位子窗口的坐标系统,一个子窗口只能显示在它的父窗口的客户区中,之外的部分将被裁减。这个裁减法则决定了如果父窗口不可见,则子窗口肯定不可见。如果父窗口移动到了屏幕之外,子窗口也一样。
    (2)当父窗口被隐藏时,它的所有子窗口也被隐藏。
    (3)父窗口被销毁的时候,它所拥有的子窗口都会被销毁。
     注意!最小化父窗口不会影响子窗口的可见状态,子窗口会随着父窗口被最小化,但是它的WS_VISIBLE属性不会变。

 

    另外,parent-child关系是双向的,一个窗口知道自己的parent和child;owner-owned关系是单向的,窗口只知道自己的owner。

    下面我们总结一下窗口类型与parent、owner窗口之间的关系特点。
    1、子窗口一定有parent,且parent即相当于owner,子窗口的父窗口可以为top-level窗口或者其他子窗口;
    2、只有overlapped窗口和popup窗口可以是owner窗口,子窗口不能是owner窗口;
    3、overlapped窗口和popup窗口的parent一般都是desktop窗口,由于overlapped窗口多用于作为应用程序的主窗口,其owner一般为desktop窗口;而popup窗口的owner是在CreateWindow函数中通过设置hWndParent参数给定的,如果hWndParent为非子窗口,则这个窗口即为popup窗口的owner;如果hWndParent为子窗口,系统从hWndParent的父窗口向上找,直到找到第一个非子窗口,把它作为该popup窗口的owner;
    
    Windows的API函数GetParent可以获取窗口的parent或owner,如果是子窗口则返回parent;如果overlapped窗口返回NULL;如果是popup窗口返回其owner。用API函数GetWindow(GW_OWNER)可以获取窗口的owner,或者用MFC CWnd类的成员函数GetOwner也可以。

 

    三、窗口WS_CLIPSIBLING和WS_CLIPCHILDREN风格

    首先简单的解释一下这两个风格的意义。
    WS_CLIPSIBLING 风格用于同一级的子窗口之间,表示当某设置了该风格的子窗口需要重绘时,被其他窗口遮挡的部分(按照Z-order)将被裁减,也就是被遮挡区域不进行重绘。
    WS_CLIPCHILDREN 风格则用于父窗口和子窗口之间,表示当某设置了该风格的父窗口需要重绘时,被子窗口遮挡的部分将被裁剪,即被遮挡的区域不进行重绘。
   
    在Windows系统的窗口中,凡是overlapped窗口和popup窗口都肯定具有WS_CLIPSIBLING风格,即使你写代码将这个风格去掉,Windows还是会自动加上。
    为什么呢?仔细想想就清楚了,我们可以认为overlapped窗口和popup窗口都是desktop窗口的同一级“子窗口”,他们之间要想在互相重叠的时候正确显示,就必须具有这个风格。为什么同一级子窗口重叠时都要有WS_CLIPSIBLING风格呢?比如现在有一个父窗口P,它有两个重叠的子窗口A和B,A的Z-order在B之前,那么正常显示的话A应该把B中重合的区域遮挡住。Windows在判断一个窗口区域是否需要重绘的时候,一般是看这个区域是否被其他窗口遮挡。因为此时系统认为A始终在B的上面,并未被遮挡,所以当你移动A窗口的时候,A的窗口内部区域是不会被通知重绘的。此时B被遮挡的部分肯定会被通知重绘,于是你会发现B重绘的时候却把与A重合的区域画乱了。但是如果我们把A和B都指定了WS_CLIPSIBLING风格以后,B被遮挡的部分的重绘就被裁剪掉了,这样它就不会捣乱了。
    当然,对于我们平时在对话框上用的最多的控件子窗口,虽然它们都没有WS_CLIPSIBLING风格,但是由于它们基本不重叠,因此不会彼此影响。
    如果你只为一部分子窗口设置了WS_CLIPSIBLING风格,就要保证其他窗口的所有重绘都发生在设置风格的子窗口之前,否则也会出现问题。对于对话框的控件来说,可以通过控制Tab-order来控制绘制顺序;对于其他子窗口,可以通过控制Z-order控制。

    对于WS_CLIPCHILDREN风格也是相同的问题,如果你不想父窗口的重绘影响到子窗口的绘制,那么最好给父窗口加上WS_CLIPCHILDREN风格。

 

    关于窗口的一些概念就先写这些吧,如果你对这些概念比较模糊的话,相信读完这篇文章会有很多收获。对于其中某些描述,我尽量做到严谨,但是可能会有错误的地方,请大家指正。另外有很多概念微软根本没有明确的定义和解释,所以还需要大家多摸索,在实践中探索规律性的东西。

转载地址:https://blog.csdn.net/up2wing/article/details/17483375 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:关于WS_CLIPCHILDREN和WS_CLIPSIBLINGS的理解
下一篇:Windows 绘图详解

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月02日 05时24分05秒