[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Creating an onClick Handler for a dynamically created button in an external unit procedure

Posted on 2006-06-01
22
Medium Priority
?
233 Views
Last Modified: 2010-04-05
What I'm trying to do:

Create a procedure in a unit which can be called in the code from another unit and when called a panel is dynamically created on the calling form with a button at the bottom which closes it (note that the docking panel 'X' is no use as it is too small for touchscreen use) Bascially the panel will be used for popup help messages.

The code is in a procedure within the unit 'RoonyMisc' - note that this unit is for called procedures only and therefore has no form attached. The units which call 'RoonyMisc' have it in the USES clause. In the case of this particular procedure 'CreateHelpBox', it is called when the appropriate form element is double-clicked and should be closed when the button with in it which is also dynamically created is clicked.

What I Need:

OK, the problem i'm having is with the ability to assign a command to an onclick handler attached to the button - i don't know how to create an onclick handler within a unit with no visual form and where no visual form is wanted, as is the case with 'RoonyMisc'. Secondly the command within the handler should destroy the panel which was dynamically created in the first place. How how how???

My code is below:

RoonyMisc Code:

Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
var FramePanel : TPanel;
var TitlePanel : TPanel;
var BarPanelLeft : TPanel;
var BarPanelRight : TPanel;
var ClosePanel : TPanel;
var CloseButton : TButton;
begin

        FramePanel := TPanel.Create(OwnerWindow);
        FramePanel.Parent := OwnerWindow;
        FramePanel.Top := HBTop;
        FramePanel.Left := HBLeft;
        FramePanel.Width := HBWidth;
        FramePanel.Height:= HBHeight;
        FramePanel.Color := clBlue;
        FramePanel.BevelInner := bvLowered;
        FramePanel.BevelOuter := bvRaised;
        FramePanel.Visible := True;
        FramePanel.Enabled := True;
        FramePanel.FullRepaint := True;
        FramePanel.DragMode := dmAutomatic;
        FramePanel.DragKind := dkDock;

        TitlePanel := TPanel.Create(OwnerWindow);
        TitlePanel.Parent := FramePanel;
        TitlePanel.Top := 2;
        TitlePanel.Left := 2;
        TitlePanel.Width := FramePanel.Width - 4;
        TitlePanel.Height := 30;
        TitlePanel.Color := clYellow;
        TitlePanel.BevelInner := bvNone;
        TitlePanel.BevelOuter := bvNone;
        TitlePanel.Visible := True;
        TitlePanel.Enabled := True;
        TitlePanel.FullRepaint := True;
        TitlePanel.Font.Name := 'Arial';
        TitlePanel.Font.Size := 11;
        TitlePanel.Font.Style := [fsBold];
        TitlePanel.Font.Color := clBlue;
        TitlePanel.Caption := HBCaption;

        BarPanelLeft := TPanel.Create(OwnerWindow);
        BarPanelLeft.Parent := TitlePanel;
        BarPanelLeft.Top := 0;
        BarPanelLeft.Left := 0;
        BarPanelLeft.Width := 40;
        BarPanelLeft.Height := 30;
        BarPanelLeft.Color := clFuchsia;
        BarPanelLeft.BevelInner := bvNone;
        BarPanelLeft.BevelOuter := bvNone;
        BarPanelLeft.Visible := True;
        BarPanelLeft.Enabled := True;
        BarPanelLeft.FullRepaint := True;
        BarPanelLeft.Font.Name := 'Arial';
        BarPanelLeft.Font.Size := 11;
        BarPanelLeft.Font.Style := [fsBold];
        BarPanelLeft.Font.Color := clYellow;
        BarPanelLeft.Caption := HBBarChar;

        BarPanelLeft := TPanel.Create(OwnerWindow);
        BarPanelLeft.Parent := TitlePanel;
        BarPanelLeft.Top := 0;
        BarPanelLeft.Left := TitlePanel.Width - 40;
        BarPanelLeft.Width := 40;
        BarPanelLeft.Height := 30;
        BarPanelLeft.Color := clFuchsia;
        BarPanelLeft.BevelInner := bvNone;
        BarPanelLeft.BevelOuter := bvNone;
        BarPanelLeft.Visible := True;
        BarPanelLeft.Enabled := True;
        BarPanelLeft.FullRepaint := True;
        BarPanelLeft.Font.Name := 'Arial';
        BarPanelLeft.Font.Size := 11;
        BarPanelLeft.Font.Style := [fsBold];
        BarPanelLeft.Font.Color := clYellow;
        BarPanelLeft.Caption := HBBarChar;

        ClosePanel := TPanel.Create(OwnerWindow);
        ClosePanel.Parent := FramePanel;
        ClosePanel.Top := FramePanel.Height - 60;
        ClosePanel.Left := 2;
        ClosePanel.Width := FramePanel.Width - 4;
        ClosePanel.Height := 58;
        ClosePanel.Color := clRed;
        ClosePanel.BevelInner := bvNone;
        ClosePanel.BevelOuter := bvNone;
        ClosePanel.Visible := True;
        ClosePanel.Enabled := True;
        ClosePanel.FullRepaint := True;

        CloseButton := TButton.Create(OwnerWindow);
        CloseButton.Parent := ClosePanel;
        CloseButton.Left := 8;
        CloseButton.Top := 9;
        CloseButton.Height := 40;
        CloseButton.Width :=  FramePanel.Width - 20;
        CloseButton.Font.Name := 'Arial';
        CloseButton.Font.Size := 11;
        CloseButton.Font.Style := [fsBold];
        CloseButton.Caption := 'CLOSE';
        CloseButton.Enabled := True;
        CloseButton.Visible := True;
        //CloseButton.OnClick := ;

end;

Unit1 Code:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, RoonyMisc;
:
:
procedure TForm1.Panel2DblClick(Sender: TObject);   // double-click panel2 to throw up the help box
begin
   CreateHelpBox(self,100,100,250,250,'HELP','?','HELPME!');    
end;
0
Comment
Question by:loonyroony
  • 11
  • 11
22 Comments
 
LVL 28

Expert Comment

by:2266180
ID: 16806238
1st: replace all
*Panel := TPanel.Create(OwnerWindow);
with
*Panel := TPanel.Create(FramePanel);
except for the framepanel
then
 CloseButton := TButton.Create(OwnerWindow);
with
 CloseButton := TButton.Create(ClosePanel);
then
//CloseButton.OnClick := ;
with
  CloseButton.OnClick := myonlick;

and define:

procedure myonclick(Sender:TObject);
begin
  with sender as TButton do// this is correct since we only use this for the close button. in otehr cases, put some if's
    ((owner as TPanel).owner) asTPanel).free;// should hide it and destroy all other resources that you created because framepanel owns them;)
