12

私は自分のカスタムコンポーネントのいくつかを書いてきました。いくつかはTCustomButton、TCustomListBoxなどの他のコンポーネントから単純に派生しています。

私が持っていてTMyButton = class(TCustomButton)、これがMyButtonという名前のユニットにあるとしましょう。このコンポーネントをパッケージ化して、IDEにインストールしました。

次に、新しい空のプロジェクトを作成し、TMyButtonをフォームにドロップします。プロジェクトをコンパイルすると、これらのユニットがインターフェイスセクションに自動的に追加されます。

.., StdCtrls, MyButton;

もちろんMyButtonが追加されることを期待していましたが、StdCtrlsが追加されないことを望んでいました。

それはそれほど悪くはありませんが、他のコンポーネントのいくつかはもっと悪いです。たとえば、1つはから派生しTCustomActionMainMenuBar、それをフォームに追加してコンパイルすると、次の余分なユニットが追加されます。

.., ToolWin, ActnMan, ActnCtrls, ActnMenus, MyMenu;

独自のコンポーネントを作成したかった理由の1つは、インターフェイスセクションに多くのユニット名が追加されないようにするためでした。そのため、独自のペイントを行い、デフォルトのプロパティなどを変更したいと思いました。

3つまたは4つのコンポーネントをフォームに追加するまでに、6〜10のユニット名が自動的に追加されますが、これは発生したくありません。

だから私の質問-IDEがインターフェースセクションにユニット名を自動的に追加するのを防ぐことは可能ですか?

自分のコンポーネントソースの実際の使用インターフェイスに「不要な」ユニット名がすでにあるという事実で十分だと思いました。私のコンポーネントは必要なユニットを知っているのに、なぜフォームのソースファイルが名前を知っている/含めることができる必要があるのですか?

MyButton, MyMenu;他のすべての一般的なユニット名を一緒に追加するのではなく、自動的に追加したいだけです。

4

4 に答える 4

10

コンポーネントは、仮想メソッドをオーバーライドして必要なユニットを句に挿入する派生TSelectionEditor実装(を参照)を登録した他のコンポーネントから派生している可能性があります。これを行う理由の1つは、これらのコンポーネントが他のユニットのタイプに依存するプロパティ/イベントを定義している場合です。RegisterSelectionEditor()TSelectionEditor.RequiresUnits()uses

于 2013-02-02T10:45:21.580 に答える
8

tl; dr;

これらのユニットの追加を防ぐことはできません。もう気にする必要はありません。


私のコンポーネントは必要なユニットを知っているのに、フォームのソースファイルが名前も知っている必要があるのはなぜですか?

あなたは正しいことも間違っていることもあります。もちろん、コードがコンポーネントの作成のみに制限されている場合は、そのコンポーネントが宣言されているユニットのみが必要になります。ランタイムとデザインタイムのいずれか。ただし、コードが開発され、祖先ユニットの型を必要とするイベントハンドラーを実装する場合は、コードでuses句にそれらのユニットが必要です。ランタイムとデザインタイムのいずれか。

例:TDBGridユニットからDBGridsフォームにaをドロップすると、ユニットもGrids追加されます。これは、特に、公開されたイベントのStateパラメーターのタイプが祖先ユニットで宣言されているためです。デザイナでそのイベントをダブルクリックすると、次のハンドラが追加されます。TGridDrawStateOnDrawDataCell

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
  Field: TField; State: TGridDrawState);
begin

end;

ここで、が存在するためTGridDrawState、このソースファイルはユニットを認識する必要がありますGrids

結論:マイナーな開発に使用されるユニットが多すぎる可能性がありますが、公開されているすべてのイベントの実装に使用されるユニットは常に十分です。


これが実際にどのように機能するかについて少し調べました。私はすでにレミーの答えに賛成しました。それがなければ私はそうすることを考えていなかったでしょうが、彼は実際には完全に正しくありません。

