2016-10-17 1 views
0

J'utilise Delphi 7 avec un certain nombre de composants tiers. Mon application stub principale charge un certain nombre de DLL, qui sont divers modules comme les créanciers, les débiteurs, les commandes d'achat, et ainsi de suite.FindComponent ne trouve pas les composants créés au moment de l'exécution

J'ai un problème avec FindComponent(). 99% du temps, cela fonctionne comme il se doit. Mais pas pour le code ci-dessous. J'essayais de créer un rapport de formulaire, où je garde tous les détails des critères de sélection de rapports dans un tableau, puis je crée les critères à la volée. En théorie, cela devrait fonctionner parfaitement, mais pour une raison quelconque après la création des composants, FindComponent() ne peut pas les trouver.

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; 

Le processus des rapports est:

  1. utilisateur clique sur un bouton

  2. Les boutons radio sont créés à partir du bouton cliquez sur

  3. utilisateur clique sur un bouton radio

  4. Signaler les critères est créé à partir du bouton radio, cliquez sur

  5. L'utilisateur entre des données ou DblClicks pour sélectionner des données dans une liste.

  6. utilisateur clique bouton Aperçu pour consulter le rapport - c'est là FindComponent échoue et retourne nul ..

Tout le code a fonctionné avant quand j'avais créé tous les critères au moment de la conception, puis ajouté le code au dessus.

Le code ci-dessous fait partie de ce qui doit être ajouté à la requête pour récupérer les données du rapport:

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

Ceci est la première fois FindComponent() échoue et va pas plus loin.

J'ai essayé différentes façons de créer les composants, mais chacun d'entre eux entraîne une violation d'accès car le composant est nul.

J'ai regardé partout, et j'ai essayé tout ce que je peux penser, pour une solution à ce problème.

+0

J'ai quelques conseils. Vous avez collé une grande quantité de code étranger ici et il est difficile de voir le bois pour les arbres. Ce serait tellement plus facile pour tout le monde, surtout vous, si vous aviez réduit le code à une forme minimale. A [mcve]. –

+1

(1) Pour votre propre bénéfice, arrêtez d'utiliser ** avec **. Avez-vous une idée du nombre de fois où vous avez accidentellement référencé un membre de votre "TMyAdvEdit" nouvellement créé sans le savoir? Il n'y a *** *** *** aucune raison impérieuse d'utiliser ** avec **; au minimum, vous pouvez toujours déclarer une variable locale telle que 'NewAdvEdit' (2) Je ne voudrais pas non plus déranger' NewAdv.Visible: = False; 'et plus tard en le définissant à' True'. À moins que votre composant ne fasse quelque chose d'obscur, vous ne devriez pas traiter un message de peinture entre ces 2 lignes. –

Répondre

6

FindComponent recherche les composants appartenant à l'objet de l'appel de méthode. Vous appelez FindComponent sur le formulaire et recherchez le composant parmi les composants appartenant au formulaire. Mais le contrôle que vous recherchez n'est pas détenu par le formulaire, il appartient à gbSelectionCriteria, qui est ce que vous avez passé au constructeur du contrôle en tant qu'argument Owner.

Si vous souhaitez utiliser FindComponent comme vous le faites, vous devez donc rendre le formulaire propriétaire des contrôles que vous créez. Ensuite, lorsque vous appelez FindComponent sur le formulaire, il peut trouver le contrôle car il est le propriétaire.Passez Self au constructeur du contrôle pour faire passer ce venir:

TMyAdvEdit.Create(Self) 

Je vais avoir à faire quelques suppositions assez grandes ici. Ce code réside peut-être dans un module de données plutôt que dans un formulaire. Mais le principe essentiel sera comme je le dis.

+0

@ Daryl990 En guise de réflexion supplémentaire, vous pourriez considérer que 'FindComponent' est un raccourci pour appeler la méthode inexistante mais plus appropriée' FindOwnedComponent'. Notez que [docs] (http://docwiki.embarcadero.com/Libraries/en/System.Classes.TComponent.FindComponent) indique réellement "Use FindComponent pour déterminer si un composant donné appartient à un autre", et par "un autre". ils veulent dire celui dont on appelle la méthode. – blong

1

Tout d'abord, je vous présente mes excuses si cela est au mauvais endroit ..

Merci pour la réponse et la réponse, je l'ai fait cela pendant beaucoup d'années et je ne peux pas croire que je manqué quelque chose si petit .

cela, si FindComponent (Nom) <> nil puis

aurait dû être présent, si gbSelectionCriteria.FindComponent (Nom) <> nil puis

Je ne l'utilise pas normalement, il était juste un moyen de tester créer le composant. J'ai défini la visibilité des composants sur false avant, puis sur true après sa création pour arrêter le scintillement lors de sa création.

Merci encore ..