Указатели, динамическое создание переменных и т.п.
Добавлено: 16 Декабрь 2007, 23:37
				
				Собственно описываю задачу, которую не могу решить:
Имеем очередь, содержащую наименования (скажем, метки) полей и их длину.
Пусть это будут строки (STRING) (хотя можно и другие типы данных использовать - не важно)
Необходимо динамически создать в окне ENTRY-поля для каждой записи в очереди.
Вроде бы все просто:
В цикле делаем create(control_id,create:entry,parent_id)
потом UNHIDE(control_id). Задаем все неоходимые свойства (координаты и т.п)
А вот как быть со свойством USE?
PROP:USE требует для ENTRY-полей задания USE-переменной
Первая мысль -- создадим динамически новые переменные!
Вторая мысль - как?
Первым делом придумалось вот что:
создать массив из указателей на строки
(ну ограничить себя, например 512-ю переменными)
А вот как правильно создать массив указателей на строки и потом подсунуть еще каждому ENTRY его USE-переменую?
Поискал у себя в закромах, раскопал старый пример Олега Руденко - как создавать через RTL Клариона новые переменные, обрадовался.
Приведу его полностью, что бы объяснить:
Опять обрадовался -- пример сулит как раз именно то, что я хочу вроде бы.
Вместо Var1 и Var2 опишу массивчик Var ANY,DIM(512)
А потом буду работать с ним так:
И потом control_id{PROP:USE}=Var[numb_of_var#] 
Фиг. В 32-х разрядной модели в C6RUNX.DLL нет 'Cla$EvaluateVariable'
(C63)
(то есть даже попробовать не удалось)
Ладно, думаю, попробую так:
Так нельзя, оказывается, тоже. 
Так как реализовать такую, вроде бы простую, вещь?
(Или может быть я мудрю? Может это на уровне первого класса, а у меня ум за разум зашел?)
Помогите, плз, разобраться.
			Имеем очередь, содержащую наименования (скажем, метки) полей и их длину.
Пусть это будут строки (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)
Так как реализовать такую, вроде бы простую, вещь?
(Или может быть я мудрю? Может это на уровне первого класса, а у меня ум за разум зашел?)
Помогите, плз, разобраться.