end;

I hope there won't be any problems running this :D
0
 

Author Comment

by:loonyroony
ID: 16806305
For the line:

CloseButton.OnClick := myonlick;

I got the following error:

[Error] RoonyMisc.pas(176): Incompatible types: 'method pointer and regular procedure'


I put the declaration for myonclick just above IMPLEMENTATION.

What have I done wrong?
0
 
LVL 28

Expert Comment

by:2266180
ID: 16806450
a yes .. the myonclick should be part of a component. hm... let me get back to you in a few minutes. I'll transform your code in a small compnent so that everything will be ok
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 28

Expert Comment

by:2266180
ID: 16806536
something like this should do it:

type TMyDialog=class(TPanel)
     private
       TitlePanel : TPanel;
       BarPanelLeft : TPanel;
//       BarPanelRight : TPanel;
       ClosePanel : TPanel;
       CloseButton : TButton;
       procedure myonclick(sender:TObject);
     public
       constructor Create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String); overload;
     end;

constructor TMyDialog.create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
begin
  inherited Create(OwnerWindow);
  Parent := OwnerWindow;
  Top := HBTop;
  Left := HBLeft;
  Width := HBWidth;
  Height:= HBHeight;
  Color := clBlue;
  BevelInner := bvLowered;
  BevelOuter := bvRaised;
  Visible := True;
  Enabled := True;
  FullRepaint := True;
  DragMode := dmAutomatic;
  DragKind := dkDock;

  TitlePanel := TPanel.Create(self);
  TitlePanel.Parent := self;
  TitlePanel.Top := 2;
  TitlePanel.Left := 2;
  TitlePanel.Width := Width - 4;
  TitlePanel.Height := 30;
  TitlePanel.Color := clYellow;
  TitlePanel.BevelInner := bvNone;
  TitlePanel.BevelOuter := bvNone;
  TitlePanel.Visible := True;
  TitlePanel.Enabled := True;
  TitlePanel.FullRepaint := True;
  TitlePanel.Font.Name := 'Arial';
  TitlePanel.Font.Size := 11;
  TitlePanel.Font.Style := [fsBold];
  TitlePanel.Font.Color := clBlue;
  TitlePanel.Caption := HBCaption;

  BarPanelLeft := TPanel.Create(TitlePanel);
  BarPanelLeft.Parent := TitlePanel;
  BarPanelLeft.Top := 0;
  BarPanelLeft.Left := 0;
  BarPanelLeft.Width := 40;
  BarPanelLeft.Height := 30;
  BarPanelLeft.Color := clFuchsia;
  BarPanelLeft.BevelInner := bvNone;
  BarPanelLeft.BevelOuter := bvNone;
  BarPanelLeft.Visible := True;
  BarPanelLeft.Enabled := True;
  BarPanelLeft.FullRepaint := True;
  BarPanelLeft.Font.Name := 'Arial';
  BarPanelLeft.Font.Size := 11;
  BarPanelLeft.Font.Style := [fsBold];
  BarPanelLeft.Font.Color := clYellow;
  BarPanelLeft.Caption := HBBarChar;

  BarPanelLeft := TPanel.Create(TitlePanel);
  BarPanelLeft.Parent := TitlePanel;
  BarPanelLeft.Top := 0;
  BarPanelLeft.Left := TitlePanel.Width - 40;
  BarPanelLeft.Width := 40;
  BarPanelLeft.Height := 30;
  BarPanelLeft.Color := clFuchsia;
  BarPanelLeft.BevelInner := bvNone;
  BarPanelLeft.BevelOuter := bvNone;
  BarPanelLeft.Visible := True;
  BarPanelLeft.Enabled := True;
  BarPanelLeft.FullRepaint := True;
  BarPanelLeft.Font.Name := 'Arial';
  BarPanelLeft.Font.Size := 11;
  BarPanelLeft.Font.Style := [fsBold];
  BarPanelLeft.Font.Color := clYellow;
  BarPanelLeft.Caption := HBBarChar;

  ClosePanel := TPanel.Create(self);
  ClosePanel.Parent := self;
  ClosePanel.Top := Height - 60;
  ClosePanel.Left := 2;
  ClosePanel.Width := Width - 4;
  ClosePanel.Height := 58;
  ClosePanel.Color := clRed;
  ClosePanel.BevelInner := bvNone;
  ClosePanel.BevelOuter := bvNone;
  ClosePanel.Visible := True;
  ClosePanel.Enabled := True;
  ClosePanel.FullRepaint := True;

  CloseButton := TButton.Create(ClosePanel);
  CloseButton.Parent := ClosePanel;
  CloseButton.Left := 8;
  CloseButton.Top := 9;
  CloseButton.Height := 40;
  CloseButton.Width :=  Width - 20;
  CloseButton.Font.Name := 'Arial';
  CloseButton.Font.Size := 11;
  CloseButton.Font.Style := [fsBold];
  CloseButton.Caption := 'CLOSE';
  CloseButton.Enabled := True;
  CloseButton.Visible := True;
  CloseButton.OnClick := myonclick;
