码农的自我修养 - 什么是Z-Order

Z-Order是Windows操作系统中管理窗口显示顺序的概念,表示窗口在屏幕上的前后层次。窗口按照Z-Order堆叠,顶层窗口遮挡底层窗口。窗口间存在父/子、拥有/被拥有和兄弟关系,形成了窗口层次结构。子窗口生成时默认位于父窗口的子窗口链尾部,以确保后生成的窗口显示在前面。Windows系统维护一个Z-Order表,用于决定窗口的绘制和更新顺序。

Z-Order是计算机的界面显示领域,窗口管理相关的一个术语。

一般是指在显示屏上,存在多个窗口,为了管理多个二维平面窗口,而增加了一个维度,来控制窗口的显示顺序。

Z-Order. The z-order of a window indicates the window's position in a stack of overlapping windows. This window stack is oriented along an imaginary axis, the z-axis, extending outward from the screen. The window at the top of the z-order overlaps all other windows.

Z-顺序。窗口的Z轴顺序表示该窗口在堆叠窗口列表中的位置。这个窗口堆叠的方向是沿着一条假想轴,即Z轴,从屏幕向外延伸。处于Z-order顶端的窗口会覆盖所有其他窗口。

比如有4个窗口,放在一个列表中,则index为0的窗口处于底端,先描画,然后才是后面的窗口,index为3的窗口就处于最顶端,最有一个描画,所以它描画后会覆盖其他窗口。

关于窗口应用,大家联想到的最多的,自然是Windows操作系统,这个图形操作系统,就是基于窗口的。下面我们来解释一下Windows操作系统的窗口系统。

Windows操作系统的窗口系统

窗口(Window)是Windows操作系统中用来显示信息和接受用户输入的基本单元(Block)。负责管理窗口相关功能的操作系统部件被称为窗口管理器(Window Manager)。Windows操作系统初始化时会生成一个窗口,叫做桌面窗口(Desktop Window),调用GetDesktopWindow函数可获得它的句柄。桌面窗口会覆盖整个屏幕,所有其它窗口都在其之上显示。

Windows中有3种类型的窗口:层叠窗口(Overlapped Window)、弹出窗口(Popup Window)、子窗口(Child Window)。

弹出窗口通常用于对话框。

层叠窗口通常被用作应用程序的主窗口。

层叠窗口和弹出窗口统称为顶层窗口(top-level windows)。

窗口之间的关系:

1,父/子(parent-child)关系:

子窗口的位置坐标都是相对于父窗口客户区的左上角(upper-left corner)计算的。子窗口会把它的notify消息发送到父窗口。父/子关系对窗口可见性的影响为:子窗口只能显示在它的父窗口的客户区中,超出父窗口客户区的部分将被裁减掉;父窗口被隐藏时,它的所有子窗口也被隐藏;最小化父窗口不影响子窗口的可见状态,子窗口会随着父窗口被最小化,但是它的WS_VISIBLE属性不变。父窗口被销毁的时候,它的所有子窗口都会被销毁。

桌面窗口与所有顶层窗口是父/子关系。

2,拥有/被拥有(owner-owned)关系

顶层窗口之间可以存在owner-owned关系。owner-owned关系对窗口可见性的影响为:owned窗口永远显示在owner窗口的前面;当owner窗口最小化的时候,它所拥有的窗口都会被隐藏;隐藏owner窗口不影响它所拥有的窗口的可见状态。

当owner窗口被销毁的时候,它所拥有的窗口都会被销毁。

3,兄弟(siblings)关系:同一个父窗口的所有直属子窗口之间是兄弟关系,也就是相互平等,没有主从之分。窗口管理器用链表(linked list)来管理每个父窗口的直属子窗口,这个链表叫子窗口链(child window list)。

窗口层次结构(Window Hierarchy)

窗口管理器以一个树状结构组织和管理系统内所有窗口,如图:

树形结构的根是桌面窗口,其下属第一层窗口是顶层窗口(层叠窗口+弹出窗口)。顶层窗口之下的所有层里只包含子窗口。从桌面窗口出发,通过一系列相关API函数的调用,可以遍历系统中的所有窗口。

Z-Order

窗口在子窗口链中的先后顺序也就是窗口在屏幕上显示时的前后顺序,在子窗口链里位置越靠前的窗口显示时也越靠前,这个前后顺序就是Z-Order。Z-Order在前的顶层窗口会遮挡Z-Order在后的顶层窗口;屏幕上的一块区域需要刷新(Update)时,同一个子窗口链中Z-Order在前的窗口先刷新,Z-Order在后的窗口后刷新。有父/子关系的窗口是父窗口先刷新,子窗口后刷新。

