2016-10-17 3 views
0

Я использую Delphi 7 с рядом сторонних компонентов. Мое основное приложение-заглушка загружает несколько DLL, которые представляют собой различные модули, такие как кредиторы, должники, заказы на поставку и т. Д.FindComponent не находит компоненты, созданные в Runtime

У меня проблема с FindComponent(). 99% времени, он работает так, как должен. Но не для кода ниже.

Я пытался создать отчеты о форме, где я сохраняю все детали критериев выбора отчетов в таблице, а затем создаю критерии «на лету». Теоретически, он должен работать отлично, но по какой-то причине после создания компонентов FindComponent() не может их найти.

try 
    for i := gbSelectionCriteria.ComponentCount - 1 downto 0 do begin 
    ShowMessage(gbSelectionCriteria.Components[i].Name); 
    gbSelectionCriteria.Components[i].Free; 
    end; 

    // The above loop to remove the components from the groupbox works fine 

    // Creating the components works 

    fSysData.tbSelectionCriteria.First; 
    while not fSysData.tbSelectionCriteria.EOF do begin 
    case fSysData.tbSelectionCriteriaComponentType.AsInteger of 
     1 : begin // TMyAdvEdit 
     with TMyAdvEdit.Create(gbSelectionCriteria) do begin 
      Visible := False; 
      Parent := gbSelectionCriteria; 
      Name := fSysData.tbSelectionCriteriaName.AsString; 
      Left := fSysData.tbSelectionCriteriaLeft.AsInteger; 
      Top := fSysData.tbSelectionCriteriaTop.AsInteger; 
      Width := fSysData.tbSelectionCriteriaWidth.AsInteger; 
      LabelCaption := fSysData.tbSelectionCriteriaCaption.AsString; 
      LabelPosition := AdvEdit.lpLeftCenter; 
      LabelAlwaysEnabled := True; 
      LabelTransparent := True; 
      EditType := MyEditType[fSysData.tbSelectionCriteriaDataType.AsInteger]; 
      Text := ''; 

      OnClick := GetClickEvent(fSysData.tbSelectionCriteriaOnClickEvent.AsString); 
      OnDblClick := GetClickEvent(fSysData.tbSelectionCriteriaOnDblClickEvent.AsString); 
      OnKeyPress := GetKeyPressEvent(fSysData.tbSelectionCriteriaOnKeyPressEvent.AsString); 

      Visible := True; 

      // at this point findComponent finds nothing 

      if FindComponent(Name) <> nil then 
      ShowMessage(Name+' Created'); 
     end; 

     edEdit.OnClick := GetClickEvent(fSysData.tbSelectionCriteriaOnClickEvent.AsString); 
     edEdit.OnDblClick := GetClickEvent(fSysData.tbSelectionCriteriaOnDblClickEvent.AsString); 
     edEdit.OnKeyPress := GetKeyPressEvent(fSysData.tbSelectionCriteriaOnKeyPressEvent.AsString); 
     edEdit.Visible := True; 

     if FindComponent(edEdit.Name) <> nil then 
      ShowMessage(edEdit.Name+' Created'); 

     end; 

     2 : begin 
     end; 

     3 : begin 
     end; 

     4 : begin 
     end; 

     5 : begin 
     end; 

     6 : begin 
     end; 

     7 : begin 
     end; 

     8 : begin 
     end; 
    end; 

    fSysData.tbSelectionCriteria.Next; 
    end; 

    if fSysData.tbSysReports.Locate('ReportID', TAdvOfficeRadioButton(Sender).Tag, []) then begin 
    ReportData.ReportID := TAdvOfficeRadioButton(Sender).Tag; 
    ReportData.RepName := fSysData.tbSysReportsReportName.AsString; 
    ReportData.RepTitle := fSysData.tbSysReportsReportTitle.AsString; 
    ReportData.RepModule := fSysData.tbSysReportsModule.AsString; 
    ReportData.RepOrientation := fSysData.tbSysReportsReportOrientaton.AsString; 
    ReportData.RepPageIndex := fSysData.tbSysReportsCriteriaPageIndex.AsInteger; 
    end; 