end;

procedure TMyDialog.myonclick(Sender:TObject);
begin
  with sender as TButton do// this is correct since we only use this for the close button. in otehr cases, put some if's
    (((owner as TPanel).owner) as TPanel).free;// should hide it and destroy all other resources that you created because framepanel owns them;)
end;

Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
var FramePanel : TMyDialog;
begin
  FramePanel := TMyDialog.Create(OwnerWindow,HBLeft,HBTop,HBWidth,HBHeight,HBCaption,HBBarChar,HBText);
  // do whatever with FramePanel;
end;
0
 

Author Comment

by:loonyroony
ID: 16806812
Wow that looks good :-) last question though - since I haven't created components before, can all this code go into the RoonyMisc unit or does it need to be put into separate files?
0
 
LVL 28

Expert Comment

by:2266180
ID: 16806850
you can put it in any unit just as it is. but if you want the component to be visible outside the unit, then you will have to move the declaration type of the component in the interface section.
0
 

Author Comment

by:loonyroony
ID: 16806938
OK we're very close now! everything is almost working apart from one thing - there's an access violation when the panel is closed! Any ideas?
0
 
LVL 28

Expert Comment

by:2266180
ID: 16806972
hm.. that depends. how are you using it? are you by any chanse freeing it again somewhere?
0
 
