winforms 如何保持Window窗体应用的窗口的Z顺序?

hivapdat  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(212)

我有一个应用程序,在运行时打开8个窗口,每个图形。
如何保持8个窗口相对于彼此的Z顺序?
我的同事们使用这个应用程序,在Windows周围伸展和移动。
当他们把一个窗口放在另一个窗口上时,我想在 Boot 时恢复这个Z顺序。
持久的位置,尺寸(w & h),和WindowState的工作很好。
我尝试了GetChildIndex(),但在构建时得到:
GetChildIndex()未声明”

i86rm4rw

i86rm4rw1#

使用GetWindow函数确定应用程序活动(打开)窗体的Z顺序,然后在重新启动应用程序时恢复相同顺序的方法。
(For简单性,表单的顺序保存到应用程序路径中的文件。您需要根据应用程序要求(当前存储格式)对其进行调整)
当应用程序的主窗体关闭时(Form.FormClosing事件),打开的窗体的当前Z顺序存储到文件中。

注意:我假设应用程序的关闭模式设置为 * 当启动窗体关闭时 *。

当要显示主窗体时(Form.Shown事件),将恢复窗体以前的Z顺序。将创建上次关闭应用程序时打开的每个窗体的示例,并显示每个窗体,同时保留Z顺序。
每个示例都是使用Activator.CreateInstance方法创建的,传递从存储(这里是文件)中检索到的Form的Name。

:到目前为止,尚未保存表单的位置。您说过您已经在使用此位置。如果需要,可以轻松地修改此处提供的代码,以存储这些衡量标准。

Imports System.IO
Imports System.Reflection

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    Dim zOrder As Dictionary(Of Integer, String) = GetWindowZOrder(Me.Handle, False)
    If zOrder Is Nothing Then return
    Using sw As New StreamWriter("FormsOrder.txt")
        For Each form In zOrder
            sw.WriteLine($"{form.Key},{form.Value}")
        Next
    End Using
End Sub

Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    If File.Exists("FormsOrder.txt") Then
        Dim orderList As String() = File.ReadAllLines("FormsOrder.txt").Reverse().ToArray()
        Dim appNameSpace = Assembly.GetExecutingAssembly().GetName().Name
        For Each formOrder As String In orderList
            Dim formName As String = formOrder.Split(","c)(1)
            Dim form = CType(Activator.CreateInstance(Type.GetType($"{appNameSpace}.{formName}")), Form)
            form.Show()
        Next
    End If
End Sub

声明和GetWindow帮助器方法(GetWindowZOrder):
GetWindowZOrder方法的**hwndFirst参数是枚举开始的Window的句柄。它可以是主窗体(起始窗体)或下一个打开的窗体之一。
如果hwndFirst是您的MainForm,您要将它从枚举中排除,将False作为
includeFirst**参数(1)传递。如果hwndFirst是 * 子 * Form之一,则相反。
(1)如果从主窗体调用此方法,则不希望再次打开它。
然后,GetWindowZOrder方法调用GetWindow以获取当前Z顺序中的下一个窗口句柄,验证该句柄是否属于应用程序,如果是,则将其添加到字典中。
然后返回Dictionary(Of Integer, String),其中Key表示订单,Value表示窗体的名称。
此代码可以是模块的一部分。

Imports System.Runtime.InteropServices

Public Function GetWindowZOrder(hwndFirst As IntPtr, includeFirst As Boolean) As Dictionary(Of Integer, String)
    Dim zOrder As New Dictionary(Of Integer, String)()
    Dim form As Form = GetOpenedForm(hwndFirst)
    If form Is Nothing Then Return Nothing

    Dim order As Integer = 0
    If includeFirst Then zOrder.Add(order, form.Name)

    Dim hwndNext As IntPtr = hwndFirst
    While True
        hwndNext = GetWindow(hwndNext, GetWindowRel.GW_HWNDNEXT)
        If hwndNext = IntPtr.Zero Then Exit While
        form = GetOpenedForm(hwndNext)
        If (form IsNot Nothing) Then
            order += 1
            zOrder.Add(order, form.Name)
        End If
    End While
    Return zOrder
End Function

Private Function GetOpenedForm(hwnd As IntPtr) As Form
    Return Application.OpenForms.OfType(Of Form)().FirstOrDefault(Function(f) f.Handle = hwnd)
End Function

<DllImport("user32.dll", SetLastError:=True)>
Private Function GetWindow(hWnd As IntPtr, uCmd As GetWindowRel) As IntPtr
End Function

Private Enum GetWindowRel As UInteger
    GW_HWNDFIRST = 0
    GW_HWNDLAST = 1
    GW_HWNDNEXT = 2
    GW_HWNDPREV = 3
    GW_OWNER = 4
    GW_CHILD = 5
    GW_ENABLEDPOPUP = 6
End Enum

相关问题