2016-09-20 22 views
0

私はフォームを持っていて、 'MyPages'という名前の 'TPageControl'オブジェクトと 'MyButton'という名前の 'TButton'オブジェクトを持っていますその上にデザイン時間。 次に、 'TTabSheet'を拡張する 'TTab'という新しいクラスがあります。 'TTab'クラスには、以下のようなメンバ変数の1つとして 'TButton'オブジェクトがあります。私は「MyButtonという」をクリックすると Free Pascalのオブジェクトから別のオブジェクトにメッセージを渡すには

class TTab = class(TTabSheet) 
private 
    m_btnCloseTab: TButton; 
end; 

は、それはタブのinit(「m_btnCloseTab」をインスタンス化するように)、新しい「TTAB」オブジェクトを作成し、 実行時で「MyPages」にそれを追加します。

これは、TTab.Init(newCaption:AnsiString)プロシージャの外観です。

Procedure TTab.Init(newCaption: AnsiString); 
begin 
    Self.Caption:= newCaption; 
    m_btnCloseTab:= TButton.Create(nil); 
    with m_btnCloseTab do begin 
    Parent:= Self; 
    Left:= 10; 
    Top:= 10; 
    Caption:= 'Close Tab'; 
    Visible:= True; 
    OnClick:= @closeTab; 
    end; 
end; 

新しいタブが追加されました。閉じるボタンは、各タブにも表示されます。

各タブの[m_btnCloseTab]をクリックして、特定のタブを閉じるにはどうすればよいですか?

以下のようにTTabのデストラクタを(TTabSheetのデストラクタをオーバーライドして)定義すると、私は外部から呼び出すことができます。

Destructor TTab.Destroy; 
begin 
    if m_btnCloseTab <> nil then begin 
    m_btnCloseTab.Destroy; 
    m_btnCloseTab:= nil; 
    end; 
    inherited; 
end; 

しかし、私は、タブ内からデストラクタを呼び出すことはできません(まあ、できます)。私がそれを行うと、m_btnCloseTabオブジェクトが例外を返すように解放することはできません。これは、まだイベントハンドラであるためです。私がそれを解放しなければ、タブはきれいに閉じますが、メモリがリークします(私たちはm_btnCloseTabを解放しなかったので)。

デストラクタを 'TTab'の外部から呼び出すことができるようにイベントをトリガーする必要があると思います。私はそれをする方法を知らない。

ご協力いただければ幸いです。

ありがとうございました。

+0

すべてを正しく理解しているかどうかはわかりません。しかし、mbtnCloseTabを所有者(mbtn_CloseTab:= TButton.Create(self)、Create(nil)ではなく)で作成すると、ボタンはタブとともに自動的に破棄されます。また、TTabには、子プロセスが破棄され、mbtn_CloseTabをnilに設定できる通知メソッドが必要です。何らかの理由で。 –

+0

コメントをいただきありがとうございます(私はもう誰もFree Pascalを使用していないと考えていました)が、実際の結果には違いはありません。 create(nil)を使うと、m_btnCloseTabをデストラクタ内で自分で解放する必要があります。 Create(Self)を使うと、TTabクラスのデストラクタが自動的に行います。 通知方法とは何ですか?私はどのように実装しますか?私が思うことは、私がする必要があることです.C#のデリゲート関数のようなものです。あなたがチュートリアルやそれを行う方法のドキュメントに私を指すことができればそれを感謝します。 –

+0

あなたは間違っています。 Lazarusフォーラムにアクセスして、生きたパスカルのコミュニティを見てください。 –

答えて

0

通知方法は、LCLソース(もちろんデルファイ)でも利用できます。簡単な例はTLabeledEditです:これはTLabelを含む何らかの "TEdit"です。 Labelが破棄された場合、Labeledへの参照をnilに設定する必要があるため、LabeledEditに通知されます。さもなければ、TLabeledEditのデストラクタは再びラベルを破棄しようとします。

procedure TCustomLabeledEdit.Notification(AComponent: TComponent; 
    Operation: TOperation); 
