Имеем очередь, содержащую наименования (скажем, метки) полей и их длину.
Пусть это будут строки (STRING) (хотя можно и другие типы данных использовать - не важно)
Необходимо динамически создать в окне ENTRY-поля для каждой записи в очереди.
Вроде бы все просто:
В цикле делаем create(control_id,create:entry,parent_id)
потом UNHIDE(control_id). Задаем все неоходимые свойства (координаты и т.п)
А вот как быть со свойством USE?
PROP:USE требует для ENTRY-полей задания USE-переменной
Первая мысль -- создадим динамически новые переменные!
Вторая мысль - как?
Первым делом придумалось вот что:
создать массив из указателей на строки
(ну ограничить себя, например 512-ю переменными)
А вот как правильно создать массив указателей на строки и потом подсунуть еще каждому ENTRY его USE-переменую?
Поискал у себя в закромах, раскопал старый пример Олега Руденко - как создавать через RTL Клариона новые переменные, обрадовался.
Приведу его полностью, что бы объяснить:
Код: Выделить всё
MAP
MODULE('Clarion RTL')
RTL::NewMem(UNSIGNED _Size),ULONG,NAME('Cla$NewMemZ')
RTL::NewStr(UNSIGNED _Size),ULONG,NAME('Cla$NewMemB')
RTL::FreeMem(ULONG _Addr),NAME('_free')
RTL::Mem2UfoAddr(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, |
UNSIGNED _VarSize,BYTE=0),ULONG,RAW,NAME('Cla$Mem2Ufo')
RTL::FreeUfo(ULONG _UFOAddr),RAW,NAME('Cla$FreeUfo')
RTL::Bind(ULONG _UFOAddr,STRING _Name),NAME('Cla$BindV')
RTL::UnBind(STRING _Name),NAME('Cla$UnbindV')
RTL::GetBindVar(STRING _cVarName),*?,RAW,NAME('Cla$EvaluateVariable')
END
END
Var1 ANY
sVar1 STRING(40)
Var2 ANY
sVar2 STRING(40)
VarNamesQue QUEUE,PRE(VAR)
Name STRING(40) ! Имя переменной
Type LONG ! Тип
Size LONG ! Размер
DecFloat BYTE ! Для DECIMAL/PDECIMAL
Addr LONG ! Здесь будет адрес блока памяти
UFOAddr LONG ! Здесь будет адрес UFO-оболочки для переменной
END
!
! Последние два поля при создании очереди инициализируются нулями.
!
CODE
...
Loop Var# = 1 to Records(VarNameQue)
Get(VarNameQue,Var#)
if ~VAR:Name OR ~VAR:Type OR ~VAR:Size Then Cycle.
if VAR:Type = TYPE:STRING
VAR:Addr = RTL::NewStr(VAR:Size)
else
VAR:Addr = RTL::NewMem(VAR:Size)
.
if ~VAR:Addr then Cycle. ! Память не выделена
VAR:UFOAddr = RTL::Mem2UfoAddr(VAR:Addr,VAR:Type,VAR:DecFloat,VAR:Size)
if ~VAR:UFOAddr ! UFO-оболочка не создана
RTL::FreeMem(VAR:Addr)
Cycle
.
RTL::Bind(VAR:UFOAddr,VAR:Name)
Put(VarNameQue) ! Обновить запись
.
Get(VarNameQue,1); Var1 &= RTL::GetBindVar(Clip(VAR:Name)&'<0>')
Get(VarNameQue,2); Var2 &= RTL::GetBindVar(Clip(VAR:Name)&'<0>')
! ВНИМАНИЕ!!! Если какая-либо переменная не найдена и ANY &= Null,
! без проверки на Message() получим GPF.
if ~(Var1 &= Null) AND ~(Var2 &= Null)
Message(Var1 + Var2) ! Var1 + Var2
.
! В конце надо освобождать за собой занятую память:
Loop Var# = 1 to Records(VarNameQue)
Get(VarNameQue,Var#)
if ~VAR:Addr then Cycle.
RTL::FreeMem(VAR:Addr); Clear(VAR:Addr)
if ~VAR:UFOAddr then Cycle.
RTL::FreeUfo(VAR:UFOAddr); Clear(VAR:UFOAddr)
RTL::UnBind(Clip(VAR:Name))
.
Вместо Var1 и Var2 опишу массивчик Var ANY,DIM(512)
А потом буду работать с ним так:
Код: Выделить всё
Var[numb_of_var#] &= RTL::GetBindVar(Clip(VAR:Name)&'<0>')
Фиг. В 32-х разрядной модели в C6RUNX.DLL нет 'Cla$EvaluateVariable'
(C63)
(то есть даже попробовать не удалось)
Ладно, думаю, попробую так:
Код: Выделить всё
Var[numb_of_var#] &= (VAR:Addr)

Так как реализовать такую, вроде бы простую, вещь?
(Или может быть я мудрю? Может это на уровне первого класса, а у меня ум за разум зашел?)
Помогите, плз, разобраться.