Динамическое создание компонентов
Материал из GedeminWiki
(Различия между версиями)
SYSDBA (обсуждение | вклад) |
SYSDBA (обсуждение | вклад) (→OnClick) |
||
| (не показаны 5 промежуточных версий 1 участника) | |||
| Строка 1: | Строка 1: | ||
| − | ... | + | В Гедымине существует возможность динамического создания компонентов в момент выполнения программы. Рассмотрим данную возможность на примере популярной игры [http://ru.wikipedia.org/wiki/%D0%9F%D1%8F%D1%82%D0%BD%D0%B0%D1%88%D0%BA%D0%B8 Пятнашки]. Создадим глобальный макрос Game15. Его задача -- сформировать DFM окна игры (диалоговая форма квадратной формы с расположенной на ней панелью -- игровое поле). Данный DFM записывается в глобальное хранилище, в папку NewForm. После чего можно создавать экземпляр такой формы используя функцию Creator.GetObject: |
| + | |||
| + | Option Explicit | ||
| + | Sub Game15 | ||
| + | Dim St, A(0), F, Creator | ||
| + | Set Creator = new TCreator | ||
| + | A(0) = "" &_ | ||
| + | "object usrf_game15: TgdcCreateableForm" & vbCrLf &_ | ||
| + | " BorderStyle = bsDialog" & vbCrLf &_ | ||
| + | " ClientWidth = 136" & vbCrLf &_ | ||
| + | " ClientHeight = 136" & vbCrLf &_ | ||
| + | " Position = poScreenCenter" & vbCrLf &_ | ||
| + | " object Field: TPanel" & vbCrLf &_ | ||
| + | " Left = 4" & vbCrLf &_ | ||
| + | " Top = 4" & vbCrLf &_ | ||
| + | " Width = 128" & vbCrLf &_ | ||
| + | " Height = 128" & vbCrLf &_ | ||
| + | " BevelInner = bvNone" & vbCrLf &_ | ||
| + | " BevelOuter = bvLowered" & vbCrLf &_ | ||
| + | " end" & vbCrLf &_ | ||
| + | "end" | ||
| + | Set St = Creator.GetObject(A, "TStringStream", "") | ||
| + | |||
| + | GlobalStorage.WriteInteger "NewForm\usrf_game15", "InternalType", 1 | ||
| + | GlobalStorage.WriteString "NewForm\usrf_game15", "Class", "TgdcCreateableForm" | ||
| + | GlobalStorage.WriteStream "NewForm\usrf_game15", "dfm", St | ||
| + | |||
| + | Set F = Creator.GetObject(Application, "usrf_game15", "game15") | ||
| + | F.ShowModal | ||
| + | End Sub | ||
| + | |||
| + | Запустим макрос на выполнение. На экране должна открыться форма с единственной, чистой панелью. Переведем ее в режим дизайнера (Ctrl-Alt-E) и в Инспекторе объектов на вкладке События создадим обработчики для событий OnCreate и OnClose. | ||
| + | |||
| + | === OnCreate === | ||
| + | |||
| + | '#include GAME15_ONCLICK | ||
| + | option explicit | ||
| + | sub usrf_game15OnCreate(ByVal Sender) | ||
| + | '*** Данный код необходим для вызова встроенного обработчика *** | ||
| + | '*** В случае его удаления возможно нарушение работы системы *** | ||
| + | call Inherited(Sender, "OnCreate", Array(Sender)) | ||
| + | '*** конец кода поддержки встроенного обработчика *** | ||
| + | |||
| + | const CellSize = 32 | ||
| + | const FieldWidth = 4 | ||
| + | |||
| + | dim I, P, C | ||
| + | set C = Sender.GetComponent("Field") | ||
| + | |||
| + | for I = 0 to (FieldWidth * FieldWidth - 2) | ||
| + | set P = Designer.CreateObject(Sender, "TPanel", "P" & I) | ||
| + | P.Left = (I mod FieldWidth) * CellSize | ||
| + | P.Top = (I \ FieldWidth) * CellSize | ||
| + | P.Width = CellSize | ||
| + | P.Height = CellSize | ||
| + | P.Caption = I + 1 | ||
| + | P.Parent = C | ||
| + | SetEventHandler P, "OnClick", "game15_OnClick" | ||
| + | next | ||
| + | |||
| + | for I = 1 to 1000 | ||
| + | game15_OnClick Sender.GetComponent("P" & Int((FieldWidth * FieldWidth - 1) * Rnd)) | ||
| + | next | ||
| + | |||
| + | end sub | ||
| + | |||
| + | === OnClose === | ||
| + | |||
| + | option explicit | ||
| + | sub usrf_game15OnClose(ByVal Sender, ByRef Action) | ||
| + | '*** Данный код необходим для вызова встроенного обработчика *** | ||
| + | '*** В случае его удаления возможно нарушение работы системы *** | ||
| + | Dim ParamArr(1) | ||
| + | Set ParamArr(0) = Sender | ||
| + | ParamArr(1) = Action | ||
| + | call Inherited(Sender, "OnClose", ParamArr) | ||
| + | Action.Value = ParamArr(1) | ||
| + | '*** конец кода поддержки встроенного обработчика *** | ||
| + | |||
| + | Dim F | ||
| + | Set F = GlobalStorage.OpenFolder("NewForm", False, False) | ||
| + | if Assigned(F) then | ||
| + | F.DeleteFolder "usrf_game15" | ||
| + | end if | ||
| + | GlobalStorage.CloseFolder F, True | ||
| + | |||
| + | Action.Value = caFree | ||
| + | end sub | ||
| + | |||
| + | === OnClick === | ||
| + | |||
| + | option explicit | ||
| + | function game15_CanMove(Parent, X, Y) | ||
| + | game15_CanMove = False | ||
| + | |||
| + | if (X >= 0) and (X < Parent.Width) and (Y >= 0) and (Y < Parent.Height) then | ||
| + | dim I, C | ||
| + | for I = 0 to Parent.ControlCount - 1 | ||
| + | set C = Parent.Controls(I) | ||
| + | if (X >= C.Left) and (X < C.Left + C.Width) and (Y >= C.Top) and (Y < C.Top + C.Height) then | ||
| + | exit function | ||
| + | end if | ||
| + | next | ||
| + | |||
| + | game15_CanMove = True | ||
| + | end if | ||
| + | end function | ||
| + | |||
| + | function game15_OnClick(Sender) | ||
| + | if game15_CanMove(Sender.Parent, Sender.Left + 32 + 1, Sender.Top) then | ||
| + | Sender.Left = Sender.Left + 32 | ||
| + | elseif game15_CanMove(Sender.Parent, Sender.Left - 32 + 1, Sender.Top) then | ||
| + | Sender.Left = Sender.Left - 32 | ||
| + | elseif game15_CanMove(Sender.Parent, Sender.Left, Sender.Top + 32 + 1) then | ||
| + | Sender.Top = Sender.Top + 32 | ||
| + | elseif game15_CanMove(Sender.Parent, Sender.Left, Sender.Top - 32 + 1) then | ||
| + | Sender.Top = Sender.Top - 32 | ||
| + | end if | ||
| + | |||
| + | Dim I | ||
| + | I = CInt(Sender.Caption) - 1 | ||
| + | if (Sender.Left = (I mod 4) * 32) and (Sender.Top = (I \ 4) * 32) then | ||
| + | Sender.Color = &HFFFFFF | ||
| + | else | ||
| + | Sender.Color = &HA0A0A0 | ||
| + | end if | ||
| + | |||
| + | end function | ||
| + | |||
| + | [[Category:Учебный курс]] | ||
Текущая версия на 11:15, 12 ноября 2009
В Гедымине существует возможность динамического создания компонентов в момент выполнения программы. Рассмотрим данную возможность на примере популярной игры Пятнашки. Создадим глобальный макрос Game15. Его задача -- сформировать DFM окна игры (диалоговая форма квадратной формы с расположенной на ней панелью -- игровое поле). Данный DFM записывается в глобальное хранилище, в папку NewForm. После чего можно создавать экземпляр такой формы используя функцию Creator.GetObject:
Option Explicit
Sub Game15
Dim St, A(0), F, Creator
Set Creator = new TCreator
A(0) = "" &_
"object usrf_game15: TgdcCreateableForm" & vbCrLf &_
" BorderStyle = bsDialog" & vbCrLf &_
" ClientWidth = 136" & vbCrLf &_
" ClientHeight = 136" & vbCrLf &_
" Position = poScreenCenter" & vbCrLf &_
" object Field: TPanel" & vbCrLf &_
" Left = 4" & vbCrLf &_
" Top = 4" & vbCrLf &_
" Width = 128" & vbCrLf &_
" Height = 128" & vbCrLf &_
" BevelInner = bvNone" & vbCrLf &_
" BevelOuter = bvLowered" & vbCrLf &_
" end" & vbCrLf &_
"end"
Set St = Creator.GetObject(A, "TStringStream", "")
GlobalStorage.WriteInteger "NewForm\usrf_game15", "InternalType", 1
GlobalStorage.WriteString "NewForm\usrf_game15", "Class", "TgdcCreateableForm"
GlobalStorage.WriteStream "NewForm\usrf_game15", "dfm", St
Set F = Creator.GetObject(Application, "usrf_game15", "game15")
F.ShowModal
End Sub
Запустим макрос на выполнение. На экране должна открыться форма с единственной, чистой панелью. Переведем ее в режим дизайнера (Ctrl-Alt-E) и в Инспекторе объектов на вкладке События создадим обработчики для событий OnCreate и OnClose.
[править] OnCreate
'#include GAME15_ONCLICK
option explicit
sub usrf_game15OnCreate(ByVal Sender)
'*** Данный код необходим для вызова встроенного обработчика ***
'*** В случае его удаления возможно нарушение работы системы ***
call Inherited(Sender, "OnCreate", Array(Sender))
'*** конец кода поддержки встроенного обработчика ***
const CellSize = 32
const FieldWidth = 4
dim I, P, C
set C = Sender.GetComponent("Field")
for I = 0 to (FieldWidth * FieldWidth - 2)
set P = Designer.CreateObject(Sender, "TPanel", "P" & I)
P.Left = (I mod FieldWidth) * CellSize
P.Top = (I \ FieldWidth) * CellSize
P.Width = CellSize
P.Height = CellSize
P.Caption = I + 1
P.Parent = C
SetEventHandler P, "OnClick", "game15_OnClick"
next
for I = 1 to 1000
game15_OnClick Sender.GetComponent("P" & Int((FieldWidth * FieldWidth - 1) * Rnd))
next
end sub
[править] OnClose
option explicit
sub usrf_game15OnClose(ByVal Sender, ByRef Action)
'*** Данный код необходим для вызова встроенного обработчика ***
'*** В случае его удаления возможно нарушение работы системы ***
Dim ParamArr(1)
Set ParamArr(0) = Sender
ParamArr(1) = Action
call Inherited(Sender, "OnClose", ParamArr)
Action.Value = ParamArr(1)
'*** конец кода поддержки встроенного обработчика ***
Dim F
Set F = GlobalStorage.OpenFolder("NewForm", False, False)
if Assigned(F) then
F.DeleteFolder "usrf_game15"
end if
GlobalStorage.CloseFolder F, True
Action.Value = caFree
end sub
[править] OnClick
option explicit
function game15_CanMove(Parent, X, Y)
game15_CanMove = False
if (X >= 0) and (X < Parent.Width) and (Y >= 0) and (Y < Parent.Height) then
dim I, C
for I = 0 to Parent.ControlCount - 1
set C = Parent.Controls(I)
if (X >= C.Left) and (X < C.Left + C.Width) and (Y >= C.Top) and (Y < C.Top + C.Height) then
exit function
end if
next
game15_CanMove = True
end if
end function
function game15_OnClick(Sender)
if game15_CanMove(Sender.Parent, Sender.Left + 32 + 1, Sender.Top) then
Sender.Left = Sender.Left + 32
elseif game15_CanMove(Sender.Parent, Sender.Left - 32 + 1, Sender.Top) then
Sender.Left = Sender.Left - 32
elseif game15_CanMove(Sender.Parent, Sender.Left, Sender.Top + 32 + 1) then
Sender.Top = Sender.Top + 32
elseif game15_CanMove(Sender.Parent, Sender.Left, Sender.Top - 32 + 1) then
Sender.Top = Sender.Top - 32
end if
Dim I
I = CInt(Sender.Caption) - 1
if (Sender.Left = (I mod 4) * 32) and (Sender.Top = (I \ 4) * 32) then
Sender.Color = &HFFFFFF
else
Sender.Color = &HA0A0A0
end if
end function