一、概念

  • 在windows系统中,每个窗口对象都对应有一个数据结构,形成一个list链表。系统的窗口管理器通过这个list来获取窗口信息和管理每个窗口。这个数据结构中有四个数据用来构建list,即child、sibling、parent、owner四个域。

  • 所以我们可以看到,窗口之间的关系有两种:owner-owned 关系parent-child关系。前者称之为拥有/被拥有关系,后者称之为父/子关系。

  • 窗口之间的关系,决定了窗口的外在表现。比如显示、销毁等。

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

    • 被拥有的窗口永远显示在拥有它的那个窗口的前面;
    • 当所有者窗口最小化的时候,它所拥有的窗口都会被隐藏;
    • 当所有者窗口被销毁的时候,它所拥有的窗口都会被销毁。
  • 注意!最小化所有者窗口并不会影响它所拥有的窗口的可见状态

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

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

  • Windows系统使用两种关系是为了更加灵活的管理窗口。父窗口会限制子窗口显示区域,而拥有者窗口则不会限制被拥有窗口显示区域。这是他们最大的区别。

  • 另外,窗口之间消息的传递也和窗口关系有关,通常,一个窗口会把自己的通知消息发送给它的父窗口,但不全是这样,这样窗口之间的消息传递也可以灵活控制。

二、窗口类型的说明和限制

  • 控制台窗口(desktop window)。这是系统最早创建的窗口。可以认为它是所有WS_OVERLAPPED类型窗口的所有者和父窗口。当系统初始化的时候,它首先创建控制台窗口,大小覆盖整个屏幕。所有其它窗口都在这个控制台窗口上面显示。窗口管理器所用的窗口list中第一个就是这个控制台。它的下一层窗口叫做顶级窗口(top-level),顶级窗口是指所有非child窗口、没有父窗口,或者父窗口是desktop的窗口,它们没有WS_CHILD属性。

  • WS_OVERLAPPED类型的窗口可以显示在屏幕的任何地方。它的所有者窗口是控制台。Overlapped的窗口属于顶级窗口,一般作为应用程序的主窗口。不论是否给出了WS_CAPTION、WS_BORDER属性,这类窗口创建后都有标题栏和边框。所有overlapped窗口都有WS_CLIPSIBLINGS属性。当系统关闭的时候,它将销毁所有overlapped类型的窗口。

  • WS_POPUP类型的窗口可以显示在屏幕任何地方,一般没有父窗口,但是如果明确调用SetParent,这类窗口也可以有父窗口。和WS_OVERLAPPED类型的窗口类似,WS_POPUP类型的窗口的所有者是在CreateWindow或者CreateWindowEx函数中通过设置hWndParent参数给定的,如果hWndParent不是子窗口,则该窗口就成为这个新的弹出式窗口的owner,否则,系统从hWndParent的父窗口向上找,直到找到第一个非子窗口,把它作为该弹出窗口的owner。在这种情况下,参数hwndParent被保存在新建窗口的parent域中,而它的所有者窗口句柄则保存在owner域中。当owner窗口销毁的时候,系统自动销毁这个弹出窗口。

  • WS_POPUP类型的窗口也属于顶级窗口,它和WS_OVERLAPPED窗口的主要区别是WS_POPUP窗口不需要有标题栏,也不必有边框。

  • 所有者窗口只能是WS_OVERLAPPED或者WS_POPUP类型的窗口,子窗口不能是所有者窗口,并且所有者窗口也可以被拥有。

  • 缺省情况下,对话框和消息框属于owned窗口,除非在创建它们的时候明确给出了WS_CHILD属性,(比如对话框中嵌入对话框的情形)否则由系统负责给它们指定owner窗口。需要注意的是,一旦创建了owned类型的窗口,就无法再改变其所有关系,因为Win32没有没有提供改变窗口所有者的方法。而且在Win32中,由于有多线程的存在,所以要注意保证parent-child窗口或者owner-owned窗口要同属于一个线程。

  • WS_CHILD类型的窗口的父窗口就是它的所有者窗口。一个子窗口的父窗口也是在CreateWindow函数中用hWndParent参数指定的。子窗口只能在父窗口的客户区中显示,并随父窗口一起销毁。**子窗口必须有一个父窗口,这是它和WS_OVERLAPPED以及WS_POPUP窗口之间的主要区别。**父窗口可以是顶级窗口,也可以是其它子窗口。

三、几个相关函数的说明

  • 获取所有者窗口**GetWindow(hWnd, GW_OWNER)**永远返回窗口的所有者(owner)。对于子窗口,函数返回NULL,因为Windows系统没有维护子窗口的所有者信息。

  • 获取/设置父窗口,Win32 API给出了函数GetParent和SetParent。对于SetParent,msdn里面说明了父子窗口必须是同一个进程的。但是由于窗口句柄是系统全局唯一的,不属于同一个进程的情况下,也可以成功调用,但是后果未知。GetParent的返回值比较复杂,对于WS_OVERLAPPED类型的窗口,它返回0,对于WS_CHILD类型,它返回其父窗口,对于WS_POPUP类型,它返回其所有者窗口。

  • **GetWindowWord(hWnd, GWW_HWNDPARENT)**返回一个窗口的父窗口,如果没有,则返回其所有者。

  • **ShowOwnedPopups(hWnd,fShow);**函数可以将owner窗口所有拥有的窗口一起显示或者隐藏。

