8

フォームのrtlStreamingでランタイムエラーが発生し、TReader.ReadRootComponentの実行中に例外EClassNotFoundが発生しました。特定のエラーメッセージは「ClassnotfoundTActionList」です。

奇妙なことは:

  1. 私のメインフォームはアクションリストを使用しています。
  2. 楽しみのために、ActnList.pas(VCLソースフォルダーから)をプロジェクトに追加して、修正を試みました。

これは、数分前まで作業していたフォームをインスタンス化するときに発生します。私が行った変更は、いくつかのサブフレームコードにありました。ユニットテストとプロトタイプのために、いくつかのフレームをモックアップしているため、ifdefマーカーを使用してすべての実装セクションコードを削除しました。

プロジェクトにアクションリストクラスを追加しようとしましたが、さまざまなコンパイラとリンクオプションがある場合とない場合がありましたが、それでもこの例外が発生します。明らかに奇妙なことが起きています。この問題を解決するには、別の奇妙な方法があるはずです。

実際、本当に奇妙なことが起こっているようです。このエラーが発生すると、次の呼び出しスタックが発生します。

rtl.Classes.ClassNotFound('TActionList')
rtl.Classes.TReader.FindComponentClass(???)
rtl.Classes.FindExistingComponent
rtl.Classes.TReader.ReadComponent(nil)       /// NIL!? WHAT!!!!!
rtl.Classes.TReader.ReadDataInner(???)
rtl.Classes.TReader.ReadData(???)
rtl.Classes.TComponent.ReadState(???)
vcl.Controls.TControl.ReadState(???)
vcl.Controls.TWinControl.ReadState($60B9CF0)
vcl.Forms.TCustomForm.ReadState(???)
rtl.Classes.TReader.ReadRootComponent($606EB90)
rtl.Classes.TStream.ReadComponent($606EB90)
rtl.Classes.InternalReadComponentRes(???,???,$606EB90)
rtl.Classes.InitComponent(TComplexFormContainingFrames)

TReader.ReadDataInner(Instance:TComponent)では、nilは意図的なもののようです。

      while not EndOfList do ReadComponent(nil);

更新:この質問に対する答えは、メイソンが述べたように「シリアル化コンテキスト」を理解することだと思います。そして、私自身の愚かさを認める時が来ました。私は、フレームの親であることに気づかずに、プロジェクトからフレームの親を削除しました。TMyFrameParentasの型宣言をスタブすることで欠落を回避しましたTMyFrameParent = class(TFrame)。これにより、問題の条件が発生します。この例外が難解なケースでいつ発生するか、およびそれを修正する方法に注意することは将来本当に便利かもしれないと思うので、ここに質問を残します。特に、Masonは、「シリアル化コンテキスト」と、それらがクラス名検索にどのように適用されるかについて、非常に興味深い情報を持っています。

4

5 に答える 5

9

これは、クラスが現在の逆シリアル化コンテキストで見つからなかったことを意味します。すべての既存のクラスがすべてのロードに登録されているわけではありません。各フォームクラスには、使用するコンポーネントへの参照を含むRTTIがあります。これを機能させるには、フォーム(またはフレームの場合はフレーム)がプライベートタグの前に少なくとも1つのTActionListを宣言していることを確認してください。

TMyForm = class(TForm)
  ActionList: TActionList;
  OtherComponent: TSomeComponent;
private
  //whatever
public
  //whatever
end;
于 2011-09-02T18:40:09.650 に答える
2

Classes.RegisterClassを使用して、ストリーミングシステムで使用するクラスを登録します。ドキュメントからの引用

フォーム宣言で参照されるフォームクラスとコンポーネントクラス(インスタンス変数)は自動的に登録されます。インスタンスを保存する場合は、アプリケーションで使用されるその他のクラスは、RegisterClassを呼び出して明示的に登録する必要があります。クラスが登録されると、コンポーネントストリーミングシステムによってロードまたは保存できます。

于 2011-09-02T19:29:28.380 に答える
1

これは、あるプロジェクトから別のプロジェクトにフレームをコピーし、そのフレームが何かから継承し、継承を偽造したが、フレームdfmに「継承された」アイテムの説明を残した場合に発生するようです。次のようなアイテムです。

inherited ActionList: TActionList
  Left = 520
  Top = 576
end

これにより、メイソンが話していた「現在の逆シリアル化コンテキスト」が生成され、クラスは含まれません。1つの修正は、上記のすべての場合に、継承をオブジェクトに変更することです。

于 2011-09-02T19:52:28.737 に答える
0

DFMファイルにTLabel宣言が存在するが、対応するPASファイルに宣言がない場合、「EClassNotFound」エラーが発生しました。どういうわけか、フォームエディタが台無しになりました。

特定の「破損した」ラベルを除いて、フォームからすべてのラベルを削除するまで、エラーは表示されませんでした。そのラベルがパネルの下に隠されていたので、それを追い詰めることは困難でした。

簡単な解決策の1つは、フォームからそのラベルを(見つけたら)切り取り(ctrl + x)、貼り付けることです。今回は、フォームエディタがPASファイルにその宣言を正しく挿入します。

于 2018-11-11T20:44:15.610 に答える
0

このエラーを取得する別の方法があります。フォーム定義クラスの先頭に「public」を配置します。デフォルトでは、クラスメンバーは「公開」されています。フォーム宣言の先頭に誤って「public」を追加しましたが、実行時に複数の「Classnotfound」例外が生成されます。

于 2019-05-10T14:29:50.673 に答える