Search code examples
delphidelphi-6

Why does a centered MessageDlg create exceptions?


Delphi 6.
I implemented a MessageDlg centered on the owner form
as suggested by @David Heffernan on january 6 2011.

The original question from 2011 is here: How to make MessageDlg centered on owner form.

The centered dialog works once.
After the first time it throws exceptions.
- EAccessViolation
- Access violation at address 00000000
- Read of address 00000000

What might I have done wrong to cause this?

function TEthernetNodes_form.CenteredMessageDlg(const Msg: string;
                                                DlgType:   TMsgDlgType;
                                                Buttons:   TMsgDlgButtons;
                                                HelpCtx:   Integer): Integer;
// Open a message Dialog in the center of the owner form
var
  Dialog: TForm;
begin
  Result := mrNo; // Suppress linker warning
  try
    Dialog := CreateMessageDialog(Msg, DlgType, Buttons);
    try
      Self.InsertComponent(Dialog);
      Dialog.Position := poOwnerFormCenter;
      Result := Dialog.ShowModal
    finally
      Dialog.Free
    end;

  except on E: Exception do
               begin
                 AddToActivityLog('Exception in CenteredMsgDlg: [' +  
                                   string(E.ClassName) + ']' +  
                                   E.Message, True, True);  
                 //Tried "ShowMEssage" instead of AddToActivityLog here. Does not display.
               end;

  end;
end;  

procedure TEthernetNodes_form.Button1Click(Sender: TObject);
begin
  CenteredMessageDlg('Test CenteredMessageDlg.', mtConfirmation, [mbOK], 0);
end;

The exception is shown in my activity log as follows:

Exception in CenteredMsgDlg: [EAccessViolation] Access violation at  
address 00000000. Read of address 00000000

Solution

  • CreateMessageDialog creates form with Application as its Owner - it is added to Application components list. With Self.InsertComponent(Dialog); you are adding it to your forms component list, but it is not removed from Application's.

    var
      Dialog: TForm;
    begin
      Result := mrNo; // Suppress linker warning
      try
        Dialog := CreateMessageDialog(Msg, DlgType, Buttons);
        try
          Application.RemoveComponent(Dialog); // remove Dialog from Application components
          Self.InsertComponent(Dialog);
          Dialog.Position := poOwnerFormCenter;
          Result := Dialog.ShowModal;
        finally
          Dialog.Free
        end;