LVL 28

Expert Comment

by:2266180
ID: 16806991
this is my test application. works just fine: (create a new app, add a button, duble click on the button (so the event is created) and then replace everything with:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses extctrls;

type TMyDialog=class(TPanel)
     private
       TitlePanel : TPanel;
       BarPanelLeft : TPanel;
//       BarPanelRight : TPanel;
       ClosePanel : TPanel;
       CloseButton : TButton;
       procedure myonclick(sender:TObject);
     public
       constructor Create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String); overload;
     end;

constructor TMyDialog.create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
begin
  inherited Create(OwnerWindow);
  Parent := OwnerWindow;
  Top := HBTop;
  Left := HBLeft;
  Width := HBWidth;
  Height:= HBHeight;
  Color := clBlue;
  BevelInner := bvLowered;
  BevelOuter := bvRaised;
  Visible := True;
  Enabled := True;
  FullRepaint := True;
  DragMode := dmAutomatic;
  DragKind := dkDock;

  TitlePanel := TPanel.Create(self);
  TitlePanel.Parent := self;
  TitlePanel.Top := 2;
  TitlePanel.Left := 2;
  TitlePanel.Width := Width - 4;
  TitlePanel.Height := 30;
  TitlePanel.Color := clYellow;
  TitlePanel.BevelInner := bvNone;
  TitlePanel.BevelOuter := bvNone;
  TitlePanel.Visible := True;
  TitlePanel.Enabled := True;
  TitlePanel.FullRepaint := True;
  TitlePanel.Font.Name := 'Arial';
  TitlePanel.Font.Size := 11;
  TitlePanel.Font.Style := [fsBold];
  TitlePanel.Font.Color := clBlue;
  TitlePanel.Caption := HBCaption;

  BarPanelLeft := TPanel.Create(TitlePanel);
  BarPanelLeft.Parent := TitlePanel;
  BarPanelLeft.Top := 0;
  BarPanelLeft.Left := 0;
  BarPanelLeft.Width := 40;
  BarPanelLeft.Height := 30;
  BarPanelLeft.Color := clFuchsia;
  BarPanelLeft.BevelInner := bvNone;
  BarPanelLeft.BevelOuter := bvNone;
  BarPanelLeft.Visible := True;
  BarPanelLeft.Enabled := True;
  BarPanelLeft.FullRepaint := True;
  BarPanelLeft.Font.Name := 'Arial';
  BarPanelLeft.Font.Size := 11;
  BarPanelLeft.Font.Style := [fsBold];
  BarPanelLeft.Font.Color := clYellow;
  BarPanelLeft.Caption := HBBarChar;

  BarPanelLeft := TPanel.Create(TitlePanel);
  BarPanelLeft.Parent := TitlePanel;
  BarPanelLeft.Top := 0;
  BarPanelLeft.Left := TitlePanel.Width - 40;
  BarPanelLeft.Width := 40;
  BarPanelLeft.Height := 30;
  BarPanelLeft.Color := clFuchsia;
  BarPanelLeft.BevelInner := bvNone;
  BarPanelLeft.BevelOuter := bvNone;
  BarPanelLeft.Visible := True;
  BarPanelLeft.Enabled := True;
  BarPanelLeft.FullRepaint := True;
  BarPanelLeft.Font.Name := 'Arial';
  BarPanelLeft.Font.Size := 11;
  BarPanelLeft.Font.Style := [fsBold];
  BarPanelLeft.Font.Color := clYellow;
  BarPanelLeft.Caption := HBBarChar;

  ClosePanel := TPanel.Create(self);
  ClosePanel.Parent := self;
  ClosePanel.Top := Height - 60;
  ClosePanel.Left := 2;
  ClosePanel.Width := Width - 4;
  ClosePanel.Height := 58;
  ClosePanel.Color := clRed;
  ClosePanel.BevelInner := bvNone;
  ClosePanel.BevelOuter := bvNone;
  ClosePanel.Visible := True;
  ClosePanel.Enabled := True;
  ClosePanel.FullRepaint := True;

  CloseButton := TButton.Create(ClosePanel);
  CloseButton.Parent := ClosePanel;
  CloseButton.Left := 8;
  CloseButton.Top := 9;
  CloseButton.Height := 40;
  CloseButton.Width :=  Width - 20;
  CloseButton.Font.Name := 'Arial';
  CloseButton.Font.Size := 11;
  CloseButton.Font.Style := [fsBold];
  CloseButton.Caption := 'CLOSE';
  CloseButton.Enabled := True;
  CloseButton.Visible := True;
  CloseButton.OnClick := myonclick;
