PureBasic

Руководство - Управление множеством различных окон

В предыдущей статье мы исследовали один из способов, которым программа может поддерживать несколько экземпляров одного типа окна. В этом мы продолжим эту концепцию - разрабатываем программу, которая может поддерживать несколько экземпляров нескольких разных типов окон, в данном случае трёх:
- Окно 'Button' – содержит отображаемый список, и две кнопки с надписями "Добавить" и "Удалить". При нажатии кнопки "Добавить" случайное целое число, которое даёт random добавляется в отображаемый список, при нажатии кнопки "Удалить" выделенная в данный момент запись в отображаемом списке удаляется.
- Окно 'Date' – содержит отображаемый список и две кнопки аналогично окну 'Button', но также содержит Гаджет календаря, макет окна изменен для размещения этого дополнительного элемента управления. При нажатии кнопки "Добавить", в отображаемый список добавляется Дата, выделенная в данный момент в календаре.
- Окно 'Track' – содержит два ползунка со значением от 0 до 100, и строковый Гаджет. Когда ползунки перемещаются, Гаджет строки показывает значение второго ползунка, вычтенное из значения первого.
Каждое окно содержит строку меню с пунктами для создания нового экземпляра любого из трех поддерживаемых типов окон или закрытия текущего окна.

Что нужно знать об этой программе:

В разделе 'Структуры' определены 4 структуры. Первая BASEWINDOW, определяет значение WindowClass и значение Menu - эти значения являются общими для каждого типа окна.

Остальные структуры расширяют структуру BASEWINDOW со значениями для каждого из уникальных элементов управления, которые им требуются и которые не предусмотрены структурой BASEWINDOW.

В разделе Переменные заметим, что снова создается хеш-карта с именем ActiveWindows, однако на этот раз она имеет целочисленный тип, она не использует ни одну из определенных структур. Для этого есть хорошая причина: нам нужно хранить три разных типа структуры, чтобы эта программа работала - и мы не можем сделать это на одной хеш-карте.

Также обратите внимание, что *EventGadgets определяется с помощью структуры BASEWINDOW.

Теперь посмотрим на процедуру CreateButtonWindow. Как и раньше, мы используем #PB_Any для создания окна и всех Гаджетов.

Однако на этот раз результаты не сохраняются непосредственно в хеш-карте ActiveWindows. Вместо этого мы используем функцию AllocateMemory для выделения памяти для структуры BUTTONWINDOW, затем мы сохраняем указатель на эту выделенную память в хеш-карте ActiveWindows. Так мы обходим проблему неспособности хранить все три разные структуры в одной хеш-карте.

Мы также устанавливаем значение WindowClass в структуре в #WindowClassButton, чтобы указать, какой тип окна и соответствующий ему тип структуры был создан, позже эта информация нам понадобится.

На этот раз есть еще две процедуры CreateWindow - по одной для каждого класса других типов окон. Они работают так же, как описано выше, но отличаются набором Гаджетов, и устанавливают другое значение в WindowClass.

Так же мы создадим процедуры DestroyWindow и ResizeWindow для обслуживания этих функций.

Дополнительно мы создадим процедуру - EventsButtonWindow. Эта процедура знает, что делать, когда какой-либо из Гаджетов в окне активируется пользователем. Подобные процедуры предусмотрены и для других типов окон.

Во всех этих процедурах мы используем хеш-карту ActiveWindows для получения указателя на выделенную память. Затем мы можем использовать этот указатель для получения ссылок на фактические элементы управления, с которыми нам нужно работать в каждой из этих процедур:

*ThisData = ActiveWindows(ThisKey)
*ThisData\ListView ...

Каждая процедура знает только, как обращаться с одним типом окна, поэтому перед началом работы мы проверяем значение WindowClass, чтобы убедиться, что в качестве аргумента было представлено окно корректного типа:

If *ThisData\WindowClass <> #WindowClassButton

Цикл событий тоже немного отличается. Для каждого типа события есть такое определение:

; Используйте *EventGadgets \ WindowClass для вызова корректной процедуры изменения размера окна.
Select *EventGadgets\WindowClass ...