begin 
    inherited Notification(AComponent, Operation); 
    if (AComponent = FEditLabel) and (Operation = opRemove) then 
    FEditLabel := nil; 
end; 

そして、ここで、あなたはあなたのケースでなければならないものを見ることができます:ここでの方法は、(ExtCtrlsから貼り付け)このようなものです

procedure TTab.Notification(AComponent: TComponent; 
    Operation: TOperation); 
begin 
    inherited Notification(AComponent, Operation); 
    if (AComponent = m_BtnCloseTab) and (Operation = opRemove) then 
    m_BtnCloseTab := nil; 
end; 

は、その通知を注意してください仮想メソッドであるとしなければなりませんコンポーネントのprotectedセクションで属性overrideで宣言してください。

+0

m_BtnCloseTabのonClickイベントハンドラからDestroyが呼び出されたときでもクラッシュします。 通知が正確に行うことを理解しようとしています。 通知イベントを呼び出すイベントは何ですか?通知手順は、新しいタブの作成を開始した時点から実際の殺害まで、何度も呼び出されました。 m_BtnCloseTab:= nil; は、クラッシュする直前にのみ呼び出されました。クラッシュすると、次のエラーが発生します。 プロジェクトproject1が例外クラス 'External:SIGSEGV'を発生させました。 アドレス40CDA8 –

+0

ボタンの所有者はまだゼロですか?私は、破壊されているオブジェクトは、最後に破壊するオブジェクトであるため、所有者に通知する必要があることをイメージできます。しかし、所有者が通知されない場合、通知する人はいません... - 通知はLCL(VCL)の中心に深く入り、TComponentによって導入されました。オペレーションopRemoveでは、TComponentが破棄されるたびに呼び出されます。 –

0

私はこのタスクに1つのボタンを使用します。

TTabからm_btnCloseTab宣言を取り出し、プライベートメインフォームに入れます。メインフォームのFormCreateに続いて

m_btnCloseTab:=のTButton。作成(MyPages);

(上記の、それは最初に作成しなければならない場合は、フォーム上に配置されている部品であるMyPagesを前提としています。)

は、ボタンをあなたのTTABのために理にかなっている上部と左を与えます。

m_btnCloseTabは、MyPagesが解放されたときに解放され、フォームが閉じられたときに解放されます。

あなたがしなければならないのは、好きなように新しいタブを作成することだけです。フォーカスしている場合は、そのタブをボタンの親にするだけです。たとえば、MyPagesのOnChangeメソッドやそれが何であれ、これを行うことができます。

ボタンをクリックすると、TTab(親)のようになります。フリー。

しかし、あなたは、ボタンのOnClick内のローカル変数に親を保存する必要があるかもしれませんが言う:

TempTab:TTAB

そして、単に設定TempTab:nilに= TTAB(親)、設定ボタンの親その後、TempTab.Freeを呼び出します。

私はあなたのタブにもオーナーを与えます。このようにして、ユーザーがタブが開いた状態でフォームを閉じると(つまり、ボタンはクリックされていません)、所有者はフォームを解放します。

NEWTAB:

だから、あなたのようなタブを宣言= TTab.Create(MyPages)。

これはあなたの問題をすべて解決するはずです。ちょっとした手間がかかった後は、管理が簡単です。

最後に、.destroyを直接呼び出すのではなく、.Freeおよび/またはFreeAndNil()メソッドを使用します。

+0

それは良い考えです。私は自由な時間があるときにそれを試してみます。 当分の間、私の実際のプロジェクトでは、回避策が見つかりました。タブを解放するのではなく、タブの閉じるボタンをクリックしたときにTage.PageControl:= nilという設定でTPageControlから削除します。 タブの数が限られているため、メインフォームが閉じられたときに解放されるリストにこれらのタブが保持されるため、アプリケーションで大きな問題はありません。できるだけ多くのメモリを解放してからタブを非表示にして、アプリを重く感じさせないようにしています。 –

関連する問題