Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как организовать работу с формами?

375
18 июля 2007 года
dominator
199 / / 16.10.2003
Здравствуйте.
Делаю небольшую программу...
Существует список т.н. отчетов. За каждым из них закреплена своя соответствующая форма, которая должна открываться при клике на наименовании отчета в форме.
Сделал следующим образом.
Структура
 
Код:
TRequestFormDesc = record
   nIndex :Integer; //Индекс формы в списке форм
   sDescription :String; //Описание формы
   sName :String; //Идентификатор
   tAssociatedForm :TForm; //Ассоциированная форма
end;

Объявляю массив структур:
 
Код:
arrtRequestFormDesc :array of TRequestFormDesc;

Далее (ситуация с одним отчетом):
 
Код:
SetLength(arrtRequestFormDesc, nREQUESTS_COUNT);

arrtRequestFormDesc[0].nIndex := 0;
arrtRequestFormDesc[0].sDescription := 'Отчет 1';
arrtRequestFormDesc[0].sName := 'Report1';
arrtRequestFormDesc[0].tAssociatedForm := frmModuleDemandsReport1;


Заполняю список с отчетами:
 
Код:
ListBox_ReportsList.Clear();
for i := 0 to Length(arrtRequestFormDesc) - 1 do begin
      ListBox_ReportsList.Items.Add(arrtRequestFormDesc.sDescription);
end;


Теперь при щелчке на наименовании отчета:
 
Код:
arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].tAssociatedForm.ShowModal();


Работает, как задумано. Но... предполагается, что форма с отчетом должна быть уже к этому времени создана:
 
Код:
Application.CreateForm(TfrmModuleDemandsReport1, frmModuleDemandsReport1);

Как мне организовать то же самое, но создавая форму в момент выбора пользователем отчета в списке?
Как я понимаю, необходимо учитывать в структуре при этом еще и класс данной формы - что то типа:
 
Код:
TRequestFormDesc = record
   nIndex :Integer; //Индекс формы в списке форм
   sDescription :String; //Описание формы
   sName :String; //Идентификатор
   tAssociatedForm :TForm; //Ассоциированная форма
   tCAssociatedForm :Что будет здесь? //Класс
end;

А затем:
 
Код:
Application.CreateForm(arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].tCAssociatedForm, arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].tAssociatedForm);
arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].tAssociatedForm.ShowModal();

Возможно сделать такое?
375
18 июля 2007 года
dominator
199 / / 16.10.2003
Возможно, написано слишком много.
Сведу все к одному:
При создании формы приложение принимает класс формы и экземпляр:
 
Код:
Application.CreateForm(
      TfrmReqForm, frmReqForm      
   );

Можно ли как-то получить ссылку на тип, имея экземпляр?
т.е.

 
Код:
Application.CreateForm(
      {как получить?}, frmReqForm      
   );
268
22 июля 2007 года
Михаил
587 / / 25.06.2005
ссылку на класс? TObject.ClassType
303
23 июля 2007 года
makbeth
1.0K / / 25.11.2004
dominator, поможет следующий код.
Объявление структуры:
 
Код:
TFormClass = class of TForm;

TRequestFormDesc = record
   nIndex :Integer; //Индекс формы в списке форм
   sDescription :String; //Описание формы
   sName :String; //Идентификатор
   [COLOR=Red]//tAssociatedForm :TForm; // Может это поле не нужно?[/COLOR]
   tCAssociatedForm : TFormClass; // Класс формы отчета
end;

При заполнении структуры:
 
Код:
//...
SetLength(arrtRequestFormDesc, nREQUESTS_COUNT);

arrtRequestFormDesc[0].nIndex := 0;
arrtRequestFormDesc[0].sDescription := 'Отчет 1';
arrtRequestFormDesc[0].sName := 'Report1';
arrtRequestFormDesc[0].tCAssociatedForm := [COLOR=Red]T[/COLOR]frmModuleDemandsReport1;
//...

Ну и вызов формы:
 
Код:
var ReportForm: TForm;
begin
    ReportForm:=arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].tCAssociatedForm.Create(Application);
    ReportForm.ShowModal;
    ReportForm.Free;
