The user insists on a pop up box for each ‘significant event” in the application. Adding a line to a memo or listbox is not aceptable.
I cannout use standard modal boxes bceuase the PC is often unnatended and my applciation will be left waiting for the user to click “OK” before it continues.
Can I just dynamically crate a form with a memo component and an OK button and pass some text to display in the memo?
I tried that and I got an access violation when OK was clicked.
Questions:
- is there any need to launch a thread to display the form, since it is being shown modelessly?
- what should I pass as the constructor parameter (prent)? Nil, since the form will destory itself?
- when the user clicks OK what should I call? Close() or Free() ? Either of these gives an access violation approx 1/2 seconds after clicking OK, but if I do nothing in the function the code runs fine (with a memory leak, of course)
Google is not so helpful as the form should destroy itself, while examples have its creator destroying it.
In main form:
theDialogForm := TDialogFormForm.Create(Nil);
theDialogForm.ShowTheForm('Database error '+#13+#10+''+#13+#10+
E.ClassName+#13+#10+
E.Message);
and the dialog form …
unit fDialogForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TDialogFormForm = class(TForm)
Memo1: TMemo;
OkButton: TButton;
procedure OkButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
procedure ShowTheForm(const theMessage : String);
end;
implementation
{$R *.dfm}
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
procedure TDialogFormForm.FormCreate(Sender: TObject);
begin
Visible := False;
end;
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
procedure TDialogFormForm.OkButtonClick(Sender: TObject);
begin
// Close();
Free();
end;
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
procedure TDialogFormForm.ShowTheForm(const theMessage : String);
begin
Memo1.Text := theMessage;
Show();
end;
end.
call stack
main thread ($630):
005164e3 +013 StoreRoom.exe Vcl.Controls TControl.WMLButtonUp
00515b30 +2d4 StoreRoom.exe Vcl.Controls TControl.WndProc
0051a47b +5b3 StoreRoom.exe Vcl.Controls TWinControl.WndProc
00537bf0 +06c StoreRoom.exe Vcl.StdCtrls TButtonControl.WndProc
00519ad0 +02c StoreRoom.exe Vcl.Controls TWinControl.MainWndProc
0048dea4 +014 StoreRoom.exe System.Classes StdWndProc
76677885 +00a USER32.dll DispatchMessageW
005b7c63 +0f3 StoreRoom.exe Vcl.Forms TApplication.ProcessMessage
005b7ca6 +00a StoreRoom.exe Vcl.Forms TApplication.HandleMessage
005b7fd9 +0c9 StoreRoom.exe Vcl.Forms TApplication.Run
00823616 +17a StoreRoom.exe StoreRoom 56 +24 initialization
75c43398 +010 kernel32.dll BaseThreadInitThunk
To close a form, you can either
Closeand set action tocaFreein the OnClose EventRelease, which is a special flavour of Free, especially for forms.The problem with calling
Free, is that the form is freed immediately, while you are still handling the click event on the close button. The form and therefore the button is freed while in that process, causing the access violation.Releaseinternally sends a message to the form, causing it to close after the click is handled.