顶层窗口生成时,窗口管理器会把它加到(桌面窗口的)子窗口链的最前面,也就是Z-Order的最前面,使整个窗口都可见。子窗口的Z-Order要高于它的父窗口,因此会显示在父窗口前面,但任何一个子窗口的Z-Order都不会超过其父窗口的Z-Order更靠前的兄弟窗口。

子窗口生成时,与顶层窗口的情况有所不同,窗口管理器会把它加到父窗口的子窗口链的最后面。这似乎是反直觉的,为什么会这样呢?窗口管理器这样做是有原因的,其主要目的是让后生成的窗口能显示在前面(兄弟窗口间有重叠的情况下),并且子窗口间的Tab-Order与窗口的生成顺序相同,这样的效果才是符合直觉的。

子窗口大多数情况下都共用其父窗口的显示DC(Device Context),所以在刷新时是可以在其兄弟窗口的客户区上绘画(draw)的,这就造成了Z-Order在后的子窗口因为刷新顺序在后,绘画能覆盖Z-Order在前的窗口,显示效果反而在前的现象,如下图所示:

系统在一个单一的表中维护z-order 。根据窗口是不是顶级窗口,父窗口,子窗口,系统把他们添加到z-order中。顶级窗口将会堆叠在所有非顶级窗口之上,不管它是否是活动窗口或者是前台窗口。

在z-order中的所有的顶级窗口都会在任何非顶级窗口之前显现。

当一个应用程序创建一个窗口时,系统会把它放置在同一类窗口的z-order的顶部。

参考:

窗口之间的主从关系与Z-Order - 中华一猿 - 博客园https://www.cnblogs.com/dhatbj/p/3288152.html

### 不使用栈实现判断字符串是否为可能的出栈序列 在不借助显式的栈结构的情况下,可以通过双指针技术以及数组模拟的方式完成这一任务。核心思想是利用两个指针分别指向原字符串和目标字符串的不同部分,并动态调整它们之间的关系以验证合法性。 #### 方法解析 定义两个指针 `pushPtr` 和 `popPtr` 分别表示当前正在处理的入栈字符位置与期望匹配的目标出栈字符位置。同时维护一个虚拟栈的状态,即记录哪些元素已经进入过栈但尚未被弹出。这一步可通过布尔型数组或者整数计数器来代替传统意义上的栈存储方式[^3]。 对于每次迭代: - 如果发现某个待入栈的新字符正好满足当前目标需求,则直接前进至下一组对应项; - 否则尝试查找之前已存入却还未移除的部分是否存在符合条件者——一旦找到便更新状态继续推进流程直至结束条件达成为止。 #### 实现代码 下面给出基于上述原理的具体 C++ 实现版本: ```cpp #include <iostream> #include <vector> using namespace std; // Function to check if the given sequence is valid pop order of elements pushed into a stack. bool IsPopOrder(const string& pushStr, const string& popStr){ int n = pushStr.length(); // Initialize two pointers and an array indicating whether each element has been popped or not. int pushIdx = 0; int popIdx = 0; vector<bool> inStack(n, false); for (; popIdx < n; ){ bool foundInStack = false; // Try finding match from already pushed but unpopped items first. for (int j=n-1 ;j>=0 && !foundInStack;j--){ if(!inStack[j]){ continue ; } if(popStr[popIdx]==pushStr[j]){ inStack[j]=false;// Mark as out-of-stack now since it's matched here. foundInStack=true; break; } } if(foundInStack){ popIdx++; continue; } // If no matching item within current 'virtual' stack content then try pushing next one onto virtual stack. if(pushIdx<n&&popStr[popIdx]!=pushStr[pushIdx]){ inStack[pushIdx++]=true; }else{ if(pushIdx<n){ pushIdx++; // Move forward after successful direct comparison without needing intermediate storage simulation anymore. popIdx++; }else{ return false; } } } return true; } int main(){ string originalString="abc"; vector<string> testCases={"abc","bca","cab"}; for(auto testCase:testCases){ cout<<testCase<<" -> "<<(IsPopOrder(originalString , testCase )?"YES":"NO")<<endl; } return 0; } ``` #### 关键点解释 1. 使用了一个额外的空间 `inStack[]` 来标记哪些元素已经在所谓的“虚拟栈”里,从而避免了真实创建栈对象带来的开销。 2. 双重循环控制逻辑确保即使没有实际物理上的堆叠也能正确反映相对次序约束下的可行性判定标准[^4]. --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜流冰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值