end;
375
23 июля 2007 года
dominator
199 / / 16.10.2003
Не получается.
До этого была родительская форма и наследники.
Уже упростил задачу:
Структура:
 
Код:
tCAssociatedForm : TForm;

Заполнение:
 
Код:
arrtRequestFormDesc[0].tCAssociatedForm := frmTest;

Здесь frmTest обычная форма от TForm.
Выполняю:
 
Код:
var ReportForm: TForm;
begin  
ReportForm:=arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].tCAssociatedForm.Create(Application);
ReportForm.ShowModal;
ReportForm.Free;

Результат: Access Violation если форма еще не создана.
Если в свойствах проекта ее создавать при запуске приложения - никаких проблем:(
Что я делаю не так?
10
23 июля 2007 года
Freeman
3.2K / / 06.03.2004
Цитата: dominator
Существует список т.н. отчетов. За каждым из них закреплена своя соответствующая форма, которая должна открываться при клике на наименовании отчета в форме.


В подобных случаях не раз советовал удалить переменную формы (первый, второй, третий), чтобы медвежья услуга IDE не мешала думать, как правильно создавать и уничтожать формы динамически.

Цитата: dominator
Структура
 
Код:
TRequestFormDesc = record
   nIndex :Integer; //Индекс формы в списке форм
   sDescription :String; //Описание формы
   sName :String; //Идентификатор
   tAssociatedForm :TForm; //Ассоциированная форма
end;


nIndex - лишний, если не служит чем-то вроде ID. Индексом формы является индекс записи в массиве, описанном ниже. tAssociatedForm правильней описать AssociatedFormClass: TFormClass. Получаем:

 
Код:
TRequestFormDesc = record
   Name: string;
   Description: string;
   AssociatedFormClass: TFormClass;
end;


Цитата: dominator
Объявляю массив структур


Логичней и проще описать перечислимый тип типов отчётов (без каламбура никак), и инициализацию массива перенести на этап компиляции:

 
Код:
type
  TRequestFormKind = (rfdFirst, rfdSecond, rfdThird, rfdSomething);
const
  RequestFormDesc: array [TRequestFormKind] of TRequestFormDesc = (
    (Name: 'Первый отчёт'; Description: 'Подумайте о первом отчёте'; AssociatedFormClass: TFirstRequestForm),
    (Name: 'Второй отчёт'; Description: 'Подумайте о втором отчёте'; AssociatedFormClass: TSecondRequestForm),
    (Name: 'Третий отчёт'; Description: 'Сообразим на троих?'; AssociatedFormClass: TThirdRequestForm),
    (Name: 'ХЗ какой отчёт'; Description: 'Тут придётся напрячься'; AssociatedFormClass: TSomethingRequestForm)
  );

Обращение идёт примерно так:
 
Код:
begin
  with RequestFormDesc[TRequestFormKind(ListBox_ReportsList.ItemIndex)].Create(Application) do
  try
    ShowModal;
  finally
    Free;
  end;
end;


И ещё совет: следуйте правилам именования Borland - откажитесь от венгерской нотации (в данном случае - "псевдовенгерской"). Простой код понятен и без костылей.
375
24 июля 2007 года
dominator
199 / / 16.10.2003
Очень благодарен за помощь. Спасибо всем откликнувшимся!
375
27 июля 2007 года
dominator
199 / / 16.10.2003
Еще вопрос...
Хочу держать информацию о классе формы в бд. Каким образом это реализовать? Делаю так:
1. Таблица. Упрощенно -
id, Title, Name, Associated_form и прочее.
2. Читаю нужную строку. Причем в Associated_form записано значение, к примеру:
TfrmReport1
3. Загоняю полученное значение в AssociatedFormClass следующим образом: TFormClass(VarToStr(мое значение...))
Компилируется без проблем. На этапе исполнения:
 
Код:
oRepForm:=arrtRequestFormDesc[ListBox_ReportsList.ItemIndex].AssociatedFormClass.Create(Application);
oRepForm.ShowModal;
oRepForm.Free;

получаю Access Violation.
Конечно же, если просто присвоить: AssociatedFormClass := TfrmReport1 все отработает нормально.
Как-то вообще такое можно сделать? В чем моя ошибка?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог