0

私は多くの子フォームを使用してmdiアプリケーションを作成していますが、そのうちの1つはレポートを表示するためのフォームです。レポートフォームでは、dllファイルを使用してフォーム上のすべてのコンポーネントを表示し、各コンポーネントの値を探します。これを行うには、次のコードを使用します。

// this code i write in dll or bpl file
procedure getReportParams(Form : Tform); stdcall;
var
i : integer;
str, cbstr : string;
b : boolean;
begin

for i:=0 to Form.ComponentCount-1 do
  begin
  str:=str+Form.Components[i].Name+' - '+Form.Components[i].ClassName+', ';
      if (Form.Components[i] is TcxLookupComboBox) then
          begin
          showmessage('test 1');

          // if i uncomment the code below, the program get error Einvalidcast 
          // cbstr:=(Form.Components[i] as TcxDBLookupComboBox).Text;
          // if (Form.Components[i] as TcxDBLookUpCombobox).Parent=Form.FindComponent('pnledit') then
          //     showmessage((Form.Components[i] as TcxDBLookUpCombobox).Name);
          end;
  end;
showmessage(str);
// this showmessage work well in dll, bpl, or other unit
if b then
showmessage(cbstr+' true') else showmessage(cbstr+' false');
end;

簡単な質問は、cbstr:=(Form.Components[i] as TcxDBLookupComboBox).Text;EInvalidCastエラーを取得せずにcoreclyでコードを作成する方法です。

ところで、このコードを他のユニットで書くと、dllとbplプログラムでエラーが発生しますが、同じユニットでそのコードを書くと(ユニットレポート)、コードはうまく機能します。よろしくお願いします。

4

2 に答える 2

3

問題は、DLLのクラスが実行可能ファイルのクラスと異なることです。同じコードからコンパイルされている場合でも、これらのクラスのインスタンスは2つあります。オブジェクトがキャスト先のクラスではないと言った場合、コンパイラーは正確です。DLLを使用してDelphiクラスを共有することはできません。

解決策は次のいずれかです。

  1. すべてのコードを単一の実行可能ファイルにコンパイルします。
  2. ランタイムパッケージを使用してクラスを共有します。

あなたのシナリオでは、コードをパッケージに入れるだけでは十分ではありません。問題はdevexpressesクラスです。ランタイムパッケージを使用しているものにリンクする必要があります。そうしていないので、それらのクラスの複数の異なるバージョンがあります。

is演算子の結果は、ClassName関数と矛盾しているように見えることに注意してください。それは、クラスのすべての異なるバージョンが同じ名前を持っているためです。

また、発生している問題は以前の質問と同じであることに注意してください。TFormをパラメータとしてDLLに渡すにはどうすればよいですか。 そこで受け入れた答えからの説明とアドバイスは、ここでも同様に当てはまります。

于 2013-03-09T18:14:56.287 に答える
2

すでに型チェックを使用している場合は、fooがであり、静的キャストを使用できること (Foo is TSomething)がわかります。TSomethingTSomething(Foo)

このコードを別の実行可能ファイルまたはdllにリンクしようとしている場合、コンパイルに失敗した場合は正しいユニットが含まれていない可能性があり、実行時に失敗した場合は、BPLリンクオプションをオンにしませんでした(ランタイムパッケージを使用、パッケージ名のリストが完全であることを確認してください)。「somethingisTSomething」をチェックすると、クラス宣言を別のライブオブジェクトのクラスと比較していることに注意してください。クラスは文字列名で定義されていません。これは、実際にはアプリケーションにリンクされているタイプ情報です。

(ランタイムパッケージなしで)DLLをリンクすると、実際にはTSomethingメインEXEとDLLにリンクされている可能性があり、それらは同じ名前のクラスの2つの異なるコピーであり、名前は1ビットではありません。IDを比較する場合、実行時にそれらが同じものであったことを知る方法はありません。そうではありません。

画面に書かれているのと同じようにコードについて考えます。実行すると、コードにコンパイルされ、タイプはexeまたはDLLのデータにすぎません。したがって、TSomething-in-myexe.exeはTSomething-in-mydll.dllと同じクラスではありません。

それらを同じにしたい場合は、異なるコンパイル済みパーツ間で型情報を比較するすべての場所で[ランタイムパッケージ(BPL)を使用]をオンにします。特に、bplが有効になっていないリンクされたターゲット間でVCLタイプへのポインターまたは参照を渡すと、思ったように機能しません。

また、ランタイムパッケージのリストに、使用しているクラスを定義するパッケージが含まれていることを確認する必要があります。(TcxSomethingはおそらくDeveloper Expressコンポーネントです。それが定義されているパッケージBPLを見つけてください。)

于 2013-03-09T18:13:00.567 に答える