Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 4 994

/ вопрос открыт /

Приветствую, уважаемые эксперты!
Формы - открытие.
В программе вспомогательных форм много и открытие их должно происходить примерно так, через одну процедуру, которая вызывается в главной форме

Procedure OpenForm(sNameForm: String);
(sNameForm as Tform).Create(Application)
....
Или что-то в этом роде.

Подскажите, как правильно и возможно ли так?
Спасибо

vladrvv Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: vladrvv (статус: Посетитель)
Вопрос отправлен: 2 февраля 2011, 06:36
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 19; последнее сообщение — 7 февраля 2011, 09:01; участников в обсуждении: 5.
bugmenot

bugmenot (статус: 3-ий класс), 2 февраля 2011, 10:24 [#1]:

А с чего ты вообще взял что так можно делать? В частности, приводить _строку_ к _классу_. Читай внимательно топик "Class references" и далее. Потом разбери след. пример:
procedure TForm12.FormClick(Sender: TObject);
type
  TFormClass = class of TForm;
var
  FormClass: TFormClass;
begin
  RegisterClass(TPersistentClass(Self.ClassType));
  FormClass := TFormClass(FindClass(Self.ClassName));
  FormClass.Create(Application).Show;
end;
виконання програми розпочинається з того самого мiсця, де призупинилося.

min@y™

min@y™ (статус: Доктор наук), 2 февраля 2011, 12:58 [#2]:

Настоятельно не рекомендую управлять объектом по имени.
А классов форм действительно много? "Много" - это сколько? Скорее всего, решить эту проблему можно иначе и намного изящнее. Требуются подробности.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vladrvv

vladrvv (статус: Посетитель), 2 февраля 2011, 20:42 [#3]:

Речь идет о MDI формах
В начале было так
Procedure TFormGL.btnGilecClick(Sender: TObject);
var
  i,nK: integer;
  LysL:Boolean;
begin
   if  (ActiveMDIChild = Nil) then begin
        TFormGILEC.Create(Application);
   end
   else begin
      for i:= 0 to MdiChildCount - 1 do  begin
          if  MDIChildren[i].Caption ='Жильцы' then begin
            LysL:=True;
            nK:=i;
          end;
      end;
      if  LysL then
           MDIChildren[nK].Show
      else begin
          TFormGILEC.Create(Application);
      end;
   end;
end
Потом оказалось, что форм много, они могут открываться из разных мест( меню, бар, из другого окна) и захотелось обобщить код.Написать одну процедуру , через которую производилось создание окна или его активация.
изменил код так
procedure TFormGL.btnGilecClick(Sender: TObject);
var
  fGilec:TForm;
sGLString:string;
begin
 
  fGilec:=FormGILEC;
sGLString:='Жильцы';
  MyFormOpen(fGilec,sGLString);
end;
 
procedure tFormGL.MyFormOpen(sNameform:TForm;sText:String);
var
  i,nK: integer;
  LysL:Boolean;
  fGilec:TForm;
begin
  LysL:=False;
  fGilec:=sNameform;
   if  (FormGL.ActiveMDIChild = Nil) then begin
    (fGilec as TForm).Create(Application);
   end
   else begin
      for i:= 0 to FormGL.MdiChildCount - 1 do  begin
          if  FormGL.MDIChildren[i].Caption =sText  then  
            LysL:=True;
            nK:=i;
          end;
   end;
   if  LysL then
           FormGL.MDIChildren[nK].Show
      else begin
          (fGilec as TForm).Create(Application);
   end;
end;
Дописал функцию MyFormOpen
Программа компилируется без замечаний, но при попытке запуска данной процедуры - выдает сообщение
Access violation at ..
min@y™

min@y™ (статус: Доктор наук), 3 февраля 2011, 08:41 [#4]:

Расскажу, как делаю я. Если у меня в проекте есть больше одной формы, показ и закрытие (если форма немодальная) каждой их этих форм я оформляю функциями внутри модуля каждой формы. Щас приведу примерчик.
Модальная:
  // Форма
  TReportForm = class(TForm)
    // <--- вся начинка тут
  end;
 
var
  ReportForm: TReportForm; // Глобальная переменная
 
procedure ShowReport(AReport: TSelfControlReport);
 
implementation
 
{$R *.dfm}
 
procedure ShowReport(AReport: TSelfControlReport);
begin
  if not Assigned(ReportForm)
    then ReportForm:= TReportForm.Create(Application);
 
  try
    ReportForm.FReport:= AReport;
    ReportForm.UpdateInfo();
    ReportForm.ShowModal();
  finally
    FreeAndNil(ReportForm);
  end;
end;
Заметь, для разных форм удобно использовать разные функции их показа, в них можно передать нужные параметры (здесь передаётся AReport: TSelfControlReport).

Ещё пример модальной формы:
// Создание нового разъёма устройства
function GetNewPlugInfo(var Info: TPlugInfo): Boolean;
var
  Item: TPlugTypeItem;
begin
  if not Assigned(NewPlugForm)
    then NewPlugForm:= TNewPlugForm.Create(Application);
 
  try
    NewPlugForm.ShortNameEdit.Text:= Info.ShortName;
    NewPlugForm.LongNameEdit.Text:= Info.LongName;
    NewPlugForm.RefreshPlugTypeComboBox(nil);
    Result:= NewPlugForm.ShowModal() = mrOk;
 
    if Result
      then with NewPlugForm do
             begin
               Info.ShortName:= NewPlugForm.ShortNameEdit.Text;
               Info.LongName:= NewPlugForm.LongNameEdit.Text;
 
               if PlugTypesComboBox.ItemIndex <> -1
                 then begin
                        Item:= TPlugTypeItem(PlugTypesComboBox.Items.Objects[PlugTypesComboBox.ItemIndex]);
                        if Assigned(Item)
                          then begin
                                 Info.PinsCount:= Item.PinsCount;
                                 Info.PlugTypeName:= Item.PlugTypeName;
                                 Info.PlugType:= Item.PlugType;
                               end;
                      end;
             end; // with
  finally
    FreeAndNil(NewPlugForm);
  end;
end;
 
// Редактирование существующего разъёма устройства
function EditPlug(APlug: TDevPlug): Boolean;
var
  Item: TPlugTypeItem;
begin
  // Изменение разъёма
 
  if not Assigned(NewPlugForm)
    then NewPlugForm:= TNewPlugForm.Create(Application);
 
  try
    NewPlugForm.ShortNameEdit.Text:= APlug.ShortName;
    NewPlugForm.LongNameEdit.Text:= APlug.LongName;
    NewPlugForm.RefreshPlugTypeComboBox(PlugTypesHolder.ItemsByCRC32[APlug.PlugTypeNameCRC32]);
 
    Result:= NewPlugForm.ShowModal() = mrOk;
 
    if Result
      then with NewPlugForm do
             begin
               APlug.ShortName:= NewPlugForm.ShortNameEdit.Text;
               APlug.LongName:= NewPlugForm.LongNameEdit.Text;
 
               if PlugTypesComboBox.ItemIndex <> -1
                 then begin
                        Item:= TPlugTypeItem(PlugTypesComboBox.Items.Objects[PlugTypesComboBox.ItemIndex]);
                        if Assigned(Item)
                          then begin
                                 APlug.PlugTypeNameCRC32:= Item.CRC32;
                                 APlug.PlugType:= Item.PlugType;
                               end
                          else begin
                                 APlug.PlugTypeNameCRC32:= 0;
                                 APlug.PlugType:= ptUnknown;
                               end;
 
                      end;
             end; // with
  finally
    FreeAndNil(NewPlugForm);
  end;
end;
Эти 2 функции создают и потом убивают одну и ту же форму, но с разными действиями. Функции возвращают True, если юзер нажал кнопку "ОК" и введённые им данные оказались верными, False - если юзер нажал кнопку "Отмена".

Немодальная (MDIChild):
  TBuffersForm = class(TForm)
    // <--- Начинка здесь
  end;
 
var
  BuffersForm: TBuffersForm;
 
procedure ShowBuffersForm;
procedure CloseBuffersForm;
 
implementation
 
{$R *.dfm}
 
// Показ формы
procedure ShowBuffersForm;
begin
  if not Assigned(BuffersForm)
    then BuffersForm:= TBuffersForm.Create(Application);
 
  with BuffersForm do
    begin
      UpdateData();
      Show();
    end;
end;
 
// Закрытие
procedure CloseBuffersForm;
begin
  BuffersForm.Close();
end;
 
// Финализация - обязательно.
procedure TBuffersForm.FormDestroy(Sender: TObject);
begin
  // Всякая нужная ботва
  BuffersForm:= nil; // <--- Обнуление глобального указателя
end;
 
procedure TBuffersForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  Action:= caFree;
end;
Если тебе нужно, чтобы в один момент вроемени сущестовало несколько форм одного класса, пиши, я скажу, как это сделать по описанному выше принципу. Это просто.

З.Ы. Не забудь, что все вышеприведённые функции прописаны именно в модулях соответствующих форм.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
min@y™

min@y™ (статус: Доктор наук), 3 февраля 2011, 08:53 [#5]:

Цитата (vladrvv):

Потом оказалось, что форм много, они могут открываться из разных мест( меню, бар, из другого окна) и захотелось обобщить код.Написать одну процедуру , через которую производилось создание окна или его активация.

Да и ещё, на счёт синхронизации контролов, пунктов меню и.т.д.
Я юзаю TActionList - это ядро программы по взаимодействию с юзером. Каждой Action присваиваю уникальный номер (Tag), ну и, конечно, устанавливаю нужные свойства, такие как Caption, Hint, Hotkey, ImageIndex, Group, Checked, Enabled и т.д. Класс TAction как раз и служит для синхронизации видимых контролов, у которых есть свойство Action.
Для каждой TAction писать свой обработчик, особенно, если их в проге 100500 штук - это чистый идиотизм. Поэтому я делаю для них единый обработчик и по свойству Tag определяю, на что тыкнул юзер. Вот кусок моей проги по решению Судоку:
procedure TMainForm.ActionExecute(Sender: TObject);
var
//  OperationResult: Integer;
  NewSudoku: string;
begin
  // Обработчик меню и кнопок
  case TComponent(Sender).Tag of
    // Задать судоку
      5: if RussianInputBox('Новое задание', 'Вставь сюда строку:', NewSudoku)
           then SetSudoku(NewSudoku);
 
    // Сохранить как изображение
     10: if SaveDialog.Execute()
           then begin
                  SaveAsPicture(SaveDialog.FileName, TPictureSaveType(SaveDialog.FilterIndex - 1));
                  SaveDialog.InitialDir:= ExtractFileDir(SaveDialog.FileName);
                end;
 
    // Копировать
     20: begin
           Clipboard.Open();
           try
             Clipboard.AsText:= FSolver.Puzzle;
           finally
             Clipboard.Close();
           end;
         end;
 
    // Копировать как картинку
     22: CopyAsBitmap();     
 
    // Вставить
     25: if Clipboard.HasFormat(CF_TEXT)
           then SetSudoku(Clipboard.AsText);
 
    // Шаг
    100: if FSolver.EmptyCellsCount <> 0
           then begin
                  SolvePanel.Tag:= FSolver.Step();
                  TimePanel.Caption:= '';
                  PaintBox.Refresh();
                end;
 
    // прогон
    101: if FSolver.EmptyCellsCount <> 0
           then begin
                  SolvePanel.Tag:= FSolver.Run();
                  TimePanel.Caption:= FloatToStrF(FSolver.RunTime, ffFixed, 15, 3);
                  PaintBox.Refresh();
                end;
 
    // сброс
    110: begin
           FSolver.Reset();
           PaintBox.Refresh();
           FByUser:= False;
           SolvePanel.Tag:= 100500;
           TimePanel.Caption:= '';
         end;
 
    // выход
    255: Close();
 
    // Подсказки
    301: begin
           FSolver.ShowMayBeValues:= ShowMayBeValuesCheckBox.Checked;
           PaintBox.Refresh();
         end;
 
    // Логирование
    302: if LogCheckBox.Checked
           then FSolver.Log:= LogMemo.Lines
           else begin
                  FSolver.Log:= nil;
                  LogMemo.Clear();
                end;
  end;
end;

З.Ы. Этот и предыдущий посты просто показывают, как делаю я, и никоим образом не являются руководством к действию.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
bugmenot

bugmenot (статус: 3-ий класс), 3 февраля 2011, 10:29 [#6]:

как многа букав...
виконання програми розпочинається з того самого мiсця, де призупинилося.

DNK

DNK (статус: Студент), 3 февраля 2011, 11:21 [#7]:

TActionList - маст юз, но вот в едином обработчике приятного мало. Вместо 100500 обработчиков мы получим лапшу на 100500 строк. Искать потом по ней, где код для нужного action - занятие на любителя. В случае же индивидуального обработчика достаточно дважды кликнуть нужный action.
Универсальные обработчики использую только в случаях, когда добавление его к новым action не приводит к изменению самого обработчика. Т.е. алгоритм остаётся тотже, новыми будут только параметры.
procedure TMyForm.AutoExecute(Sender: TObject);
begin
  MyProcedure(TAction(Sender).Tag);
end;
Если требуется больше одного параметра, то по OnCreate формы кладу в TAction.Tag указатель на необходимые данные.
"Digital Networked Knight"
Вадим К

Вадим К (статус: Академик), 3 февраля 2011, 11:34 [#8]:

Я вообще против такого использования свойства Tag. Легко запутаться и код не понятен. Потом пол дня ломай голову, почему вызвало не тот что нужно участок кода.
К тому же, процедуры, которые не влазят на один разворот экрана - плохо. их сложно глазами выловить.
Да и зачем делать то, что делфи для нас уже сделало? (я говорю о диспетчеризации событий).
Галочка "подтверждения прочтения" - вселенское зло.
min@y™

min@y™ (статус: Доктор наук), 3 февраля 2011, 11:45 [#9]:

Цитата (Вадим К):

Я вообще против такого использования свойства Tag. Легко запутаться и код не понятен. Потом пол дня ломай голову, почему вызвало не тот что нужно участок кода.

Ну, если писать правильно и комментировать код, то не запутываешься. Проверено на мне неоднократно.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vladrvv

vladrvv (статус: Посетитель), 3 февраля 2011, 19:09 [#10]:

Спасибо всем , кто принял участие в обсуждении вопроса.Но все таки интересно, что неправильно в моем коде?
....
 if  (FormGL.ActiveMDIChild = Nil) then begin
    (fGilec as TForm).Create(Application);
....
Компилируется без замечаний.Где-то очень важная "мелочь" пропущена .
Сейчас остановился на таком варианте:
1) На баре размещаю столько кнопок, сколько окон MDI. На них же вешаю основные процедуры создания или активизации окна.

2) В остальных местах программ, там где надо открыть окно, пишу совсем маленький код , к примеру для кнопки с именем
NameButton
 
 btnNameButton.Click;
min@y™

min@y™ (статус: Доктор наук), 3 февраля 2011, 20:43 [#11]:

Цитата (vladrvv):

что неправильно в моем коде?

А ты воспользуйся отладчиком, пройдись по шажочкам по коду, выясни, в какой строке у тебя вылетает AV и какой указатель равен nil или указывает хз-куда. Этой информации нам и не хватает, чтобы хоть как-то въехать в ситуёвину.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vladrvv

vladrvv (статус: Посетитель), 4 февраля 2011, 07:31 [#12]:

Выложил упрощенный вариант программы, повторяющий ситуацию
http://zalil.ru/30451390
DNK

DNK (статус: Студент), 4 февраля 2011, 20:20 [#13]:

vladrvv: У меня конструкция (sNameForm as TForm) не компилируется.

Цитата:

Operator not applicable to this operand type
"Digital Networked Knight"
min@y™

min@y™ (статус: Доктор наук), 4 февраля 2011, 21:04 [#14]:

Короче, аффтар вопроса нихрена не читает ответы и упрям, как осёл. Может закрыть этот вопрос нахрен?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
min@y™

min@y™ (статус: Доктор наук), 4 февраля 2011, 21:07 [#15]:

Хренова гора нубов вываливают тут свои позорные исходники и просят найти ошибку. Когда им предлагают решение задачи другим способом - игнорят и минусуют. Ну какого хрена?!
Ну сколько можно, а?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vladrvv

vladrvv (статус: Посетитель), 5 февраля 2011, 07:49 [#16]:

min@y™
Ну за чем грубить? Спасибо за ценные советы и примеры кода. Я их обязательно учту.+ поставлю.Но в данном случае мне важно выяснить, что неправильно и почему этот код не работает
DNK

DNK (статус: Студент), 5 февраля 2011, 08:46 [#17]:

Цитата (vladrvv):

Но в данном случае мне важно выяснить, что неправильно и почему этот код мой запорожец не работает может долететь до марса
:)
"Digital Networked Knight"
min@y™

min@y™ (статус: Доктор наук), 5 февраля 2011, 09:55 [#18]:

Цитата (vladrvv):

Но в данном случае мне важно выяснить, что неправильно и почему этот код не работает

Ну так и что тебе мешает поставить точку останова и пройтись дебаггером по куску кода, посмотреть значеня переменных и понять, где и почему вылетает ошибка? У тебя пальцы сломаны, не можешь на кнопки нажимать? Ну нахрена перекладывать проблему, которую сам можешь решить за 2 минуты, на толпу народа в интернете?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
vladrvv

vladrvv (статус: Посетитель), 7 февраля 2011, 09:01 [#19]:

Проблема решена. Применен прием - поиск класса по имени. Все формы открываеются одной процедурой из любого места.Пример выложен http://zalil.ru/30465772. Кто работает с MDI формами -возможно пригодится.
Тема закрыта

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:46
Выполнено за 0.07 сек.