次のユニット例を考えてみましょう。

unit AwLabel;

interface

uses
  Classes, StdCtrls;

type
  TAwLabelStyle = (bsWide, bsTall);

  TAwLabel = class(TLabel)
  private
    FStyle: TAwLabelStyle;
  published
    property Style: TAwLabelStyle read FStyle write FStyle default bsWide;
  end;

implementation

end.

unit AwLabelEx;

interface

uses
  Classes, AwLabel;

type
  TAwLabelEx = class(TAwLabel);

implementation

end.

unit AwReg;

interface

uses
  AwLabel, AwLabelEx;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TAwLabel, TAwLabelEx]);
end;

ここで、コンポーネントをフォームにドロップしTAwLabelEx、ユニットAwLabelAwLabelEx追加すると、これが自動的に行われます。特別な関与は必要ありません。タイプにはAwLabel単位が必要ですTAwLabelStyle。この場合、イベントとは関係がないことに注意してください。残っている唯一の議論は、タイプがコンポーネント定義の公開されたセクションで使用されているということです。


ISelectionEditor.RequiresUnitsレミーが言ったようにどうですか?

TAwLabelStyle別のユニットに移動することを検討してください。

unit AwTypes;

interface

type
  TAwLabelStyle = (bsWide, bsTall);

implementation

end.

TAwLabelフォームにまたはTAwLabelExコンポーネントをドロップしても、AwTypesユニットは追加されません。最後のリンクから引用するには:

注:イベントが、クラス単位にもその祖先の単位にも含まれていないパラメーターの1つを持つ型を使用する可能性があります。この場合、RequiresUnitsを実装する選択エディターを登録して、イベントに必要なタイプを宣言するユニットごとに使用する必要があります。

それでは、選択エディターを登録しましょう。

unit AwReg;

interface

uses
  Classes, AwTypes, AwLabel, AwLabelEx, DesignIntf, DesignEditors;

type
  TAwLabelSelectionEditor = class(TSelectionEditor)
  public
    procedure RequiresUnits(Proc: TGetStrProc); override;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TAwLabel, TAwLabelEx]);
  RegisterSelectionEditor(TAwLabel, TAwLabelSelectionEditor);
end;

{ TAwLabelSelectionEditor }

procedure TAwLabelSelectionEditor.RequiresUnits(Proc: TGetStrProc);
begin
  Proc('AwTypes');
end;

end.

TAwLabelフォームにまたはTAwLabelExコンポーネントをドロップするAwTypesと、uses句にユニットが追加されるようになりました。

于 2013-02-02T19:53:09.240 に答える
4

TCustomActionMainMenuBarの継承ツリーは次のようになります。

System.Classes.TObject
System.Classes.TPersistent
System.Classes.TComponent
Vcl.Controls.TControl
Vcl.Controls.TWinControl
Vcl.ToolWin.TToolWindow
Vcl.ActnMan.TCustomActionBar
Vcl.ActnCtrls.TCustomActionDockBar
Vcl.ActnMenus.TCustomActionMenuBar
Vcl.ActnMenus.TCustomActionMainMenuBar
Vcl.ActnMenus.TActionMainMenuBar

フォームにコンポーネントを含めると、このツリーに表示されるすべてのユニットがuses句に描画され、保存するたびに再挿入されます。他の人が言っているように、Open Tools APIを使用することにより、コンポーネントに祖先を含まない他のユニットを含めることもできます。

于 2013-02-02T11:50:01.767 に答える
2

これは、コンポーネントの祖先が次のOpen Tools APIようなコードでuses句にいくつかのユニットを追加するために使用しているために発生しています。

uses
  ToolsAPI;

var
  currentProject: IOTAProject;
begin
  currentProject := GetActiveProject();
  currentProject.AddFile('StdCtrls.pas', True);

この質問もおもしろいと思うかもしれません。

于 2013-02-02T09:17:07.520 に答える