C# MDI项目:如何按子窗体当前显示顺序遍历子窗体?
按MDI子窗体当前显示顺序遍历的解决方案
我懂你遇到的这个问题——MDI父窗体自带的MdiChildren属性是按子窗体的创建顺序返回的,不管你怎么切换窗口的显示层级,这个顺序都不会跟着变。要按当前的显示Z顺序(也就是最上层/最下层的先后顺序)遍历子窗体,我们可以借助Win32 API来获取系统维护的真实窗口层级顺序。
步骤1:导入Win32 API函数
首先在你的父窗体(Form1)中添加以下代码,用来调用系统API获取窗口的Z顺序:
using System.Runtime.InteropServices; using System.Collections.Generic; // 导入获取窗口句柄的系统API [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); // 定义API需要的常量 private const uint GW_HWNDFIRST = 0; private const uint GW_HWNDNEXT = 1;
步骤2:编写获取Z顺序子窗体的方法
接下来写一个方法,用来按当前显示顺序收集所有MDI子窗体:
private List<Form> GetMdiChildrenInZOrder() { List<Form> orderedForms = new List<Form>(); // 从当前MDI父窗体的第一个子窗口(最顶层)开始遍历 IntPtr currentWnd = GetWindow(this.Handle, GW_HWNDFIRST); while (currentWnd != IntPtr.Zero) { // 将窗口句柄转换为Form对象 Form childForm = Control.FromHandle(currentWnd) as Form; // 确认是当前父窗体的MDI子窗体 if (childForm != null && childForm.MdiParent == this) { orderedForms.Add(childForm); } // 获取下一个层级的窗口 currentWnd = GetWindow(currentWnd, GW_HWNDNEXT); } return orderedForms; }
这个方法默认会从最顶层的子窗体开始,依次收集到最底层的子窗体。如果你需要反过来(从最底层到最顶层),可以把GW_HWNDFIRST换成GW_HWNDLAST,GW_HWNDNEXT换成GW_HWNDPREV即可。
步骤3:使用方法遍历子窗体
现在你可以用这个方法来按当前显示顺序遍历子窗体了,比如:
// 遍历按Z顺序排列的子窗体 foreach (Form child in GetMdiChildrenInZOrder()) { // 这里写你的处理逻辑,比如输出窗体标题 Console.WriteLine($"当前显示顺序的窗体:{child.Text}"); }
原理说明
Windows系统会维护一个窗口Z顺序的层级列表,GetWindow函数可以按照这个层级逐个获取窗口句柄。我们通过筛选出属于当前MDI父窗体的子窗体,就能得到真实的显示顺序列表,而不是固定的创建顺序。
内容的提问来源于stack exchange,提问作者Manuel Paz
相关产品推荐
相关产品推荐

