2009-03-17 4 views
1

Ich versuche, eine Komponente wie TButtonedEdit von Delphi 2009 zu erstellen. Es ist ein benutzerdefiniertes TEdit, das links und rechts über zwei Schaltflächen verfügt.Mein Komponentenabsturz (TCustomEdit-Nachfolger)

In meiner Version verwende ich 2 TSpeedButton Objekte für die linken und rechten Tasten.

Bitte werfen Sie einen Blick auf meinen einfachen Code unten.

Es ist in Ordnung, es zu installieren, und ich kann es in der Komponente pallete sehen.

Aber aus einem unbekannten Grund kann ich meine Anwendung nicht speichern. Sobald ich die Komponente hinzugefügt habe und die Eigenschaften oder das Schreib-Ereignis geändert habe, wird Delphi sofort beendet (abgestürzt?).

Ich weiß nicht, was falsch ist ... aber das ist meine erste Komponente, die ich sicher nicht richtig bin.

Könnten Sie bitte herausfinden, was die Probleme sind?

Es scheint, dass Delphi 7.0 Probleme beim Speichern der .dfm, wenn ich diese Komponente verwenden.

Wenn ich diese Komponente zu einem Formular hinzugefügt habe, speichere es, Delphi fragt nach dem Speichern von "Unit1.pas", dann sofort beenden.

Vielen Dank.

unit MyButtonedEdit; 

interface 

uses 
    Windows, Buttons, Classes, Controls, Forms, Graphics, Messages, StdCtrls; 

type 
    TMyCustomButtonedEdit = class(TCustomEdit) 
    private 
    FLeftButton: TSpeedButton; 
    FRightButton: TSpeedButton; 

    procedure LeftButtonClick(Sender: TObject); 
    procedure RightButtonClick(Sender: TObject); 

    function GetLeftGlyph: TBitmap; 
    function GetRightGlyph: TBitmap; 

    procedure SetLeftGlyph(const g: TBitmap); 
    procedure SetRightGlyph(const g: TBitmap); 

    protected 
    procedure CreateParams(var Params: TCreateParams); override; 
    procedure DoLeftButtonClick; virtual; abstract; 
    procedure DoRightButtonClick; virtual; abstract; 
    function GetEnabled: boolean; override; 
    procedure SetEnabled(e: boolean); override; 
    procedure WMSize(var Message: TWMSize); message WM_SIZE; 
    property LeftButton: TSpeedButton read FLeftButton write FLeftButton; 
    property RightButton: TSpeedButton read FRightButton write FRightButton; 
    property Enabled: boolean read GetEnabled write SetEnabled; 
    property LeftGlyph: TBitmap read GetLeftGlyph write SetLeftGlyph; 
    property RightGlyph: TBitmap read GetRightGlyph write SetRightGlyph; 

    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    published 
    end; 


    TMyButtonedEdit = class(TMyCustomButtonedEdit) 
    private 
    FOnLeftButtonClick: TNotifyEvent; 
    FOnRightButtonClick: TNotifyEvent; 
    protected 
    procedure DoLeftButtonClick; override; 
    procedure DoRightButtonClick; override; 
    public 
    published 
    property LeftButton; 
    property RightButton; 
    property AutoSelect; 
    property BorderStyle; 
    property Color; 
    property Ctl3d; 
    property DragCursor; 
    property DragMode; 
    property Enabled; 
    property Font; 
    property LeftGlyph; 
    property RightGlyph; 
    property HideSelection; 
    property ParentColor; 
    property ParentCtl3D; 
    property ParentFont; 
    property ParentShowHint; 
    property PopupMenu; 
    property ReadOnly; 
    property ShowHint; 
    property TabOrder; 
    property Text; 
    property Visible; 
    property OnLeftButtonClick: TNotifyEvent read FOnLeftButtonClick write FOnLeftButtonClick; 
    property OnRightButtonClick: TNotifyEvent read FOnRightButtonClick write FOnRightButtonClick;  
    property OnChange; 
    property OnClick; 
    property OnDblClick; 
    property OnDragDrop; 
    property OnDragOver; 
    property OnEndDrag; 
    property OnEnter; 
    property OnExit; 
    property OnKeyDown; 
    property OnKeyPress; 
    property OnKeyUp; 
    property OnMouseDown; 
    property OnMouseMove; 
    property OnMouseUp; 
    property OnStartDrag; 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('MyComponents',[TMyButtonedEdit]); 
end; 

{ TMyCustomButtonedEdit } 

constructor TMyCustomButtonedEdit.Create(AOwner: TComponent); 
begin 
    inherited; 
    ControlStyle := ControlStyle - [csSetCaption]; 

    FLeftButton := TSpeedButton.Create(self); 
    with FLeftButton do begin 
    Parent := self; 
    TabStop := false; 
    Visible := true; 
    OnClick := LeftButtonClick; 
    end; 

    FRightButton := TSpeedButton.Create(self); 
    with FRightButton do begin 
    Parent := self; 
    TabStop := false; 
    Visible := true; 
    OnClick := RightButtonClick; 
    end; 
end; 