end;

procedure TMyDialog.myonclick(Sender:TObject);
begin
  with sender as TButton do// this is correct since we only use this for the close button. in otehr cases, put some if's
    (((owner as TPanel).owner) as TPanel).free;// should hide it and destroy all other resources that you created because framepanel owns them;)
end;

Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
var FramePanel : TMyDialog;
begin
  FramePanel := TMyDialog.Create(OwnerWindow,HBLeft,HBTop,HBWidth,HBHeight,HBCaption,HBBarChar,HBText);
  // do whatever with FramePanel;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  createhelpbox(self,100,100,250,250,'HELP','?','HELPME!');
end;

end.
0
 

Author Comment

by:loonyroony
ID: 16807060
It all hinges around the closing procedure:

procedure TMyDialog.myonclick(Sender:TObject);
begin
  with sender as TButton do// this is correct since we only use this for the close button. in otehr cases, put some if's
    (((owner as TPanel).owner) as TPanel).free;// should hide it and destroy all other resources that you created because framepanel owns them;)
end;


My compiler (Delphi 6) rejected it so I modified it to the following which compiles fine:

procedure THelpDialog.HelpBoxCloseButtonOnClick(Sender:TObject);
var CloseButton : TButton;
var FramePanel : TPanel;
var ClosePanel : TPanel;
begin              
  CloseButton := Sender As TButton;
  ClosePanel := CloseButton.owner As TPanel;
  FramePanel := ClosePanel.owner As TPanel;
  FramePanel.Free;
end;

The line which throws up the violation is 'FramePanel.Free'
0
 
LVL 28

Expert Comment

by:2266180
ID: 16807096
hm... weird. I have delphi 7.

what is the error with which d6 rejects my code?
also, did you paste entire code as I wrote it or used yours? because yours had some minor (owning) issues which are fixed in my code.
0
 

Author Comment

by:loonyroony
ID: 16807186
sorry i've repasted the handler code and it compiles fine now.

however it's still throwing up an access violation at run time when it tries to free the panel. The ownership in the constructor is identical to the one above now. I don't understand it - It works if the code is in the same unit as in your pasted section above, however it falls over when the procedure is in the separate RoonyMisc module and it's being called from Unit1.
0
 
LVL 28

Expert Comment

by:2266180
ID: 16807288
all I can think of is that you made the "connections" wrong. paste your code here (remove anyhting not related to this issue - copy the whole project to another directory and open the dpr from there and delete all stuff that is not needed to reduce code size. then run it and make sure the issue reproduces. if it doesn't then it means you deleted the issue and you'll have to go through your code and find the error: or post the whole code here)
0
 

Author Comment

by:loonyroony
ID: 16807329
RoonyMisc.pas:

unit RoonyMisc;

interface

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

  type THelpDialog = class(TPanel)
     private
       TitlePanel : TPanel;
       BarPanel : TPanel;
       ClosePanel : TPanel;
       CloseButton : TButton;
       procedure HelpBoxCloseButtonOnClick(sender:TObject);
     public
       constructor Create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String); overload;
     end;
                                           
Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);

implementation

