Link to home
Start Free TrialLog in
Avatar of bnz
bnz

asked on

Component Properties read component#2

Another question regarding properties.
I have a TControl property in my component, I place the component and a checkbutton on the form then assign then checkbutton to the control-property.

I then select the checkbox again and cut it using ctrl+x, bang I get a big error and have to close delphi. What can I do?
Avatar of gemarti
gemarti
Flag of United States of America image

Maybe you need to disassociate the checkbutton from your control when your app detects ctrl x.
how did you bind the two together? (...assign the checkbutton to the control-property...) Just undo what ever it is you did.

More information would be beneficial the the other experts and would probably get your problem solved quicker.
Avatar of bnz
bnz

ASKER

I just choose the checkbox in TControl property via Object Inspector.

I will post the code - it's a free component I'm working on. Hope it's not too big.

unit CheckGroupBox;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  //Hack to read protected properties  
  TControlFake = class(TControl);
  TButtonControlFake = class(TButtonControl);  

  TEnabledEvent = procedure(Sender: TObject; Enabled: boolean) of object;

  TCheckGroupBox = class(TGroupBox)
  private
    OldCaption: string;
    FPositionCheckComponent: Boolean;
    FOnEnabled: TEnabledEvent;
    FCheckComponent: TControl;
    FOldCheckComponentOnClick: TNotifyEvent;
    procedure SetCaption(const Value: TCaption);
    procedure SetCheckComponent(const Value: TControl);
    procedure CheckComponentOnClick(Sender: TObject);
    function CheckComponentChecked: boolean;
    procedure SetPositionCheckComponent(const Value: Boolean);
    function ComponentToString(Component: TComponent): string;
  protected
    procedure SetEnabled(Value: Boolean); override;
    procedure Loaded; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure Update; override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;    
  published
    property OnEnabled: TEnabledEvent read FOnEnabled write FOnEnabled;
    property Caption write SetCaption;
    property CheckComponent: TControl read FCheckComponent write SetCheckComponent;
    property PositionCheckComponent: Boolean read FPositionCheckComponent write SetPositionCheckComponent;
  end;

procedure Register;

implementation

{$R CheckGroupBox.Res}

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

constructor TCheckGroupBox.Create(AOwner: TComponent);
begin
  inherited;

  PositionCheckComponent := True;
  OldCaption := Caption;  
end;

procedure TCheckGroupBox.Loaded;
begin
  inherited;

  Update;
end;

procedure TCheckGroupBox.Update;
begin
  inherited;
  Caption := Caption;
  Left := Left;
  Top := Top;
  PositionCheckComponent := FPositionCheckComponent;
  Enabled := Enabled and CheckComponentChecked;
end;

procedure TCheckGroupBox.SetCaption(const Value: TCaption);
begin
  if Value <> '' then
    OldCaption := Value;

  //if FCheckComponent <> nil clear groupbox caption
  if FCheckComponent <> nil then
      inherited Caption := ''
  else
      inherited Caption := OldCaption;
end;

procedure TCheckGroupBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  //Update CheckComponent position
  PositionCheckComponent := FPositionCheckComponent;
end;

procedure TCheckGroupBox.SetCheckComponent(const Value: TControl);
begin
width := width +5;
  if Value is TCheckGroupBox then
    raise Exception.Create('Assigned TCheckGroupBox to itself');

  FCheckComponent := Value;

  if FCheckComponent <> nil then
  begin
    FCheckComponent.FreeNotification(Self);
    FCheckComponent.BringToFront;
    //Saves old eventhandler
    if Assigned( TControlFake(FCheckComponent).OnClick ) then
        FOldCheckComponentOnClick := TControlFake(FCheckComponent).OnClick;

    TControlFake(FCheckComponent).OnClick := CheckComponentOnClick;
    Update;
  end;
end;

procedure TCheckGroupBox.SetPositionCheckComponent(const Value: Boolean);
begin
  //Align check component at groupbox
  FPositionCheckComponent := Value;
  if Value and (FCheckComponent <> nil) then
  begin
    FCheckComponent.Left := Left + 8;
    FCheckComponent.Top  := Top - 3;
  end;
end;

procedure TCheckGroupBox.SetEnabled(Value: Boolean);
var
  i: integer;
begin
  inherited;

  //Disable all controls
  for i := 0 to ControlCount-1 do
    Controls[i].Enabled := Value and CheckComponentChecked;

  if Assigned(OnEnabled) then
    FOnEnabled(Self, Value);
end;

function TCheckGroupBox.CheckComponentChecked: boolean;
var
  S: string;
begin
  if FCheckComponent is TButtonControl then
    Result := TButtonControlFake(FCheckComponent).Checked
  else if FCheckComponent <> nil then
  //Read the properties of the CheckComponent, it must have a property named Checked
  begin
     S := ComponentToString(FCheckComponent);
     Result := Pos('Checked = True', S) > 0;
  end
  else
     Result := True;
end;

function TCheckGroupBox.ComponentToString(Component: TComponent): string;
var
  StrStream: TStringStream;
begin
    StrStream := TStringStream.Create(Result);
    try
      StrStream.WriteComponent(Component);
      StrStream.Position := 0;
      ObjectBinaryToText(StrStream, StrStream);
      StrStream.Position := 0;
      Result := StrStream.DataString;
    finally
      StrStream.Free;
    end;
end;

procedure TCheckGroupBox.CheckComponentOnClick(Sender: TObject);
begin
  Enabled := CheckComponentChecked;
  //Call old event
  if Assigned(FOldCheckComponentOnClick) then
    FOldCheckComponentOnClick(Self);
end;

end.
Avatar of bnz

ASKER

the width:=width+5 is just to see when the SetCheckComponent is called, it doesn't get called when I cut the component away.
I cannot seem to duplicate your problem.

I compiled the code. I did make a change to the compiler directive. I removed {$R GroupCheckBox.Res}.

I tried putting a Checkbox on the control and then ctrl-x...no problem.

Then I tried a radio button...still no problem


When you used the wizard to create the new control did you select TControl (Controls) or TControls (QControls)..I'm not sure what difference it would make but I selected TControl (Controls). I did not try the QControls....
Avatar of kretzschmar
you should override the notification-method,
and set your property to nil there if your checkbox tells you there that it will be removed
(Action = opRemove)

meikl ;-)
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of bnz

ASKER

Yes, very nice... thanks