Как сохранить Z-порядок окон моего приложения Windows Forms? - PullRequest
0 голосов
/ 23 апреля 2019

У меня есть приложение, которое открывается во время выполнения 8 окон, каждое из которых представляет график.
Как мне сохранить Z-порядок 8 окон относительно друг друга?

Мои коллеги-сотрудники используютЭто приложение и растягивать, и перемещаться по окнам.
Когда они кладут одно окно поверх другого, я хочу восстановить этот Z-порядок при загрузке.

Сохранение местоположения, размеров (w & h) и WindowState прекрасно работает.

Я пытался GetChildIndex(), но во время сборки я получаю:

GetChildIndex () не объявлен "

1 Ответ

3 голосов
/ 23 апреля 2019

Метод, использующий функцию GetWindow для определения Z-порядка активных (открытых) форм приложения и последующего восстановления того же порядка при перезапуске приложения.

(Для простоты порядок форм сохраняется в файле в пути к приложению. Необходимо адаптировать его к требованиям приложения (текущий формат хранения))

Когда приложение является основнымФорма закрывается (событие Form.FormClosing), текущий Z-порядок открытых форм сохраняется в файле.
Примечание : Я полагаю, что режим завершения работы приложения установлен на При запуске форма закрывается .

Предыдущий Z-порядок форм восстанавливается, когда будет отображаться основная форма (событие Form.Shown).Создается экземпляр каждой из форм, которые были открыты в момент последнего закрытия приложения, и отображается каждая форма с сохранением 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Метод - это дескриптор окна, с которого начинается перечисление.Это может быть ваша основная форма (начальная форма) или одна из форм, которые вы открываете затем.
Если hwndFirst является вашей основной формой, вы хотите исключить ее из перечисления, передавая False как includeFirst параметр (1) .Обратное, если hwndFirst является одной из дочерних форм.

(1) Если этот метод вызывается из главной формы, мы не хотим его снова открывать .

Затем метод GetWindowZOrder вызывает GetWindow, чтобы получить следующий дескриптор Window в текущем Z-порядке, проверяет, принадлежит ли этот дескриптор приложению, и, если он есть, добавляет его в словарь.
Затем возвращается 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...