constructor THelpDialog.create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
begin
  inherited Create(OwnerWindow);
  Parent := OwnerWindow;
  Top := HBTop;
  Left := HBLeft;
  Width := HBWidth;
  Height:= HBHeight;
  Color := clBlue;
  BevelInner := bvLowered;
  BevelOuter := bvRaised;
  Visible := True;
  Enabled := True;
  FullRepaint := True;
  DragMode := dmAutomatic;
  DragKind := dkDock;

  TitlePanel := TPanel.Create(self);
  TitlePanel.Parent := self;
  TitlePanel.Top := 2;
  TitlePanel.Left := 2;
  TitlePanel.Width := Width - 4;
  TitlePanel.Height := 30;
  TitlePanel.Color := clYellow;
  TitlePanel.BevelInner := bvNone;
  TitlePanel.BevelOuter := bvNone;
  TitlePanel.Visible := True;
  TitlePanel.Enabled := True;
  TitlePanel.FullRepaint := True;
  TitlePanel.Font.Name := 'Arial';
  TitlePanel.Font.Size := 11;
  TitlePanel.Font.Style := [fsBold];
  TitlePanel.Font.Color := clBlue;
  TitlePanel.Caption := HBCaption;

  BarPanel := TPanel.Create(TitlePanel);
  BarPanel.Parent := TitlePanel;
  BarPanel.Top := 0;
  BarPanel.Left := 0;
  BarPanel.Width := 40;
  BarPanel.Height := 30;
  BarPanel.Color := clFuchsia;
  BarPanel.BevelInner := bvNone;
  BarPanel.BevelOuter := bvNone;
  BarPanel.Visible := True;
  BarPanel.Enabled := True;
  BarPanel.FullRepaint := True;
  BarPanel.Font.Name := 'Arial';
  BarPanel.Font.Size := 11;
  BarPanel.Font.Style := [fsBold];
  BarPanel.Font.Color := clYellow;
  BarPanel.Caption := HBBarChar;

  BarPanel := TPanel.Create(TitlePanel);
  BarPanel.Parent := TitlePanel;
  BarPanel.Top := 0;
  BarPanel.Left := TitlePanel.Width - 40;
  BarPanel.Width := 40;
  BarPanel.Height := 30;
  BarPanel.Color := clFuchsia;
  BarPanel.BevelInner := bvNone;
  BarPanel.BevelOuter := bvNone;
  BarPanel.Visible := True;
  BarPanel.Enabled := True;
  BarPanel.FullRepaint := True;
  BarPanel.Font.Name := 'Arial';
  BarPanel.Font.Size := 11;
  BarPanel.Font.Style := [fsBold];
  BarPanel.Font.Color := clYellow;
  BarPanel.Caption := HBBarChar;

  ClosePanel := TPanel.Create(self);
  ClosePanel.Parent := self;
  ClosePanel.Top := Height - 60;
  ClosePanel.Left := 2;
  ClosePanel.Width := Width - 4;
  ClosePanel.Height := 58;
  ClosePanel.Color := clRed;
  ClosePanel.BevelInner := bvNone;
  ClosePanel.BevelOuter := bvNone;
  ClosePanel.Visible := True;
  ClosePanel.Enabled := True;
  ClosePanel.FullRepaint := True;

  CloseButton := TButton.Create(ClosePanel);
  CloseButton.Parent := ClosePanel;
  CloseButton.Left := 8;
  CloseButton.Top := 9;
  CloseButton.Height := 40;
  CloseButton.Width :=  Width - 20;
  CloseButton.Font.Name := 'Arial';
  CloseButton.Font.Size := 11;
  CloseButton.Font.Style := [fsBold];
  CloseButton.Caption := 'CLOSE';
  CloseButton.Enabled := True;
  CloseButton.Visible := True;
  CloseButton.OnClick := HelpBoxCloseButtonOnClick;
end;

procedure THelpDialog.HelpBoxCloseButtonOnClick(Sender:TObject);
begin
  with sender as TButton do// this is correct since we only use this for the close button. in otehr cases, put some if's
    (((owner as TPanel).owner) as TPanel).free;// should hide it and destroy all other resources that you created because framepanel owns them;)
end;

Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
var FramePanel : THelpDialog;
begin
  FramePanel := THelpDialog.Create(OwnerWindow,HBLeft,HBTop,HBWidth,HBHeight,HBCaption,HBBarChar,HBText);
end;

end.




Unit1.pas    => The form contains two panels Panel1 and Panel2. Panel1 is irrelevant. Panel2 should have a double-click handler for activating the code.


unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    procedure Panel2DblClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Panel2DblClick(Sender: TObject);
begin                        
   CreateHelpBox(self,100,100,250,250,'HELP','?','HELPME!');