Хотя выделения памяти, фактически созданные процедурами CreateWindow, будут иметь тип BUTTONWINDOW, DATEWINDOW или TRACKWINDOW, мы можем использовать *EventGadgets, потому что он определен как тип BASEWINDOW, а BASEWINDOW является родительской структурой для других структур.

Если мы не пытаемся изменить какие-либо сохраненные значения с помощью *EventGadgets - все должно быть хорошо.

Наконец, мы посылаем зарегистрированные значения события в EventWindow, EventGadget, EventType, прямо в процедуры событий и позволяем им беспокоиться о том, чтобы выполнить задание.

;- Константы
#DateFormat = "%dd/%mm/%yyyy"

;- Перечисления
Enumeration
    #WindowClassButton = 1
    #WindowClassDate
    #WindowClassTrack
EndEnumeration

; Команды меню будут одинаковыми во всех окнах.
Enumeration
    #MenuNewButton
    #MenuNewDate
    #MenuNewTrack
    #MenuClose
EndEnumeration

;- Структуры
Structure BASEWINDOW
    WindowClass.i
    Menu.i
EndStructure

Structure BUTTONWINDOW Extends BASEWINDOW
    ListView.i
    AddButton.i
    RemoveButton.i
EndStructure

Structure DATEWINDOW Extends BASEWINDOW
    Calendar.i
    AddButton.i
    RemoveButton.i
    ListView.i
EndStructure

Structure TRACKWINDOW Extends BASEWINDOW
    TrackBar1.i
    TrackBar2.i
    Label.i
    Difference.i
EndStructure

;- Переменные
; Эта хеш-карта будет отслеживать все активные окна, как и раньше, однако, поскольку структура для каждого класса
; окон различается, мы будем хранить указатели на структуры на хеш-карте, а не на ссылки на Гаджеты напрямую.
NewMap ActiveWindows.i()

; Эти значения будут использоваться для придания новым окнам уникальной метки.
Define.i Buttons, Dates, Tracks

; Переменные событий.
; Обратите внимание на тип *EventGadgets.
Define.i Event, EventWindow, EventGadget, EventType, EventMenu, EventQuit
Define.s EventWindowKey
Define *EventGadgets.BASEWINDOW

