代码之家  ›  专栏  ›  技术社区  ›  Serguzest

在对象检查器上显示tframe子体的其他属性

  •  9
  • Serguzest  · 技术社区  · 16 年前

    delphi对象检查器不按设计显示tframe子体的附加属性。 人们倾向于建议使用已知的技巧,该技巧通常用于在对象检查器上显示tform子体的属性。诀窍是:通过如下设计时包将tform子体的自定义模块注册到delphi ide:

    RegisterCustomModule(TMyFrame, TCustomModule);
    

    对象检查器可以用这种方式显示tframe子体实例的其他属性,但是当它嵌入到表单中时,它会丢失其帧行为。不可重新设计,不可能为其子组件实现事件,并且它接受子控件(它不接受)。但它在自己的设计领域表现正常。

    看起来,delphi ide提供的那些行为是专门为tframe提供的。它们可能不是一般的设施。

    有没有其他方法可以在不失去框架行为的情况下做到这一点?

    我在用Delphi2007


    @ Tondrej,

    阅读问题评论,提前谢谢。

    frameunit.dfm格式:

    object MyFrame: TMyFrame
      Left = 0
      Top = 0
      Width = 303
      Height = 172
      TabOrder = 0
      object Edit1: TEdit
        Left = 66
        Top = 60
        Width = 151
        Height = 21
        TabOrder = 0
        Text = 'Edit1'
      end
    end
    

    unit frameunit;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs, StdCtrls;
    
    type
      TBaseFrame = Class(TFrame)
      protected
        Fstr: string;
        procedure Setstr(const Value: string);virtual;
      published
        Property str:string read Fstr write Setstr;
      End;
    
      TMyFrame = class(TBaseFrame)
        Edit1: TEdit;
      private
        // This won't be called in designtime. But i need this to be called in designtime
        Procedure Setstr(const Value: string);override;
      end;
    
    implementation
    
    {$R *.dfm}
    
    { TBaseFrame }
    
    procedure TBaseFrame.Setstr(const Value: string);
    begin
      Fstr := Value;
    end;
    
    { TMyFrame }
    
    procedure TMyFrame.Setstr(const Value: string);
    begin
      inherited;
      Edit1.Text := Fstr;
      // Sadly this code won't work and Edit1 won't be updated in designtime.
    end;
    
    end.
    

    unit RegisterUnit;
    
    interface
    
    procedure Register;
    
    implementation
    
    uses
      Windows, DesignIntf, frameunit;
    
    procedure Register;
    var
      delphivclide: THandle;
      TFrameModule: TCustomModuleClass;
    begin
      delphivclide := GetModuleHandle('delphivclide100.bpl');
      if delphivclide <> 0 then
      begin
        TFrameModule := GetProcAddress(delphivclide, '@Vclformcontainer@TFrameModule@');
        if Assigned(TFrameModule) then
        begin
          RegisterCustomModule(frameunit.TBaseFrame, TFrameModule);
          // Just registering that won't cause Tmyframe to loose its frame behaviours
          // but additional properties won't work well.
    
          //RegisterCustomModule(frameunit.TMyFrame, TFrameModule);  
          // That would cause Tmyframe to lose its frame behaviours
          // But additional properties would work well.
    
        end;
      end;
    end;
    
    
    end.
    
    4 回复  |  直到 12 年前
        1
  •  4
  •   Ondrej Kelle    16 年前

    您正在为您的帧注册哪个自定义模块类? 你用的是哪个版本的Delphi?

    根据我在Delphi2007上的实验,似乎可以工作的自定义模块类是tframemodule。这个类包含在delphivclide100.bpl中。由于没有相应的delphivclide.dcp,您必须手动加载它:

    unit FrameTestReg;
    
    interface
    
    procedure Register;
    
    implementation
    
    uses
      Windows, DesignIntf,
      FrameTest;
    
    procedure Register;
    var
      delphivclide: THandle;
      TFrameModule: TCustomModuleClass;
    begin
      delphivclide := GetModuleHandle('delphivclide100.bpl');
      if delphivclide <> 0 then
      begin
        TFrameModule := GetProcAddress(delphivclide, '@Vclformcontainer@TFrameModule@');
        if Assigned(TFrameModule) then
          RegisterCustomModule(TTestFrame, TFrameModule);
      end;
    end;
    
    end.
    

    我的frametest单元非常简单,它没有frametest.dfm,只有新tframe子体的声明:

    unit FrameTest;
    
    interface
    
    uses
      Forms;
    
    type
      TTestFrame = class(TFrame)
      private
        FHello: string;
      published
        property Hello: string read FHello write FHello;
      end;
    
    implementation
    
    end.
    

    使用tframemodule类,到目前为止一切工作正常。我可以创建要包含在项目中的ttestframe的新子代,并在对象检查器中编辑其已发布属性,将此新子代的实例放在IDE中的窗体上,在对象检查器中编辑其新的已发布属性,在.dfm资源中为其子组件等编写事件处理程序。我可以看到实例的预期“inline”指令。 到目前为止我还没有遇到任何问题,也许这是解决办法。

        2
  •  1
  •   Mad Scientist    7 年前

    没必要用“黑客方式”

    uses
    ...
      DMForm,
      VCLFormContainer,
    ...
    
    procedure Register;
    begin
    ...
      RegisterCustomModule(TYourFrameClass, TFrameModule);   // for frames
      RegisterCustomModule(TYourModuleClass, TDataModuleCustomModule);   // for data modules
    ...
    end;
    

    还有另一种方法可以添加帧

    type
      TNestableWinControlCustomModule = class (TWinControlCustomModule)
      public
        function Nestable: Boolean; override;
      end;
    
    function TNestableWinControlCustomModule.Nestable: Boolean;
    begin
      Result := True;
    end;
    

    +

      RegisterCustomModule(TYourFrameClass, TNestableWinControlCustomModule);
    

    单元名称(在XE7中测试):

    tcustommodule=> 设计编辑器

    tdatamodulecustommodule=> 二甲基亚硝胺 (designide.dcp)

    TwinControlCustommodule=> 格式表 (designide.dcp)

    tframemodule=> VCL容器 (vcldesigner.dcp)

    我想是因为 火猴 应该可以用类似的方式 (查找) FMXDesigner.dcp公司 &检查记事本中的内容(amp;C++)

    PS。 在旧的delphi版本中,单元中有tdatamoduledesignercustommodule元类而不是tdatamodulecustommodule 小精灵

    PPS。 其他现有的元类名称:

    tcustomformcustommodule模块

    tidesourcemodulecustommodule

        3
  •  0
  •   Oliver Giesen    16 年前

    不,我不认为这是完全可能的。

    当我有类似的需求时,我通常做的是简单地将框架子体作为自己的组件安装。但是,这样做会丢失很多典型的框架行为(特别是在设计时),例如,您不能再直接操作子组件,对框架的更改也不再自动传播到在设计时使用它的表单-您必须首先重新编译包含框架的运行时包。

    从面向对象的角度来看,这也不算太糟。它实际上加强了实现隐藏的概念。您仍然可以通过框架本身的新属性和方法公开子组件的各个属性和功能。

        4
  •  0
  •   mmmmmm    13 年前
    procedure TMyFrame.Setstr(const Value: string);
    begin
      inherited;
      Edit1.Text := Fstr;
      // Sadly this code won't work and Edit1 won't be updated in designtime.
    end;
    

    我认为这是因为它不应该在设计时工作。您已将tbaseframe注册为自定义模块,因此它是tbaseframe的(而不是它的后代!)!!!)在设计时应可编辑的属性。DelphiIDE只知道您注册的类的已发布属性;它不知道您在项目中创建的任何子代和重写。要使代码在设计时工作,应将其包含在tbaseframe定义中:

    procedure TBASEFrame.Setstr(const Value: string);
    begin
      inherited;
      Edit1.Text := Fstr; 
    end;
    

    或者(除了tbaseframe之外)将tmyframe定义注册为自定义模块。

    试着理解:delphi ide在设计时只知道已经注册在里面的东西。这不是障碍,而是合乎逻辑的行为。