end;

end.
0
 

Author Comment

by:loonyroony
ID: 16807357
Ah interesting - it worked when in a new separate directory......
0
 

Author Comment

by:loonyroony
ID: 16807365
OK it stops working when a second panel is added - it seems like there's some sort of interference from having more than one panel in Unit1 which isn't much use. Any ideas?
0
 
LVL 28

Expert Comment

by:2266180
ID: 16807401
first, change:
Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
var FramePanel : THelpDialog;
begin
  FramePanel := THelpDialog.Create(OwnerWindow,HBLeft,HBTop,HBWidth,HBHeight,HBCaption,HBBarChar,HBText);
end;

to
Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
begin
  THelpDialog.Create(OwnerWindow,HBLeft,HBTop,HBWidth,HBHeight,HBCaption,HBBarChar,HBText);
end;

as I see you don't use that variable.
It seems that with 2 panels is indeed reproducing, but only once. no matter how many times I then doubleclick the second panel, no more errors occure.
I'll investigate
0
 

Author Comment

by:loonyroony
ID: 16807434
Right this is getting very weird:

1 Panel works
2 Panels give an Access Violation
3 to 15 Panels works
16 + Panels give an abstract error


huh???
0
 

Author Comment

by:loonyroony
ID: 16807503
could it be that the free command isn't disposing of the panels correctly? Some sort of memory management issue?
0
 
LVL 28

Accepted Solution

by:
2266180 earned 2000 total points
ID: 16807734
no. it's because something like this happens:
button is clicked:
in button the execution goes down a few levels (going down until tcontrol.click (stuff is pushed on the stack))
then the event is fired
then everyting is disposed. no problem here
now it starts going back again.
question: where to? the object has been destroyed. stuff from the stack is now invalid. there is nothing to go back to. so an access violation is raised.

I fixed it by adding a thread that free's the dialog. the thread will be freed upon termination.
here is the complete code (I also modified the component)

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Panel2: TPanel;
    Panel1: TPanel;
    procedure Panel2DblClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type TMyDialog=class
     private
       FramePanel : TPanel;
       TitlePanel : TPanel;
       BarPanelLeft : TPanel;
//       BarPanelRight : TPanel;
       ClosePanel : TPanel;
       CloseButton : TButton;
       procedure myonclick(sender:TObject);
     public
       constructor Create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
       destructor Destroy; override;
     end;

     TMyThread=class(TThread)
     private
       dialog:TMyDialog;
       procedure freeit;
     public
       constructor create(d:TMyDialog);
       procedure execute; override;
     end;