转载于:https://juejin.im/post/5a378596f265da432840f52d

Windows系统中owner owned 关系和 parent child关系相关推荐

  1. Windows系统中让硬盘更快的九大绝招

    Windows系统中让硬盘更快的九大绝招 一.合理使用硬盘  何为合理使用硬盘呢?首先我们要了解硬盘盘片的物理结构.分区并格式化后的硬盘却是以扇区为基本单位的,一个分区是由若干个扇区构成的.那什么是扇 ...

  2. windows系统中创建线程常用哪几个函数,有什么区别?

    windows系统中创建线程常用哪几个函数? 在windows系统中创建线程的函数有: CreadThread,AfxBeginThread,_beginthread,_beginthreadex. ...

  3. 解决Macbook Pro 2017安装Windows10双系统后在Windows系统中Apple蓝牙鼠标不能使用问题

    MAC BOOK PRO 2017安装Windows10双系统在Windows系统中蓝牙鼠标不能使用解决办法 最近因工作需要,macOS系统不能要求,大部分工作必须要在Windows系统中进行,最初安 ...

  4. 在windows系统中使用Ceres非线性优化库:(一)安装Ceres库

    (一)安装Ceres库                         1.用vcpkg安装Ceres库                 1.1.安装vcpkg 1.2.安装Ceres 1.3.配置C ...

  5. ip设置 kali 重置_在 Windows 系统中如何重置 TCP/IP 协议堆栈修复网络连接问题

    Internet 在 TCP/IP 协议上工作,如果 TCP/IP 协议堆栈在 Windows 或任何其他操作系统(例如 Linux 或 MacOS)中无法正常工作,则您的 Internet 连接会出 ...

  6. windows系统中,在当前目录下打开cmd命令行的两种方法

    windows系统中,在当前目录下打开cmd命令行的两种方法 1.在当前路径地址栏中直接输入'cmd',然后回车. 2.在当前路径下,按住'shift'键同时点击鼠标右键,点击"在此处打开P ...

  7. Cmder命令行工具在Windows系统中的配置

    一.Cmder简介 Cmder:一款用于Windows系统中,可增强传统cmd命令行工具的控制台模拟器(类似于Linux系统中的终端控制窗口) 特点: 无需安装,解压即用 可使用较多Linux命令,如 ...

  8. Windows系统中安装Python模块pip numpy matplotlib

    Windows系统中安装Python模块pip numpy matplotlib  [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/deta ...

  9. 在Windows系统中配置Google AddressSanitizer

    Google AddressSanitizer简介 AddressSanitizer (ASan) 是 C 和 C++ 的内存错误检测软件,它可以检测: 释放指针后继续使用 堆缓冲区溢出 栈缓冲区溢出 ...

  10. mysql 重装,Windows系统中完全卸载MySQL数据库实现重装mysql

    一.在控制面板,卸载MySQL的所有组件 控制面板-->所有控制面板项-->程序和功能,卸载所有和MySQL有关的程序 二.找到你的MysQL安装路径,看还有没有和MySQL有关的文件夹, ...

最新文章

  1. MySQL中有哪些锁?
  2. android studio gradle配置_Unity打包Android最全攻略(含完整流程及常见问题)
  3. 使用函数实现数据大小端转换
  4. T-SQL | 逻辑查询处理内幕学习
  5. GitHub.com上的那些东西你都知道什么意思吗?
  6. nginx 监听同一端口
  7. 由一个activity跳转到另一个activity
  8. Bailian2806 公共子序列【最长公共子序列+DP】
  9. 广播的接收与U盘广播
  10. JavaScript:自封装函数利用内置Date对象输出格式化“YYYY-MM-dd hh:mm:ss”时间
  11. “领跑者”计划倒逼光伏产业升级效果显现
  12. Centos下PHP5升级PHP7
  13. RH850/F1x的PWM-Diag功能分析
  14. 使用VsCode搭建Vue开发环境
  15. 【弃】Selenium官方文档中文版
  16. DSP 增强型脉宽调制ePWM
  17. ACCEPTED: waiting for AM container to be allocated, launched and register with RM.
  18. 视频在H5页面在微信浏览器不能自动播放问题
  19. mysql桦仔_带您理解SQLSERVER是如何执行一个查询的
  20. 备受全球瞩目的「USDT集体索赔案」来龙去脉|全文译本

热门文章

  1. Linux cpumask分析
  2. navicat连接阿里云数据库
  3. notepad++更换皮肤
  4. peoplesoft 更新表接口程序
  5. 批量替换Excel超级链接
  6. 60级神圣系圣骑心得(转)
  7. Vue上传图片裁剪预览插件vue-img-cutter的使用
  8. 十一则:程序员冷“笑话”据说只有真正的程序员才看得懂
  9. VirtualBox安装CentOS5.5 Insert Guest Additions CD image…(HOST+D)
  10. c++中调用c编写的动态链接库出现undefined reference to `xxx‘的解决方法