Как использовать или решать проблемы с наследованием визуальных форм в Delphi?

Я работал над проектом в Delphi 7, где я хотел, чтобы формы наследовали компоненты от других форм. Мне удалось заставить это работать, но я столкнулся со следующими проблемами (и я собираюсь опубликовать решения, чтобы, надеюсь, помочь другим в будущем):

  1. В файле .pas формы я бы изменил форму, чтобы она наследовалась от какой-либо другой формы, но она не получила бы компоненты от формы-предка.
  2. Для некоторых форм-потомков я получаю следующее сообщение об ошибке при открытии формы во время разработки: «Ошибка создания формы: предок для« TAncestorForm »не найден». Мне пришлось бы сначала вручную открыть форму предка, а затем я мог бы открыть форму потомка.

person Liron Yahdav    schedule 10.10.2008    source источник


Ответы (2)


Во-первых, для тех, кто не знает, как наследовать форму визуально, вы создаете форму предка как обычно. Затем перейдите в «Файл» > «Создать» > «Другое». Выберите вкладку с названием текущего проекта и выберите форму, от которой вы хотите наследоваться. Если вы хотите наследовать от формы, которая не является частью текущего проекта, откройте эту форму, щелкните ее правой кнопкой мыши и выберите «Добавить в репозиторий». Затем вы сможете перейти в «Файл»> «Создать»> «Другое» и выбрать эту форму на соответствующей вкладке.

Учитывая это, я столкнулся с проблемами, потому что некоторые из форм-потомков уже были созданы, поэтому я не мог следовать описанному выше процессу. Кроме того, я внес некоторые изменения в формы из стандартного кода, создаваемого Delphi. Я смог решить все проблемы с наследованием визуальных форм, используя следующие рекомендации:

  • Файл .pas формы-потомка должен иметь класс формы, наследуемый от правильного класса-предка, например:
    type TMyForm = class(TAncestorForm)
  • Первая строка в .dfm формы-потомка должна содержать слово inherited вместо object, например:
    inherited MyForm: TMyForm
  • EDIT: после двойной проверки следующее НЕ требуется: Файл .pas формы-предка должен иметь стандартную глобальную переменную, которую создает Delphi, например:
    var AncestorForm: TAncestorForm;
  • Раздел uses файла .dpr проекта должен иметь ту же глобальную переменную, что и комментарий после имени файла объекта, например:
    unAncestor in 'unAncestor.pas' {AncestorForm}

Примечания/советы:

  • Как форму-предка, так и форму-потомка можно создать без автоматического создания, если вы хотите (Установить в «Проект»> «Параметры»> «Формы»> «Автоматическое создание форм»).
  • Чтобы вернуть свойству формы-потомка значение формы-предка, щелкните правой кнопкой мыши свойство в Инспекторе объектов и выберите «Восстановить унаследованное».
  • Чтобы вернуть все значения свойств компонента к значениям предка, щелкните компонент правой кнопкой мыши и выберите «Восстановить унаследованные».
person Liron Yahdav    schedule 10.10.2008
comment
Глобальная переменная не требуется. - person Erick Sasse; 10.10.2008
comment
Глобальная переменная требуется только в том случае, если вы разрешили Delphi автоматически создавать форму (вы можете установить это в диалоговом окне «Параметры проекта»). - person onnodb; 10.10.2008
comment
Вы, ребята, правы. Я только что перепроверил это. Я отредактирую пост, спасибо. - person Liron Yahdav; 11.10.2008
comment
См. также эти два сообщения в блоге, объясняющие наследование Frame и DataModule: wiert.wordpress.com/2009/07/22/ и wiert.wordpress.com/2009/08/20/ Эти статьи содержат изображения хороших и плохих ситуаций. - person Jeroen Wiert Pluimers; 24.10.2009
comment
Для людей C++Builder вы можете следовать тем же инструкциям. Единственное предостережение, которое у меня есть, это то, что TAncestorForm не может находиться в своем собственном пространстве имен (т.е. должно находиться в глобальном пространстве имен). По крайней мере, это была моя находка. - person Scott Saad; 01.12.2010
comment
Я столкнулся с той же проблемой, но в моем случае и потомок, и предок уже существовали. Однако в проекте DFM предка не был включен в файлы проекта. Мне пришлось удалить предка, затем щелкнуть правой кнопкой мыши проект и добавить › , снова предка. На этот раз DFM был включен. - person Bizmarck; 21.03.2017
comment
Интересно, что нужно, чтобы заставить его работать, просто упоминание устройства в файле DPR или добавление комментария формы/фрейма. Потому что, имея эти родительские формы в BPL, включение пункта in в DPR было бы в лучшем случае жульничеством. Однако есть другой обходной путь: github.com/the-Arioch/XE2_AutoOpenUnit. - person Arioch 'The; 13.08.2018
comment
Итак, я попробовал unAncestor {AncestorForm}, без in 'unAncestor.pas' в моем DPR, и мой Delphi XE2 ведет себя так странно... Он пытается автоматически открыть что-то, но... Ну, он выдает исключение, которое может открыть файл DPR-PATH\AncestorForm ! Таким образом, без in-clause он берет комментарий для имени файла относительно папки DPR, а затем пытается открыть его, не проверяя, существует ли файл! Странный - person Arioch 'The; 15.08.2018
comment
Для удаления пункта в DPR для модулей, содержащих BPL, есть две абстрактные и одна практическая причины: 1) это антидокументация. Вы документируете в DPR, что модуль скомпилирован в EXE, в то время как на самом деле он скомпилирован в BPL, который использует EXE; 2) нарушение единой ответственности: путь к модулю должен быть указан в одном месте: DPK 3) поэтому я столкнулся с ситуацией, когда у меня было несколько версий модуля в разных папках. ДПК и ДНР случайно указали на разные. Таким образом, реальный код использовал единицу, предоставленную DPK, в то время как IDE указывала на единицу, задокументированную DPR (ложно). Много путаницы. - person Arioch 'The; 15.08.2018
comment
Интересно.... Какие из вышеперечисленных шагов автоматически выполняются IDE, а какие нужно делать вручную? Кроме того, вам нужно открыть форму предка, прежде чем вы откроете унаследованную форму? - person Z80; 05.02.2021

DPR кажется немного сложнее, чем это. В моем случае я создал предка, производного от TFrame. Затем я получил несколько кадров из TAncestorFrame. Предложение использования моего DPR тогда выглядело так:

uses
  Forms,
  ancestorFrame in 'ancestorFrame.pas' {AncestorFrame : TFrame},
  frame1Unit in 'frame1Unit.pas' {frame1:TFrame},
  frame2Unit in 'frame2Unit .pas' {frame2:TFrame},

Файл DPROJ должен выглядеть так:

<DCCReference include="frame1Unit.pas">
  <Form>frame1</Form>
  <DesignClass>TFrame</DesignClass>
</DCCReference>

Производные кадры должны выглядеть так:

TFrame1 = class(TAncestorFrame)

В файлах Derived Frames .DFM должно быть указано:

inherited Frame1:TFrame1
person Unknown Coder    schedule 23.10.2009