finally 
end; 

Процесс докладов является:

  1. Пользователь нажимает на кнопку

    кнопки
  2. Радио создаются с помощью кнопки мыши

  3. пользователь нажимает кнопку радио

  4. Критерии отчета создается с помощью переключателя

  5. Пользователь вводит данные или DblClicks для выбора данных из списка.

  6. пользователь щелкает кнопку Preview для просмотра отчета - это где FindComponent терпит неудачу и возвращает NIL ..

Весь код работал раньше, когда я создал все критерии во время разработки, а затем добавил код выше.

Приведенный ниже код является частью того, что нужно добавить в запрос, чтобы получить данные для отчета:

if Length(TMyAdvEdit(FindComponent('edQuoteReference')).Text) > 0 then 
    qryTempTable.SQL.Add(' and q.UserReference = "' + TMyAdvEdit(FindComponent('edQuoteReference')).Text + '"'); 

Это первый раз FindComponent() терпит неудачу и не идет дальше.

Я пробовал различные способы создания компонентов, но каждый из них приводит к нарушению доступа, потому что компонент равен нулю.

Я искал всюду и старался все, о чем я мог думать, для решения этой проблемы.

+0

У меня есть совет. Вы наклеили здесь большое количество постороннего кода, и трудно увидеть дерево для деревьев. Было бы намного проще для всех, особенно для вас, если бы вы сократили код до минимальной формы. A [mcve]. –

+1

(1) Для вашей выгоды, пожалуйста, прекратите использование ** с **. Вы знаете, сколько раз вы случайно ссылались на члена вашего вновь созданного «TMyAdvEdit», не понимая этого? *** *** нет *** непреложной причины использовать ** с **; как минимум, вы всегда можете объявить локальную переменную, такую ​​как «NewAdvEdit» (2), я также не буду беспокоиться о «NewAdv.Visible: = False;» и позже установить ее в «True». Если ваш компонент не делает что-то неясное, вы не должны обрабатывать сообщение краски между этими двумя строками. –

ответ

6

FindComponent ищет компоненты, принадлежащие субъекту вызова метода. Вы вызываете FindComponent в форме, и поэтому ищите компонент среди тех компонентов, которыми владеет эта форма. Но элемент управления, который вы ищете, не принадлежит форме, он принадлежит gbSelectionCriteria, и это то, что вы передали конструктору элемента управления как аргумент Owner.

Если вы хотите использовать FindComponent так, как вы это делаете, вам необходимо сделать форму владельцем элементов управления, которые вы создаете. Затем, когда вы вызываете FindComponent на форму, он может найти элемент управления, потому что он является владельцем.Проходят Self конструктору элемента управления, чтобы сделать это свершилось:

TMyAdvEdit.Create(Self) 

У меня сделать некоторые довольно большие догадки здесь. Возможно, этот код фактически находится в модуле данных, а не в форме. Но основной принцип будет, как я уже сказал.

+0

@ Daryl990 в качестве дополнительной мысли, вы могли бы подумать, что 'FindComponent' является сокращенным способом вызова несуществующего, но более точно названного метода' FindOwnedComponent'. Обратите внимание, что [docs] (http://docwiki.embarcadero.com/Libraries/en/System.Classes.TComponent.FindComponent) действительно говорят: «Использовать FindComponent для определения того, принадлежит ли данный компонент другому», а также «другим «они означают тот, метод которого называется. – blong

1

Во-первых, я прошу прощения, если это находится в неправильном месте ..

Спасибо за ответ, и ответ, я делал это в течение многих лет, и я не могу поверить, что я пропустил что-то такое маленькое ,

это, если FindComponent (Имя) <> ноль, то

должен был это, если gbSelectionCriteria.FindComponent (Имя) <> ноль затем

Я обычно не использовать с того, был всего лишь одним способом протестировать создание компонента. Я установил видимость компонентов в false до и после этого до истины после ее создания, чтобы остановить мерцание по мере его создания.

Еще раз спасибо ..

Смежные вопросы