我有一个运行时打开8个窗口的应用,每个窗口都是图形。
如何保持8个窗口相对于彼此的Z顺序?
我的同事们使用此应用程序在窗户上伸展和移动。
当他们将一个窗口放在另一个窗口上时,我想在启动时恢复此Z顺序。
保持位置,尺寸(w&h)和WindowState
的效果很好。
我尝试了GetChildIndex()
,但是在构建时我得到了:
未声明GetChildIndex()”
答案 0 :(得分:3)
一种利用GetWindow函数确定应用程序(打开的)窗体的Z顺序,然后在重新启动应用程序时恢复相同顺序的方法。
(为简单起见,表单的订单被保存到应用程序路径中的文件中。您需要使其适应应用程序要求(当前存储格式))
当应用程序的主窗体关闭时(Form.FormClosing
事件),打开的窗体的当前Z顺序将存储到文件中。
注意:我假设应用程序的关机模式设置为启动表单关闭时。
将要显示“主表单”(Form.Shown
事件)时,将恢复先前的表单Z顺序。创建上次关闭应用程序时打开的每个Forms的实例,并显示每个Form,并保留Z顺序。
使用Activator.CreateInstance方法创建每个实例,并传递从存储中检索到的表单的名称(此处为文件)。
注意:截至目前,表单的位置尚未保存。您说您已经有这项工作了。如果需要,此处提供的代码可以轻松调整为也存储这些度量。
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
):
hwndFirst
方法的 GetWindowZOrder
参数是开始枚举的Window的句柄。它可以是您的主表单(开始表单),也可以是您接下来打开的表单之一。
如果hwndFirst
是您的MainForm,则要将其从枚举中排除,将False
作为 includeFirst
参数(1) 。如果hwndFirst
是 child 形式之一,则相反。
(1)如果从主窗体调用了此方法,我们不想再次打开它。
然后,GetWindowZOrder
方法调用GetWindow
以获取当前Z顺序中的下一个Window句柄,验证该句柄是否属于应用程序,如果存在,则将其添加到Dictionary中。
然后,它返回一个Dictionary(Of Integer, String)
,其中Key
代表顺序,Value
代表表单的名称。
此代码可以是模块的一部分。
Imports System.Runtime.InteropServices
<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
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 Not (form Is 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