2016-10-17 38 views
0

多くのサードパーティコンポーネントでDelphi 7を使用しています。私のメインスタブアプリケーションは、債権者、債務者、注文書などのようなさまざまなモジュールである多数のDLLを読み込みます。FindComponentが実行時に作成されたコンポーネントを見つけられない

私は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. ユーザーレポートを表示するには、[プレビュー]ボタンをクリックする - すべてのコードは、私が設計時にすべての基準を作成していた時に前に働いていた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'に設定します。コンポーネントが何かを不明瞭にしない限り、2行の間にペイントメッセージを処理しないでください。 –

答えて

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

これは間違った場所にある場合、私は謝ります..応答と答えを

おかげで、私は長年、多くのためにこれをやっていると私は非常に小さい何かを逃した信じることができません。

この、 gbSelectionCriteria.FindComponent(名前)<ならば、

ゼロFindComponent指定(名前)<>は、その後

私は通常、とそれを使用していないnilを>この、 されている必要がある場合コンポーネントをテストするための単なる1つの方法でした。 コンポーネントの可視性をfalseに設定してから、trueにすると、作成時にフリッカーが停止します。

おかげで再び..