;- Окно 'Button'
Procedure.i CreateButtonWindow()
    ; Создает новое окно Button и добавляет его в хеш-карту отслеживания,
    ; выделяет память для ссылок на Гаджеты, создает Гаджеты
    ; и сохраняет эти ссылки в памяти структур.
    Shared Buttons, ActiveWindows()
    Protected *ThisData.BUTTONWINDOW
    Protected.i ThisWindow
    Protected.s ThisKey, ThisTitle

    ; Устанавливает заголовок окна.
    Buttons + 1
    ThisTitle = "Button Window " + StrU(Buttons)

    ; Открывает окно.
    ThisWindow = OpenWindow(#PB_Any, 30, 30, 225, 300, ThisTitle, #PB_Window_SystemMenu - #PB_Window_SizeGadget - #PB_Window_MinimizeGadget - #PB_Window_TitleBar)

    ; Проверяет работу команды OpenWindow.
    If ThisWindow
        ; Установка минимальных размеров окна.
        WindowBounds(ThisWindow, 220, 100, #PB_Ignore, #PB_Ignore)

        ; Преобразует ссылку на окно в строку, которая будет использоваться в качестве значения ключа хеш-карты.
        ThisKey = StrU(ThisWindow)

        ; Выделение памяти для хранения ссылок на Гаджеты.
        *ThisData = AllocateMemory(SizeOf(BUTTONWINDOW))
    EndIf

    ; Убеждаемся что память выделилась успешно.
    If *ThisData
        ; Сохранить ссылку на окно и значение указателя памяти в хеш-карте.
        ActiveWindows(ThisKey) = *ThisData

        ; Установить класс окна.
        *ThisData\WindowClass = #WindowClassButton

        ; Создать панель меню.
        *ThisData\Menu = CreateMenu(#PB_Any, WindowID(ThisWindow))

        ; Если создание меню удалось, создать пункты меню.
        If *ThisData\Menu
            MenuTitle("Window")
            MenuItem(#MenuNewButton, "New Button Window")
            MenuItem(#MenuNewDate, "New Date Window")
            MenuItem(#MenuNewTrack, "New Track Window")
            MenuItem(#MenuClose, "Close Window")
        EndIf

        ; Создать Гаджеты окон.
        *ThisData\ListView = ListViewGadget(#PB_Any, 10, 10, 200, 225)
        *ThisData\AddButton = ButtonGadget(#PB_Any, 15, 245, 90, 30, "Add")
        *ThisData\RemoveButton = ButtonGadget(#PB_Any, 115, 245, 90, 30, "Remove")
    Else
        ; Не удалось выделить память.
        CloseWindow(ThisWindow)
    EndIf

    ; Установить возвращаемое значение.
    If ThisWindow > 0 And *ThisData > 0
        ; Вернуть ссылку на новое окно.
        ProcedureReturn ThisWindow
    Else
        ; Вернуть 0.
        ProcedureReturn 0
    EndIf
EndProcedure

Procedure.i DestroyButtonWindow(Window.i)
    ; Удалить окно с хеш-карты ActiveWindows, освободить выделенную память,
    ; закрыть окно и установить флаг выхода, если это необходимо.
    Shared EventQuit, ActiveWindows()
    Protected *ThisData.BUTTONWINDOW
    Protected.s ThisKey

    ; Преобразует ссылку на окно в строку
    ThisKey = StrU(Window)

    ; Получить ссылку на указатель структуры.
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassButton
        ProcedureReturn #False
    EndIf

    ; Освободить выделенную память.
    FreeMemory(*ThisData)

    ; Удалить запись хеш-карты.
    DeleteMapElement(ActiveWindows(), ThisKey)

    ; Закрыть окно.
    CloseWindow(Window)

    ; Проверить, есть ли еще открытые окна.
    If MapSize(ActiveWindows()) = 0
        EventQuit = #True
    EndIf

    ; Установить успешное возвращаемое значение.
    ProcedureReturn #True
EndProcedure

Procedure.i ResizeButtonWindow(Window.i)
    ; Изменить размеры дочерних Гаджетов в окне.
    Shared ActiveWindows()
    Protected *ThisData.BUTTONWINDOW
    Protected.i X, Y, W, H
    Protected.s ThisKey

    ; Получить ссылку на указатель структуры.
    ThisKey = StrU(Window)
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassButton
        ProcedureReturn #False
    EndIf

    ; Изменение размера списка.
    W = WindowWidth(Window) - 25
    H = WindowHeight(Window) - 85
    ResizeGadget(*ThisData\ListView, #PB_Ignore, #PB_Ignore, W, H)

    ; Кнопки центрирования.
    X = WindowWidth(Window)/2 - 95
    Y = WindowHeight(Window) - 65
    ResizeGadget(*ThisData\AddButton, X, Y, #PB_Ignore, #PB_Ignore)

    X = WindowWidth(Window)/2 + 5
    ResizeGadget(*ThisData\RemoveButton, X, Y, #PB_Ignore, #PB_Ignore)

    ProcedureReturn #True
EndProcedure

Procedure.i EventsButtonWindow(Window, Gadget, Type)
    ; Обработка событий для окна 'button'.
    Shared Buttons, ActiveWindows()
    Protected *ThisData.BUTTONWINDOW
    Protected.i NewValue, Index
    Protected.s ThisKey

    ; Преобразует ссылку на окно в строку.
    ThisKey = StrU(Window)

    ; Получить ссылку на указатель структуры.
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassButton
        ProcedureReturn #False
    EndIf

    Select Gadget
        Case *ThisData\AddButton
            NewValue = Random(2147483647)
            AddGadgetItem(*ThisData\ListView, -1, StrU(NewValue))

        Case *ThisData\RemoveButton
            Index = GetGadgetState(*ThisData\ListView)
            If Index >= 0 And Index <= CountGadgetItems(*ThisData\ListView)
                RemoveGadgetItem(*ThisData\ListView, Index)
            EndIf

        Case *ThisData\ListView
            ; Ничего не делать.
    EndSelect
EndProcedure

;- Окно 'Date'
Procedure.i CreateDateWindow()
    ; Создает новое окно 'Date' и добавляет его в хеш-карту отслеживания,
    ; выделяет память для ссылок на Гаджеты, создает Гаджеты
    ; и сохраняет эти ссылки в памяти структуры.
    Shared Dates, ActiveWindows()
    Protected *ThisData.DATEWINDOW
    Protected.i ThisWindow
    Protected.s ThisKey, ThisTitle

    Dates + 1
    ThisTitle = "Date Window " + StrU(Dates)
    ThisWindow = OpenWindow(#PB_Any, 30, 30, 310, 420, ThisTitle , #PB_Window_SystemMenu - #PB_Window_SizeGadget - #PB_Window_MinimizeGadget - #PB_Window_TitleBar)

    ; Убедитесь, что команда OpenWindow открыла окно.
    If ThisWindow
        ; Установить минимальные размеры окна.
        WindowBounds(ThisWindow, 310, 245, #PB_Ignore, #PB_Ignore)

        ; Преобразуйте ссылку окна в строку, которая будет использоваться в качестве значения ключа хеш-карты.
        ThisKey = StrU(ThisWindow)

        ; Выделите память для хранения ссылок на Гаджеты.
        *ThisData = AllocateMemory(SizeOf(DATEWINDOW))
    EndIf

    ; Убедимся, что память выделилась корректно.
    If *ThisData
        ; Сохранить  ссылки на окна и значения указателя памяти в хеш-карте.
        ActiveWindows(ThisKey) = *ThisData

        ; Установить класс окна.
        *ThisData\WindowClass = #WindowClassDate

        ; Создать панель меню.
        *ThisData\Menu = CreateMenu(#PB_Any, WindowID(ThisWindow))

        ; Если создание меню удалось, создать пункты меню.
        If *ThisData\Menu
            MenuTitle("Window")
            MenuItem(#MenuNewButton, "New Button Window")
            MenuItem(#MenuNewDate, "New Date Window")
            MenuItem(#MenuNewTrack, "New Track Window")
            MenuItem(#MenuClose, "Close Window")
        EndIf

        ; Создать Гаджеты окон.
        *ThisData\Calendar = CalendarGadget(#PB_Any, 10, 10, 182, 162)
        *ThisData\AddButton = ButtonGadget(#PB_Any, 210, 10, 90, 30, "Add")
        *ThisData\RemoveButton = ButtonGadget(#PB_Any, 210, 45, 90, 30, "Remove")
        *ThisData\ListView = ListViewGadget(#PB_Any, 10, 187, 290, 200)
    Else
        ; Не удалось выделить память.
        CloseWindow(ThisWindow)
    EndIf

    ; Установить возвращаемое значение.
    If ThisWindow > 0 And *ThisData > 0
        ; Вернуть ссылку на новое окно.
        ProcedureReturn ThisWindow
    Else
        ; Вернуть 0
        ProcedureReturn 0
    EndIf

EndProcedure

Procedure.i DestroyDateWindow(Window.i)
    ; Удалите окно с хеш-карты ActiveWindows, освободите выделенную память,
    ; закройте окно и установите флаг выхода, если это необходимо.
    Shared EventQuit, ActiveWindows()
    Protected *ThisData.DATEWINDOW
    Protected.s ThisKey

    ; Преобразует ссылку на окно в строку.
    ThisKey = StrU(Window)

    ; Получить ссылку на указатель структуры.
    *ThisData = ActiveWindows(ThisKey)

    ; Проверить,  действительный ли указатель получен.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверьте, что это корректный тип окна, если не получается остановить, поскольку эта процедура не может уничтожить это окно.
    If *ThisData\WindowClass <> #WindowClassDate
        ProcedureReturn #False
    EndIf

    ; Освободить выделенную память.
    FreeMemory(*ThisData)

    ; Удалить запись хеш-карты.
    DeleteMapElement(ActiveWindows(), ThisKey)

    ; Закрыть окно.
    CloseWindow(Window)

    ; Проверить, есть ли еще открытые окна.
    If MapSize(ActiveWindows()) = 0
        EventQuit = #True
    EndIf

    ; Установить успешное возвращаемое значение.
    ProcedureReturn #True
EndProcedure

Procedure.i ResizeDateWindow(Window.i)
    ; Изменение размеров дочерних Гаджетов в окне.
    Shared ActiveWindows()
    Protected *ThisData.DATEWINDOW
    Protected.i X, Y, W, H
    Protected.s ThisKey

    ; Получить ссылку на указатель структуры.
    ThisKey = StrU(Window)
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassDate
        ProcedureReturn #False
    EndIf

    ; Изменение размера списка.
    W = WindowWidth(Window) - 20
    H = WindowHeight(Window) - 220
    ResizeGadget(*ThisData\ListView, #PB_Ignore, #PB_Ignore, W, H)

    ProcedureReturn #True
EndProcedure

Procedure.i EventsDateWindow(Window, Gadget, Type)
    ; Обработать события для окна 'Date'.
    Shared Buttons, ActiveWindows()
    Protected *ThisData.DATEWINDOW
    Protected.i NewValue, Index
    Protected.s ThisKey

    ; Преобразует ссылку на окно в строку.
    ThisKey = StrU(Window)

    ; Получить ссылку на указатель структуры.
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassDate
        ProcedureReturn #False
    EndIf

    Select Gadget
        Case *ThisData\AddButton
            NewValue = GetGadgetState(*ThisData\Calendar)
            AddGadgetItem(*ThisData\ListView, -1, FormatDate(#DateFormat, NewValue))

        Case *ThisData\RemoveButton
            Index = GetGadgetState(*ThisData\ListView)
            If Index >= 0 And Index <= CountGadgetItems(*ThisData\ListView)
                RemoveGadgetItem(*ThisData\ListView, Index)
            EndIf

        Case *ThisData\Calendar, *ThisData\ListView
            ; Ничего не делать.
    EndSelect
EndProcedure

;- Окно 'Track'
Procedure.i CreateTrackWindow()
    ; Создает новое окно 'Track' и добавляет его к хеш-карте отслеживания,
    ; выделяет память для ссылок на Гаджеты, создает Гаджеты
    ; и сохраняет эти ссылки в структуре памяти.
    Shared Tracks, ActiveWindows()
    Protected *ThisData.TRACKWINDOW
    Protected.i ThisWindow, ThisSum
    Protected.s ThisKey, ThisTitle

    Tracks + 1
    ThisTitle = "Track Bar Window " + StrU(Tracks)
    ThisWindow = OpenWindow(#PB_Any, 30, 30, 398, 130, ThisTitle, #PB_Window_SystemMenu - #PB_Window_SizeGadget - #PB_Window_MinimizeGadget - #PB_Window_TitleBar)

    ; Убедимся, что команда OpenWindow смогла открыть окно.
    If ThisWindow
        ; Установить минимальные размеры окна.
        WindowBounds(ThisWindow, 135, 130, #PB_Ignore, 130)

        ; Преобразовать ссылку окна в строку, которая будет использоваться в качестве значения ключа хеш-карты.
        ThisKey = StrU(ThisWindow)

        ; Выделите память для хранения ссылок на Гаджеты.
        *ThisData = AllocateMemory(SizeOf(TRACKWINDOW))
    EndIf

    ; Убедимся, что память выделилась корректно.
    If *ThisData
        ; Сохранить  ссылки на окна и значения указателя памяти в хеш-карте.
        ActiveWindows(ThisKey) = *ThisData

        ; Установить класс окна.
        *ThisData\WindowClass = #WindowClassTrack

        ; Создать панель меню.
        *ThisData\Menu = CreateMenu(#PB_Any, WindowID(ThisWindow))

        ; Если создание меню удалось, создать пункты меню.
        If *ThisData\Menu
            MenuTitle("Window")
            MenuItem(#MenuNewButton, "New Button Window")
            MenuItem(#MenuNewDate, "New Date Window")
            MenuItem(#MenuNewTrack, "New Track Window")
            MenuItem(#MenuClose, "Close Window")
        EndIf

        ; Создать Гаджеты окон.
        *ThisData\TrackBar1 = TrackBarGadget(#PB_Any, 10, 10, 375, 25, 0, 100, #PB_TrackBar_Ticks)
        *ThisData\TrackBar2 = TrackBarGadget(#PB_Any, 10, 40, 375, 25, 0, 100, #PB_TrackBar_Ticks)
        *ThisData\Label = TextGadget(#PB_Any, 10, 75, 80, 25, "Difference:")
        *ThisData\Difference = StringGadget(#PB_Any, 90, 75, 290, 25, "0", #PB_String_ReadOnly)
    Else
        ; Не удалось выделить память.
        CloseWindow(ThisWindow)
    EndIf

    ; Установить возвращаемое значение.
    If ThisWindow > 0 And *ThisData > 0
        ; Вернуть ссылку на новое окно.
        ProcedureReturn ThisWindow
    Else
        ; Вернуть 0
        ProcedureReturn 0
    EndIf
EndProcedure

Procedure.i DestroyTrackWindow(Window.i)
    ; Удалите окно с хеш-карты ActiveWindows, освободите выделенную память,
    ; закройте окно и установите флаг выхода, если это необходимо.
    Shared EventQuit, ActiveWindows()
    Protected *ThisData.DATEWINDOW
    Protected.s ThisKey

    ; Преобразует ссылку на окно в строку.
    ThisKey = StrU(Window)

    ; Получить ссылку на указатель структуры.
    *ThisData = ActiveWindows(ThisKey)

    ; Проверить, действительный ли указатель получен.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверьте, что это корректный тип окна, если не получается остановить, поскольку эта процедура не может уничтожить это окно.
    If *ThisData\WindowClass <> #WindowClassTrack
        ProcedureReturn #False
    EndIf

    ; Освободить выделенную память.
    FreeMemory(*ThisData)

    ; Удалить запись хеш-карты.
    DeleteMapElement(ActiveWindows(), ThisKey)

    ; Закрыть окно.
    CloseWindow(Window)

    ; Проверить, есть ли еще открытые окна.
    If MapSize(ActiveWindows()) = 0
        EventQuit = #True
    EndIf

    ; Установить успешное возвращаемое значение.
    ProcedureReturn #True
EndProcedure

Procedure.i ResizeTrackWindow(Window.i)
    ; Изменение размеров дочерних Гаджетов в окне.
    Shared ActiveWindows()
    Protected *ThisData.TRACKWINDOW
    Protected.i X, Y, W, H
    Protected.s ThisKey

    ; Получить ссылку на указатель структуры.
    ThisKey = StrU(Window)
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassTrack
        ProcedureReturn #False
    EndIf

    ; Изменение размера ползунков.
    W = WindowWidth(Window) - 20
    ResizeGadget(*ThisData\TrackBar1, #PB_Ignore, #PB_Ignore, W, #PB_Ignore)
    ResizeGadget(*ThisData\TrackBar2, #PB_Ignore, #PB_Ignore, W, #PB_Ignore)

    ; Изменение размера строки.
    W = WindowWidth(Window) - 110
    ResizeGadget(*ThisData\Difference, #PB_Ignore, #PB_Ignore, W, #PB_Ignore)

    ProcedureReturn #True
EndProcedure

Procedure.i EventsTrackWindow(Window, Gadget, Type)
    ; Обработка событий для окна 'Track'.
    Shared Buttons, ActiveWindows()
    Protected *ThisData.TRACKWINDOW
    Protected.i NewValue
    Protected.s ThisKey

    ; Преобразует ссылку на окно в строку.
    ThisKey = StrU(Window)

    ; Получить ссылку на указатель структуры.
    *ThisData = ActiveWindows(ThisKey)

    ; Убедиться, что был получен действительный указатель, если не получается остановить.
    If *ThisData = 0
        ProcedureReturn #False
    EndIf

    ; Проверить, что это корректный тип окна, если не получается остановить.
    If *ThisData\WindowClass <> #WindowClassTrack
        ProcedureReturn #False
    EndIf

    Select Gadget
        Case *ThisData\TrackBar1, *ThisData\TrackBar2
            NewValue = GetGadgetState(*ThisData\TrackBar1) - GetGadgetState(*ThisData\TrackBar2)
            SetGadgetText(*ThisData\Difference, Str(NewValue))

        Case *ThisData\Label, *ThisData\Difference
            ; Ничего не делать.
    EndSelect
EndProcedure

;- Главный код

; Создать первое окно.
EventWindow = CreateButtonWindow()
ResizeButtonWindow(EventWindow)

;- Цикл событий
Repeat
    Event = WaitWindowEvent()
    EventWindow = EventWindow()
    EventWindowKey = StrU(EventWindow)
    EventGadget = EventGadget()
    EventType = EventType()
    EventMenu = EventMenu()
    *EventGadgets = ActiveWindows(EventWindowKey)

    Select Event
        Case #PB_Event_Gadget
            ; Проверить, действительный ли указатель получен.
            If *EventGadgets > 0
                ; Используйте *EventGadgets \ WindowClass для отправки событий в корректную процедуру событий.
                Select *EventGadgets\WindowClass
                    Case #WindowClassButton
                        EventsButtonWindow(EventWindow, EventGadget, EventType)

                    Case #WindowClassDate
                        EventsDateWindow(EventWindow, EventGadget, EventType)

                    Case #WindowClassTrack
                        EventsTrackWindow(EventWindow, EventGadget, EventType)

                    Default
                        ; Ничего не делать
                EndSelect
            EndIf

        Case #PB_Event_Menu
            Select EventMenu
                Case #MenuNewButton
                    EventWindow = CreateButtonWindow()
                    If EventWindow > 0
                        ResizeButtonWindow(EventWindow)
                    EndIf

                Case #MenuNewDate
                    EventWindow = CreateDateWindow()
                    If EventWindow > 0
                        ResizeDateWindow(EventWindow)
                    EndIf

                Case #MenuNewTrack
                    EventWindow = CreateTrackWindow()
                    If EventWindow > 0
                        ResizeTrackWindow(EventWindow)
                    EndIf

                Case #MenuClose
                    ; Проверить,  действительный ли указатель получен.
                    If *EventGadgets > 0
                        ; Используйте *EventGadgets \ WindowClass для вызова правильной процедуры уничтожения окна.
                        Select *EventGadgets\WindowClass
                            Case #WindowClassButton
                                DestroyButtonWindow(EventWindow)

                            Case #WindowClassDate
                                DestroyDateWindow(EventWindow)

                            Case #WindowClassTrack
                                DestroyTrackWindow(EventWindow)

                            Default
                                ; Ничего не делать
                        EndSelect
                    EndIf
            EndSelect

        Case #PB_Event_CloseWindow
            ; Проверить,  действительный ли указатель получен.
            If *EventGadgets > 0
                ; Используйте *EventGadgets \ WindowClass для вызова правильной процедуры уничтожения окна.
                Select *EventGadgets\WindowClass
                    Case #WindowClassButton
                        DestroyButtonWindow(EventWindow)

                    Case #WindowClassDate
                        DestroyDateWindow(EventWindow)

                    Case #WindowClassTrack
                        DestroyTrackWindow(EventWindow)

                    Default
                        ; Ничего не делать
                EndSelect
            EndIf

        Case #PB_Event_SizeWindow
            If *EventGadgets > 0
                ; Используйте *EventGadgets \ WindowClass для вызова правильной процедуры изменения размера окна.
                Select *EventGadgets\WindowClass
                    Case #WindowClassButton
                        ResizeButtonWindow(EventWindow)

                    Case #WindowClassDate
                        ResizeDateWindow(EventWindow)

                    Case #WindowClassTrack
                        ResizeTrackWindow(EventWindow)

                    Default
                        ; Ничего не делать
                EndSelect
            EndIf

    EndSelect

Until EventQuit = #True

Навигация Руководства

< Динамическая нумерация окон и Гаджетов - Обзор - Другие ключевые слова Компилятора >