Author: Lou Adler
I'd like to know if there's some way to prevent a user from closing Windows, or
closing an application while it is currently performing a process. Do you know of
way?
Answer:
There are two ways to approach this problem. One is strictly Delphi; the other
involves creating a message handler for the WM_CLOSE message in Windows. Let's look
at the former method first.
The easiest way to decide whether to allow or disallow a user from closing a
program is with the OnCloseQuery method of the main form. If you open that method,
you'll see the following:
1
2 procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
3 begin
4
5 end;
The most important part of that method is the CanClose formal parameter. If False,
the window will not be allowed to close. If true, the program will close. Here's an
example. Let's say that while some background processing is occuring, you have a
Boolean variable called "ProcessRunning" set to true during the course of the
process. If the user tries to close the program during the run you could do
something like this:
6
7 procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
8 begin
9 if ProcessRunning then
10 CanClose := False
11 else
12 CanClose := True;
13 end;
The point to this is to check certain conditions within the program. If the
criteria for closing is correct, you can close the window. Otherwise, leave it up.
You'd do the same thing with a custom message handler for the WM_CLOSE message. The
only difference is, you have to create the handler. To do this, look at the
following section of code taken out of a program that I wrote that is set up to
handle WM_CLOSE:
14 private
15
16 procedure WMClose(var Msg: TWMClose); message WM_CLOSE;
17 public
18
19 end;
20
21 var
22 Form1: TForm1;
23 CloseDown: Boolean;
24
25 implementation
26
27 {$R *.DFM}
28
29 procedure TForm1.WMClose(var Msg: TWMClose);
30 begin
31 if not CloseDown then
32 Msg.Result := 0
33 else
34 inherited;
35 end;
If you're new to creating custom Windows message handlers, while not a trivial
thing, it's not that hard to do. It just requires some work. I won't go into a long
discussion about Windows message handlers. WM_CLOSE happens to be a fairly simple
message to handle, but there are more complex ones out there that take much more
space than a simple e- mail reply. So I'll just tell you how to go about handling
the message, then let you play with the code:
First, in the private section of the form's type declaration, you must declare the
handler. In this case, I've declared it as:
36
37 procedure WMClose(var Msg: TWMClose); message WM_CLOSE;
You can name the procedure anything you like.
As far as the implementation is concerned, to deny closure, we have to set the
message's result to 0. To allow closure, we just call the inherited WM_CLOSE
handler.
38 procedure TForm1.WMClose(var Msg: TWMClose);
39 begin
40 if not CloseDown then
41 Msg.Result := 0
42 else
43 inherited;
44 end;
As you can see, the principle is exactly the same as using the OnCloseQuery method of the form. But you can also see that to accomplish the same task, a bit more work had to be done. So a good "rule of thumb" is to use Delphi's built-in capabilities as much as possible, and to use only custom message handlers for events that aren't handled by default in Delphi.
|