如何在DLL中获取组件类

时间:2013-03-09 16:12:37

标签: delphi dll

我正在制作一个包含许多子表单的mdi应用程序,其中一个是显示报表的表单。 在报表上,我使用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;

简单的问题是如何使用corecly编写代码cbstr:=(Form.Components[i] as TcxDBLookupComboBox).Text;而不会出现EInvalidCast错误?

顺便说一句,如果我在其他单元中编写此代码,则dll和bpl程序会出错,但如果我将该代码写入同一单元(单元报告),则代码可以正常工作。谢谢你的进步。

2 个答案:

答案 0 :(得分:3)

您的问题是DLL中的类与可执行文件中的类不同。你有两个这些类的实例,甚至认为它们是从相同的代码编译的。当编译器表示该对象不是您将其强制转换为的类时,编译器是准确的。你根本无法使用DLL共享Delphi类。

解决方案是:

  1. 将所有代码编译为单个可执行文件。
  2. 使用运行时包来共享类。
  3. 在您的方案中,将代码放入包中是不够的。问题是devexpresses类。您需要链接到使用运行时包的那些。因为您没有这样做,所以您有这些类的多个不同版本。

    您注意到is运算符的结果似乎与ClassName函数不一致。嗯,那是因为该类的所有不同版本都具有相同的名称。

    我还注意到您遇到的问题与之前的问题相同:How can I pass TForm to a DLL as parameter?您在此处接受的答案的解释和建议同样适用于此。

答案 1 :(得分:2)

如果您已使用(Foo is TSomething)类型检查,那么您知道foo是TSomething并且您可以使用静态广播:TSomething(Foo)

如果您尝试将此代码链接到另一个可执行文件或dll中,则可能没有包含正确的单位,如果它在运行时失败,并且如果它在运行时失败,则您没有打开BPL链接选项(使用运行时PACKAGES,并确保包名称列表已完成)。请记住,检查“某事是TSomething”,您正在将类声明与另一个活动对象的类进行比较。字符串名称未定义类。它实际上是链接到您的应用程序中的类型信息。

当您链接DLL(没有运行时包)时,您实际上可能已将TSomething链接到主EXE和DLL中,并且它们是具有相同名称且名称不重要的类的两个不同副本一点。当你比较身份时,没有办法在运行时知道它们是同一个东西。所以他们不是。

您可以按照您在屏幕上看到的方式来考虑代码。当它运行时,它被编译成代码,类型只是exe或DLL中的数据。所以TSomething-in-myexe.exe与TSomething-in-mydll.dll不是同一类。

如果希望它们相同,请为要在不同编译部分之间比较类型信息的所有位置启用“使用运行时包”(BPL)。特别是在非启用bpl的链接目标之间传递指针或对VCL类型的引用不会像你想象的那样工作。

您还应该确保运行时包列表包含定义您正在使用的类的包。 (TcxSomething可能是开发人员快速组件,请查找它所定义的BPL包。)