destructor TMyCustomButtonedEdit.Destroy; 
begin 
    FLeftButton.Free; 
    FRightButton.Free; 
    inherited; 
end; 

procedure TMyCustomButtonedEdit.CreateParams(var Params: TCreateParams); 
begin 
    inherited CreateParams(Params); 
    Params.Style := Params.Style or WS_CLIPCHILDREN; 
end; 

function TMyCustomButtonedEdit.GetEnabled: boolean; 
begin 
    result := inherited Enabled; 
end; 

function TMyCustomButtonedEdit.GetLeftGlyph: TBitmap; 
begin 
    result := FLeftButton.Glyph; 
end; 

function TMyCustomButtonedEdit.GetRightGlyph: TBitmap; 
begin 
    result := FRightButton.Glyph; 
end; 

procedure TMyCustomButtonedEdit.LeftButtonClick(Sender: TObject); 
begin 
    DoLeftButtonClick; 
    SetFocus; 
end; 

procedure TMyCustomButtonedEdit.RightButtonClick(Sender: TObject); 
begin 
    DoRightButtonClick; 
    SetFocus; 
end; 

procedure TMyCustomButtonedEdit.SetEnabled(e: boolean); 
begin 
    inherited Enabled := e; 
    FLeftButton.Enabled := e; 
    FRightButton.Enabled := e; 
end; 

procedure TMyCustomButtonedEdit.SetLeftGlyph(const g: TBitmap); 
begin 
    FLeftButton.Glyph := g; 
end; 

procedure TMyCustomButtonedEdit.SetRightGlyph(const g: TBitmap); 
begin 
    FRightButton.Glyph := g; 
end; 

procedure TMyCustomButtonedEdit.WMSize(var Message: TWMSize); 
var 
    b: integer; 
begin 
    if (BorderStyle = bsSingle) and not Ctl3d then 
    b := 1 
    else 
    b := 0; 
    FLeftButton.Top := b; 
    FLeftButton.Height := ClientHeight - b * 2; 
    FLeftButton.Width := FLeftButton.Height; 
    FLeftButton.Left := b; 

    FRightButton.Top := b; 
    FRightButton.Height := ClientHeight - b * 2; 
    FRightButton.Width := FRightButton.Height; 
    FRightButton.Left := ClientWidth - FRightButton.Width - b; 
end; 

{ TMyButtonedEdit } 

procedure TMyButtonedEdit.DoLeftButtonClick; 
begin 
    inherited; 
    if Assigned(FOnLeftButtonClick) then 
    FOnLeftButtonClick(Self); 
end; 

procedure TMyButtonedEdit.DoRightButtonClick; 
begin 
    inherited; 
    if Assigned(FOnRightButtonClick) then 
    FOnRightButtonClick(Self); 
end; 

end. 

Antwort

0

Es ist eine lange Zeit, da ich jede Komponente Entwicklung getan habe, aber ich glaube ich zu erinnern, dass der Eigentümer einer Komponente normalerweise die Besitzer Eltern sein sollte, nicht die Eltern selbst, so

FLeftButton := TSpeedButton.Create(self); 

sollte be:

FLeftButton := TSpeedButton.Create(AOwner); 
+0

Nicht in Composite-Komponenten.Was Sie beschreiben, sind Komponenten, die in der Entwurfszeit an ein Formular angehängt werden. Dies ist das IDE-Verhalten von Delphi. Aber selbst in den Composite-Komponenten von VCL ist der Composite der Besitzer von Child-Komponenten - mit anderen Worten, der Composite. –

7

Ihr Problem ist, rufen Sie auf Enabled. Passenderweise ist der Fehler, den Sie tatsächlich vor dem Absturz erhalten,

Sie haben sich in eine Endlosschleife.

Um Komponenten zu debuggen, ist es das Beste, sie zur Laufzeit zu erstellen. Dies ist viel einfacher zu debuggen als zu Entwurfszeit zu versuchen. Um zur Laufzeit zu debuggen habe ich das getan.

var 
BE : TMyButtonedEdit; 
begin 
BE := TMyButtonedEdit.Create(self); 
be.Parent := self; 
be.Visible := true; 

Wenn ich Ihre Kontrolle erstellt dauerte es eine lange Zeit, dann habe ich den Fehler Stackoverflow in der Regel eine Endlos-Schleife bedeutet. Ich habe immer noch nicht ganz herausgefunden, warum, aber ich arbeite daran.

Lösung.

Sie können keine Eigenschaften erben (gut Sie können - siehe Kommentare), so dass Ihr Anruf

inherited Enabled; 

tatsächlich wurde selbst aufruft. Was Sie tun müssen, ist

inherited GetEnabled; 

Vielen Dank für das mentale Training.

+0

Gleiches gilt für SetEnabled –

+0

Sie können geerbte Eigenschaften tatsächlich aufrufen. Es ist der einzige Weg, dies manchmal zu tun, wenn der Accessor privat und nicht geschützt ist. In diesem Fall besteht das Problem darin, dass der Accessor virtuell ist. (Zum Glück können Sie keine privaten virtuellen Methoden haben, oder das könnte ein echtes Durcheinander sein ...);) –