代码之家  ›  专栏  ›  技术社区  ›  Brian Frost

如何提高delphi框架的使用

  •  22
  • Brian Frost  · 技术社区  · 16 年前

    我在Delphi中使用框架已经很多年了,它们是VCL最强大的功能之一,但是标准使用它们似乎有一些风险,例如:

    1. 很容易意外地移动或编辑帧主体窗体上的帧子组件,而不会意识到您正在对帧进行“调整”-我知道这不会影响原始帧代码,但通常不是您想要的。

    2. 使用框架时,您仍会接触到其子组件进行可视化编辑,即使该框架已使用多年且不应触摸。

    所以我想…

    1. 有没有一种方法可以“分组”组件,使其位置“锁定”?这对成品和框架都很有用。通常,其他开发人员会将代码返回给我,其中只有表单边界发生了更改,甚至他们并不打算进行任何更改。

    2. 有没有任何方法可以将框架及其组件转换为单个delphi组件?如果是这样,框架内部将被完全隐藏,其可用性将进一步提高。

    我对任何想法都感兴趣…

    布莱恩。

    5 回复  |  直到 13 年前
        1
  •  22
  •   marco-fiset    13 年前

    将帧注册为组件可以解决这两个问题。2。

    1. 将框架控件放置在窗体或其他框架上时,框架上的组件将被锁定
    2. 您将得到一个可以可视化设计的组件(实际上是:控件)

    但是:有几个问题(可以解决,请参阅文章链接),其中最重要的是:

    当您将组件放在框架上,然后将该框架作为组件放在Delphi窗体或框架上时,组件在“结构”窗格中可见。

    问题是,因为它们在“结构”窗格中可见,所以可以删除它们,从而导致访问冲突。

    解决这个问题的诀窍 not forget the 'sprig' .
    我从中吸取了宝贵的教训 Ray Konopka 在期间 DelphiLive 2009。

    因为这课很有价值,我写了一篇 blog post 上面有详细的描述。

    关键部分是这段代码(更多细节请参见博客文章):

    procedure RegisterFramesAsComponents(const Page: string; const FrameClasses: array of TFrameClass);
    var
      FrameClass: TFrameClass;
    begin
      for FrameClass in FrameClasses do
      begin
        RegisterComponents(Page, [FrameClass]);
        RegisterSprigType(FrameClass, TComponentSprig);
      end;
    end;
    

    希望这有帮助。

    ——杰罗恩

        2
  •  17
  •   John Thomas    16 年前

    是的,只需将它们注册为组件。-)

    正常设计您的框架,并在此注册之后。此外,请确保对不同单元没有不必要的依赖关系,因为这些单元在使用“组件”时是链接的。也可以添加 published 属性,以便以后在对象检查器中使用它们。例如,请参见IDE生成的以下代码(另请参见我的注释):

    unit myUnit;
    
    uses
     ...
    
    type
      TmyComp = class(TFrame) //set your frame name to be the name your component 
        ToolBar1: TToolBar; //different components added in the form designer
        aliMain: TActionList;
        ...
      published //this section is added by hand
        property DataSource: TDataSource read FDataSource write SetDataSource; //some published properties added just for exemplification
        property DefFields: string read FDefFields write SetDefFields;
        ...
      end;
    
    
    procedure Register; //added by hand
    
    implementation
    
    {$R *.DFM}
    
    procedure Register;
    begin
      RegisterComponents('MyFrames', [TmyComp]); //register the frame in the desired component category
    end;
    

    在您选择的包中编译上面的代码,安装它并检查组件面板。-)

    高温高压

        3
  •  8
  •   NaN    14 年前

    为了增加贡献,请注意 Structure 窗口并右键单击您选择的tframe名称,然后单击 Add to Palete 菜单选项。 这将使一个组件出你的框架,你不需要创建任何 Register 程序。;-)

        4
  •  5
  •   Uli Gerhardt    16 年前

    我几乎总是在代码中创建框架实例。这很容易,到目前为止对我来说效果很好。

        5
  •  4
  •   Moritz Beutel    16 年前

    我在尝试使用框架作为组件时也遇到了这个问题。有各种各样的可能性来解决明显的问题,但它们都破坏了信息隐藏的原则(框架的所有子组件都公开为已发布的属性,这意味着每个人都可以访问它们)。

    我通过实现一个通用的“帧控制”组件解决了这个问题:

    unit RttiBrow.Cbde.FrameControl;
    
    interface
    
    uses
      Classes, Controls, Forms, Messages, ExtCtrls;
    
    type
      TFrameClass = class of TFrame;
    
      TComponentFrame = class (TFrame)
      private
        function GetClientHeight: Integer;
        function GetClientWidth: Integer;
        procedure SetClientHeight(const Value: Integer);
        procedure SetClientWidth(const Value: Integer);
        function GetOldCreateOrder: Boolean;
        procedure SetOldCreateOrder(const Value: Boolean);
        function GetPixelsPerInch: Integer;
        procedure SetPixelsPerInch(const Value: Integer);
        function GetTextHeight: Integer;
        procedure SetTextHeight(const Value: Integer);
      published
        { workarounds for IDE bug }
        property ClientWidth: Integer read GetClientWidth write SetClientWidth stored False;
        property ClientHeight: Integer read GetClientHeight write SetClientHeight stored False;
        property OldCreateOrder: Boolean read GetOldCreateOrder write SetOldCreateOrder stored False;
        property PixelsPerInch: Integer read GetPixelsPerInch write SetPixelsPerInch stored False;
        property TextHeight: Integer read GetTextHeight write SetTextHeight stored False;
      end;
    
      TComponentFrame<TFrameControl: class { TControl }> = class (TComponentFrame)
      private
        function GetController: TFrameControl; inline;
      protected
        property Controller: TFrameControl read GetController;
      public
        constructor Create (AOwner: TComponent); override;
      end;
    
      TFrameControl<T: TFrame> = class (TWinControl)
      private
        FFrame: T;
        function PlainFrame: TFrame;
      protected
        procedure CreateParams (var Params: TCreateParams); override;
        property Frame: T read FFrame;
      public
        constructor Create (AOwner: TComponent); override;
        property DockManager;
      published
        property Align;
        property Anchors;
        property BiDiMode;
        property Color;
        property Constraints;
        property Ctl3D;
        property UseDockManager default True;
        property DockSite;
        property DoubleBuffered;
        property DragCursor;
        property DragKind;
        property DragMode;
        property Enabled;
        property Font;
        property ParentBiDiMode;
        property ParentBackground;
        property ParentColor;
        property ParentCtl3D;
        property ParentDoubleBuffered;
        property ParentFont;
        property ParentShowHint;
        property ShowHint;
        property TabOrder;
        property TabStop;
        property Touch;
        property Visible;
        property OnAlignInsertBefore;
        property OnAlignPosition;
        property OnCanResize;
        property OnConstrainedResize;
        property OnDockDrop;
        property OnDockOver;
        property OnDragDrop;
        property OnDragOver;
        property OnEndDock;
        property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnGesture;
        property OnGetSiteInfo;
        property OnMouseActivate;
        property OnMouseDown;
        property OnMouseEnter;
        property OnMouseLeave;
        property OnMouseMove;
        property OnMouseUp;
        property OnResize;
        property OnStartDock;
        property OnStartDrag;
        property OnUnDock;
      end;
    
    
    implementation
    
    uses
      Windows;
    
    { TFrameControl<T> }
    
    constructor TFrameControl<T>.Create(AOwner: TComponent);
    begin
      inherited;
      FFrame := T (TFrameClass (T).Create (Self));
      PlainFrame.Parent := Self;
      PlainFrame.Align := alClient;
    end;
    
    procedure TFrameControl<T>.CreateParams(var Params: TCreateParams);
    begin
      inherited;
      Params.Style := Params.Style or WS_CLIPCHILDREN;
      Params.ExStyle := Params.ExStyle or WS_EX_CONTROLPARENT;
    end;
    
    function TFrameControl<T>.PlainFrame: TFrame;
    begin
      Result := FFrame; // buggy compiler workaround
    end;
    
    
    { TComponentFrame }
    
    function TComponentFrame.GetOldCreateOrder: Boolean;
    begin
      Result := False;
    end;
    
    function TComponentFrame.GetPixelsPerInch: Integer;
    begin
      Result := 0;
    end;
    
    function TComponentFrame.GetTextHeight: Integer;
    begin
      Result := 0;
    end;
    
    procedure TComponentFrame.SetClientHeight(const Value: Integer);
    begin
      Height := Value;
    end;
    
    procedure TComponentFrame.SetClientWidth(const Value: Integer);
    begin
      Width := Value;
    end;
    
    procedure TComponentFrame.SetOldCreateOrder(const Value: Boolean);
    begin
    end;
    
    procedure TComponentFrame.SetPixelsPerInch(const Value: Integer);
    begin
    end;
    
    procedure TComponentFrame.SetTextHeight(const Value: Integer);
    begin
    end;
    
    function TComponentFrame.GetClientHeight: Integer;
    begin
      Result := Height;
    end;
    
    function TComponentFrame.GetClientWidth: Integer;
    begin
      Result := Width;
    end;
    
    
    { TComponentFrame<TFrameControl> }
    
    constructor TComponentFrame<TFrameControl>.Create(AOwner: TComponent);
    begin
      inherited;
      Assert (AOwner <> nil);
      Assert (AOwner.InheritsFrom (TFrameControl));
    end;
    
    function TComponentFrame<TFrameControl>.GetController: TFrameControl;
    begin
      Result := TFrameControl (Owner);
    end;
    
    
    end.
    

    使用此类,将框架添加为组件将分为两个阶段:

      // frame unit
    type
      TFilteredList = class;
    
      TFrmFilteredList = class (TComponentFrame<TFilteredList>)
        // lots of published sub-components and event methods like this one:
        procedure BtnFooClick(Sender: TObject);
      end;
    
      TFilteredList = class (TFrameControl<TFrmFilteredList>)
      private
        procedure Foo;
      public
        // the component's public interface
      published
        // the component's published properties
      end;
    
    procedure Register;
    ...
    procedure Register;
    begin
      RegisterComponents ('CBDE Components', [TFilteredList]);
    end;
    
    procedure TFrmFilteredList.BtnFooClick(Sender: TObject);
    begin
      Controller.Foo;
    end;
    
    procedure TFilteredList.Foo;
    begin
    end;
    ...
    

    使用此方法时,组件的用户将看不到子组件。

    推荐文章