Come migliorare l'utilizzo di Delphi Frames
-
02-10-2019 - |
Domanda
Ho usato fotogrammi in Delphi per anni, e sono una delle caratteristiche più potenti della VCL, ma l'uso standard di loro sembra avere un po 'di rischio come ad esempio:
-
E 'facile da spostare accidentalmente o modificare i sub-componenti del telaio in forma di accoglienza di una cornice senza rendersi conto che si è 'ritocco' con il telaio - so che questo non pregiudica il codice cornice originale, ma non è in genere ciò che si vorrebbe.
-
Quando si lavora con il telaio si sta ancora esposti a suoi sub-componenti per l'editing visuale, anche quando questo telaio è anni e non deve essere toccato.
Così ho avuto modo di pensare ....
-
C'è un modo di 'raggruppamento' componenti in modo tale che le loro posizioni sono 'bloccate'? Questo sarebbe utile per le forme finite così come fotogrammi. Spesso altri sviluppatori restituiscono il codice a me dove solo i limiti della forma sono cambiati e anche loro non hanno intenzione alcuna variazione.
-
C'è un modo di trasformare un telaio e dei suoi componenti in un unico componente Delphi? In tal caso, le parti interne del telaio sarebbero completamente nascosti e la sua semplicità d'uso aumenterebbero ulteriormente.
Sono interessato a qualsiasi pensiero ...
Brian.
Soluzione
La registrazione i fotogrammi come risolve componente sia 1. e 2 .:
- i componenti sul telaio sono bloccati quando si mette che il controllo telaio su una forma o in un'altra struttura
- si otterrà un componente (in realtà: il controllo) che è possibile progettare visivamente
Ma: ci sono un paio di catture (che possono essere risolti, vedi link articolo), di cui il più importante è questa:
Quando si mette componenti sul telaio, e poi cadere il fotogramma come componente su un modulo di Delphi o telaio, i componenti sono visibili nella struttura Pane.
Il problema è che perché sono visibili nel riquadro Struttura, è possibile eliminare, causando violazioni di accesso.
Il trucco per risolvere questo non dimenticare il 'ciuffo' .
Ho imparato che preziosa lezione da Ray Konopka durante DelphiLive 2009.
Dato che la lezione è così prezioso, ho scritto un post sul blog su di esso che descrive in dettaglio.
La parte essenziale è questo piccolo pezzo di codice (maggiori dettagli nel post del blog):
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;
Spero che questo aiuti.
- Jeroen
Altri suggerimenti
Sì, basta registrarsi come componenti. : -)
Progetta la tua cornice normalmente e dopo questo registrarlo. Anche essere sicuri di non avere dipendenze indesiderate su diverse unità dal momento che questi sono collegati quando il 'componente' viene utilizzato. Inoltre è possibile aggiungere proprietà published
al fine di utilizzarli in oggetto Inspector in seguito. Si veda ad esempio il seguente codice generato dal IDE (vedi anche i miei commenti):
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;
Compila il suddetto in un pacchetto a scelta, installarlo e verificate palette dei componenti. : -)
HTH
Proprio per aumentare il contributo, nota che se si va a finestra Structure
e destro del mouse sul nome TFrame che si è scelto, e cliccare sul menu Add to Palete
.
Questo farà una fuori componente del telaio e non è necessario creare qualsiasi procedura Register
. ; -)
Sono quasi sempre la creazione di istanze telaio in codice. Questo è facile e ha funzionato bene per me finora.
Ho anche imbattuto in questo problema quando si cerca di utilizzare i frame come componenti. Ci sono varie possibilità per risolvere i problemi evidenti, ma tutti minano il principio di nascondere informazioni (tutti i sottocomponenti del telaio vengono esposti come proprietà pubblicate, che significa che tutti possano accedervi).
ho risolto implementando un generico "controllo frame" componente:
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.
Con questa classe, aggiungendo un fotogramma come componente diventa un processo in due fasi:
// 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;
...
Quando si utilizza questo metodo, l'utente del componente non vedrà i tuoi sotto-componenti.