constructor TMyDialog.create(OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
begin
  FramePanel:=TPanel.Create(OwnerWindow);
  FramePanel.Parent := OwnerWindow;
  FramePanel.Top := HBTop;
  FramePanel.Left := HBLeft;
  FramePanel.Width := HBWidth;
  FramePanel.Height:= HBHeight;
  FramePanel.Color := clBlue;
  FramePanel.BevelInner := bvLowered;
  FramePanel.BevelOuter := bvRaised;
  FramePanel.Visible := True;
  FramePanel.Enabled := True;
  FramePanel.FullRepaint := True;
  FramePanel.DragMode := dmAutomatic;
  FramePanel.DragKind := dkDock;

  TitlePanel := TPanel.Create(FramePanel);
  TitlePanel.Parent := FramePanel;
  TitlePanel.Top := 2;
  TitlePanel.Left := 2;
  TitlePanel.Width := FramePanel.Width - 4;
  TitlePanel.Height := 30;
  TitlePanel.Color := clYellow;
  TitlePanel.BevelInner := bvNone;
  TitlePanel.BevelOuter := bvNone;
  TitlePanel.Visible := True;
  TitlePanel.Enabled := True;
  TitlePanel.FullRepaint := True;
  TitlePanel.Font.Name := 'Arial';
  TitlePanel.Font.Size := 11;
  TitlePanel.Font.Style := [fsBold];
  TitlePanel.Font.Color := clBlue;
  TitlePanel.Caption := HBCaption;

  BarPanelLeft := TPanel.Create(TitlePanel);
  BarPanelLeft.Parent := TitlePanel;
  BarPanelLeft.Top := 0;
  BarPanelLeft.Left := 0;
  BarPanelLeft.Width := 40;
  BarPanelLeft.Height := 30;
  BarPanelLeft.Color := clFuchsia;
  BarPanelLeft.BevelInner := bvNone;
  BarPanelLeft.BevelOuter := bvNone;
  BarPanelLeft.Visible := True;
  BarPanelLeft.Enabled := True;
  BarPanelLeft.FullRepaint := True;
  BarPanelLeft.Font.Name := 'Arial';
  BarPanelLeft.Font.Size := 11;
  BarPanelLeft.Font.Style := [fsBold];
  BarPanelLeft.Font.Color := clYellow;
  BarPanelLeft.Caption := HBBarChar;

  BarPanelLeft := TPanel.Create(TitlePanel);
  BarPanelLeft.Parent := TitlePanel;
  BarPanelLeft.Top := 0;
  BarPanelLeft.Left := TitlePanel.Width - 40;
  BarPanelLeft.Width := 40;
  BarPanelLeft.Height := 30;
  BarPanelLeft.Color := clFuchsia;
  BarPanelLeft.BevelInner := bvNone;
  BarPanelLeft.BevelOuter := bvNone;
  BarPanelLeft.Visible := True;
  BarPanelLeft.Enabled := True;
  BarPanelLeft.FullRepaint := True;
  BarPanelLeft.Font.Name := 'Arial';
  BarPanelLeft.Font.Size := 11;
  BarPanelLeft.Font.Style := [fsBold];
  BarPanelLeft.Font.Color := clYellow;
  BarPanelLeft.Caption := HBBarChar;

  ClosePanel := TPanel.Create(FramePanel);
  ClosePanel.Parent := FramePanel;
  ClosePanel.Top := FramePanel.Height - 60;
  ClosePanel.Left := 2;
  ClosePanel.Width := FramePanel.Width - 4;
  ClosePanel.Height := 58;
  ClosePanel.Color := clRed;
  ClosePanel.BevelInner := bvNone;
  ClosePanel.BevelOuter := bvNone;
  ClosePanel.Visible := True;
  ClosePanel.Enabled := True;
  ClosePanel.FullRepaint := True;

  CloseButton := TButton.Create(ClosePanel);
  CloseButton.Parent := ClosePanel;
  CloseButton.Left := 8;
  CloseButton.Top := 9;
  CloseButton.Height := 40;
  CloseButton.Width :=  FramePanel.Width - 20;
  CloseButton.Font.Name := 'Arial';
  CloseButton.Font.Size := 11;
  CloseButton.Font.Style := [fsBold];
  CloseButton.Caption := 'CLOSE';
  CloseButton.Enabled := True;
  CloseButton.Visible := True;
  CloseButton.OnClick := myonclick;
end;

destructor TMyDialog.Destroy;
begin
  FramePanel.Free;
  inherited;
end;

procedure TMyDialog.myonclick(Sender:TObject);
begin
  TMyThread.create(self);
end;

Procedure CreateHelpBox( OwnerWindow : TWinControl;
                         HBLeft : Integer;
                         HBTop : Integer;
                         HBWidth: Integer;
                         HBHeight: Integer;
                         HBCaption : String;
                         HBBarChar : String;
                         HBText : String);
begin
  TMyDialog.Create(OwnerWindow,HBLeft,HBTop,HBWidth,HBHeight,HBCaption,HBBarChar,HBText);
end;

{ TMyThread }

constructor TMyThread.create(d: TMyDialog);
begin
  inherited Create(false);
  dialog:=d;
  FreeOnTerminate:=true;
end;

procedure TMyThread.execute;
begin
  sleep(50);
  Synchronize(freeit);
  sleep(50);
end;

procedure TMyThread.freeit;
begin
  dialog.free;// should hide it and destroy all other resources that you created because framepanel owns them;)
end;

procedure TForm1.Panel2DblClick(Sender: TObject);
begin
  CreateHelpBox(self,100,100,250,250,'HELP','?','HELPME!');
end;

end.
0
 

Author Comment

by:loonyroony
ID: 16808436
Whahey!! It's ALIIVEEE!!!!!

Thanx so much mate :-) we got there in the end!!

0
 
LVL 28

Expert Comment

by:2266180
ID: 16808541
glad it works :)
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question