Руководство - Динамическая нумерация окон и Гаджетов, с помощью #PB_Any
Если вы просматривали справочные статьи для команды OpenWindow или какой-либо из команд создания Гаджетов (например, ButtonGadget()), или если Вы экспериментировали с инструментом Form Designer, Вы могли заметить ссылки на специальную константу с именем #PB_Any. В этой статье мы рассмотрим её подробней, чтобы вы поняли, почему она так важна.В разделе 'Enumerations' обратите внимание, что для элементов меню есть только перечисления. Они будут доступны во всех окнах - хотя каждое окно будет иметь свою собственную панель меню.Наконец, обратите внимание, что хеш-карта не является единственным способом достижения этого эффекта, можно использовать Список или Массив хотя код для реализации этих альтернатив должен быть несколько иным, чем представленный здесь из-за различий в способах работы этих коллекций.
В разделе Structures обратите внимание, что структура POLYGONWINDOW содержит четыре значения с типом Integer и, таким образом, предоставляет место для хранения ссылок на строку меню, метку, поле со списком и график изображения.
В разделе Переменные заметим, что в дополнение к обычным переменным для получения подробностей событий создается хеш-карта ActiveWindows с использованием ранее определенной структуры POLYGONWINDOW.
Посмотрите на процедуру CreatePolygonWindow.
Когда мы создаем окно, мы фиксируем результат функции OpenWindow() в переменной ThisWindow. Затем мы преобразуем это значение в строку и используем его как ключ для новой записи хеш-карты.
Когда мы тогда создаем меню, метку, Комбо-бокс и отображаем Гаджеты в новом окне, ссылки, возвращаемые этими функциями, также сохраняются на хеш-карте.
Посмотрите на процедуру ResizePolygonWindow.
Обратите внимание, что значение EventWindow передается из цикла обработки событий в эту процедуру. Это значение затем используется для извлечения ссылок на дочерние элементы управления из хеш-карты, и эти ссылки затем используются для изменения размеров Гаджетов.
Посмотрите на процедуру DestroyPolygonWindow.
Здесь ссылки дочернего элемента управления удаляются из хеш-карты, когда окно закрывается. Если размер хеш-карты достигнет нуля - больше нет открытых окон, и DestroyPolygonWindow задает флаг события, чтобы завершить программу.
Запустите программу.
- Используйте пункт меню "New Window", чтобы открыть два или три новых окна многоугольника.
- Используйте поле со списком в каждом, чтобы выбрать другую форму – обратите внимание, что каждое окно работает независимо от всех остальных.
- Измените размер некоторых окон - обратите внимание, что все они могут быть изменены независимо друг от друга и что полигон также будет изменять размер окна.
; Директивы компилятора. EnableExplicit ; Константы CompilerIf Defined(Blue, #PB_Constant) = #False #Blue = 16711680 #Gray = 8421504 #White = 16777215 CompilerEndIf ;- Перечисления ; Команды меню будут одни и те же, на всех окнах. Enumeration #MenuNew #MenuClose EndEnumeration ;- Структуры ; Эта структура будет содержать ссылки на уникальные элементы окна. Structure POLYGONWINDOW Menu.i LabelSides.i ComboSides.i ImagePlot.i EndStructure ;- Переменные ; Эта хеш-карта использует ранее объявленную структуру для содержания ссылок, для всех открытых окон. NewMap ActiveWindows.POLYGONWINDOW() ; Переменные событий. Define.i Event, EventWindow, EventGadget, EventType, EventMenu, EventQuit Define.s EventWindowKey ; Реализация Procedure.i CreatePolygonWindow() ; Создает новое окно и Гаджеты, добавляя его и его дочерние Гаджеты к хеш-карте отслеживания. Shared ActiveWindows() Protected.i ThisWindow Protected.s ThisKey ThisWindow = OpenWindow(#PB_Any, 50, 50, 300, 300, "Polygon", #PB_Window_SystemMenu - #PB_Window_SizeGadget - #PB_Window_MinimizeGadget - #PB_Window_TitleBar) WindowBounds(ThisWindow, 250, 250, #PB_Ignore, #PB_Ignore) If ThisWindow ; Карты принимают как ключ строковое значение, поэтому преобразуем целочисленное значение (.i) переменной ThisWindow в строку (string). ThisKey = StrU(ThisWindow) ; Добавить элемент хеш-карты для сохранения новых ссылок Гаджета. AddMapElement(ActiveWindows(), ThisKey) ; Создать строку меню. ActiveWindows(ThisKey)\Menu = CreateMenu(#PB_Any, WindowID(ThisWindow)) MenuTitle("Window") MenuItem(#MenuNew, "New Window") MenuItem(#MenuClose, "Close Window") ; Создать дочерние Гаджеты и сохраните их ссылки в хеш-карте. With ActiveWindows() ; Метка для комбо-бокса \LabelSides = TextGadget(#PB_Any, 5, 5, 150, 20, "Number of Sides:") ; Стороны комбо-бокса \ComboSides = ComboBoxGadget(#PB_Any, 160, 5, 100, 25) AddGadgetItem(\ComboSides, 0, "Triangle") AddGadgetItem(\ComboSides, 1, "Diamond") AddGadgetItem(\ComboSides, 2, "Pentagon") AddGadgetItem(\ComboSides, 3, "Hexagon") AddGadgetItem(\ComboSides, 4, "Heptagon") AddGadgetItem(\ComboSides, 5, "Octagon") AddGadgetItem(\ComboSides, 6, "Nonagon") AddGadgetItem(\ComboSides, 7, "Decagon") ; Выбрать Треугольник. SetGadgetState(\ComboSides, 0) ; Гаджет визуального изображения в окне. \ImagePlot = ImageGadget(#PB_Any, 5, 35, 290, 240, 0, #PB_Image_Border) EndWith EndIf ; Вернуть ссылку на новое окно. ProcedureReturn ThisWindow EndProcedure Procedure DestroyPolygonWindow(Window.i) ; Удалить окно с хеш-карты ActiveWindows, закройте окно и установите флаг выхода, если это необходимо. Shared EventQuit, ActiveWindows() Protected.s ThisKey ; Преобразует значение (.i) переменной Window в строку (string). ThisKey = StrU(Window) ; Удалить запись из хеш-карты. DeleteMapElement(ActiveWindows(), ThisKey) ; Закрыть Окно. CloseWindow(Window) ; Проверить, есть ли еще открытые окна. If MapSize(ActiveWindows()) = 0 EventQuit = #True EndIf EndProcedure Procedure.i ResizePolygonWindow(Window.i) ; Изменить размеры дочерних Гаджетов в окне. ; На практике в этом примере только ImageGadget необходимо изменять. Shared ActiveWindows() Protected.i ThisImage Protected.i X, Y, W, H Protected.s ThisKey ; Получить ссылки на соответствующие Гаджеты с хеш-карты. ThisKey = StrU(Window) ThisImage = ActiveWindows(ThisKey)\ImagePlot ; Изменение размеров Гаджетов. W = WindowWidth(Window) - 15 H = WindowHeight(Window) - 70 ResizeGadget(ThisImage, #PB_Ignore, #PB_Ignore, W, H) EndProcedure Procedure PlotPolygon(Window.i) ; Нарисовать многоугольник и перенесите его в Гаджет изображения. Shared ActiveWindows() Protected.f Radius, OriginX, OriginY, StartX, StartY, EndX, EndY Protected.i Sides, Vertex, Width, Height, ThisCombo, ThisImage, ThisPlot Protected.s ThisKey ; Проверить, соответствует ли это событие правильному окну. If Not IsWindow(Window) : ProcedureReturn : EndIf ; Получить ссылки на соответствующие Гаджеты с хеш-карты. ThisKey = StrU(Window) ThisCombo = ActiveWindows(ThisKey)\ComboSides ThisImage = ActiveWindows(ThisKey)\ImagePlot ; Вычислить размеры и происхождение. Sides = GetGadgetState(ThisCombo) + 3 Width = GadgetWidth(ThisImage) - 4 Height = GadgetHeight(ThisImage) - 4 OriginX = Width/2 OriginY = Height/2 If Width < Height Radius = OriginX - 50 Else Radius = OriginY - 50 EndIf ; Создать новое изображение. ThisPlot = CreateImage(#PB_Any, Width, Height) StartDrawing(ImageOutput(ThisPlot)) ; Нарисовать белый фон. Box(0, 0, Width, Height, #White) ; Нарисовать ограничивающий круг серого цвета. Circle(OriginX, OriginY, Radius, #Gray) ; Нарисовать многоугольник. For Vertex = 0 To Sides ; Вычислить начальную точку стороны. StartX = OriginX + (Radius * Cos(2 * #PI * Vertex/Sides)) StartY = OriginY + (Radius * Sin(2 * #PI * Vertex/Sides)) ; И конечную точку. EndX = OriginX + (Radius * Cos(2 * #PI * (Vertex + 1)/Sides)) EndY = OriginY + (Radius * Sin(2 * #PI * (Vertex + 1)/Sides)) ; Нарисовать сторону синим цветом. LineXY(StartX, StartY, EndX, EndY, #Blue) Next Vertex ; Заполнить многоугольник синим цветом. FillArea(OriginX, OriginY, #Blue, #Blue) StopDrawing() ; Перенос содержимого изображения в отображаемый Гаджет. SetGadgetState(ThisImage, ImageID(ThisPlot)) ; Уничтожить временное изображение. FreeImage(ThisPlot) EndProcedure ;- Главный код ; Создать первое окно. EventWindow = CreatePolygonWindow() ResizePolygonWindow(EventWindow) PlotPolygon(EventWindow) ;- Цикл событий. Repeat Event = WaitWindowEvent() EventWindow = EventWindow() EventWindowKey = StrU(EventWindow) EventGadget = EventGadget() EventType = EventType() EventMenu = EventMenu() Select Event Case #PB_Event_Gadget ; Произошло событие Гаджета. If EventGadget = ActiveWindows(EventWindowKey)\LabelSides ; Ничего не делать. ElseIf EventGadget = ActiveWindows(EventWindowKey)\ComboSides ; Если поле со списком изменилось, перерисовать изображение. PlotPolygon(EventWindow) ; Обновить заголовок окна, чтобы отобразить новую фигуру. SetWindowTitle(EventWindow, GetGadgetText(ActiveWindows(EventWindowKey)\ComboSides)) ElseIf EventGadget = ActiveWindows(EventWindowKey)\ImagePlot ; Ничего не делать. EndIf Case #PB_Event_Menu ; Произошло событие меню. If EventMenu = #MenuNew EventWindow = CreatePolygonWindow() ResizePolygonWindow(EventWindow) PlotPolygon(EventWindow) ElseIf EventMenu = #MenuClose DestroyPolygonWindow(EventWindow) EndIf Case #PB_Event_Repaint ; Содержимое окна было аннулировано. PlotPolygon(EventWindow) Case #PB_Event_SizeWindow ; Размеры окна были изменены. ResizePolygonWindow(EventWindow) PlotPolygon(EventWindow) Case #PB_Event_CloseWindow ; Окно было закрыто. DestroyPolygonWindow(EventWindow) EndSelect Until EventQuit = #True
Навигация Руководства
< Доступ к памяти - Обзор - Управление множеством окон >