Cry about...
Delphi Programming
How to send and handle a custom Windows message
These notes apply to Delphi running
on a Microsoft Windows platform.
Delphi allows you to define your own messages when can then be posted on the
Windows message queue and then handled by your own custom handler in your
application.
The notes here show how to:
- Define your own custom message
- Define a handler for the message
- Send a message
- Pass data via messages
Each message must have a unique id. The constant WM_USER is defined (in the
Messages unit) as the first message number available for application use.
const
WM_MY_MESSAGE = WM_USER + 0;
WM_ANO_MESSAGE = WM_USER + 1;
These messages should be defined in the interface section of the unit
containing the form that will be handling them. Alternately, to guarantee that
all messages are unique within an application consider defining all your
messages together in a single unit.
Note:
WM_USER is fine for internal application messages.
- Use
WM_APP for messages between applications.
- Use the
RegisterMessage API call if you need a message
number that is guaranteed to be unique in a system.
To add a message handler to a form, define a procedure that takes an argument
of type TMessage and add the directive "message"
with the message id that the procedure is to handle.
For example:
type
TMyForm = class(TForm)
.
.
.
private
procedure OnMyMessage(var Msg: TMessage); message
WM_MY_MESSAGE;
procedure OnAnoMessage(var Msg: TMessage); message
WM_ANO_MESSAGE;
.
.
To send a message use either:
PostMessage(hWnd: HWND; Msg: UINT;
wParam: WPARAM; lParam: LPARAM): BOOL;
or
SendMessage(hWnd: HWND; Msg: UINT;
wParam: WPARAM; lParam: LPARAM): BOOL;
both of which are defined in the Windows unit. Both of these will append
the message to the end of the application's Windows message queue. The
difference between them is that SendMessage will not return until
the message has been handled, whereas PostMessage will return
straight away.
For example, for a form to send itself one of the messages defined
above:
PostMessage(self.Handle,WM_MY_MESSAGE,0,0);
The additional parameters wParam and lParam provide
a mechanism to pass some additional information along with the message. Both of
these parameters are defined as type Integer. At the recipient end
the values can be extracted from the message by simply referencing the WParam
and LParam members of TMessage.
Note: The technique described here is suited for sending data from a thread
to the main process (or form) of the application.
The wParam and lParam members are ideally suited
for passing integer data, but can also be used to pass objects, for example:
SendMessage(LinkCheckForm.Handle,WM_ANO_MESSAGE,Integer(self),0);
and at the recipient end:
procedure TMyForm.OnAnoMessage(var Msg:
TMessage);
var
myObject: TMyClass;
begin
myObject := TMyClass(msg.WParam);
.
.
The things to be aware of if you use this approach:
- It can only be used if you are sending messages within the same process
- because memory in the sending process cannot be accessed by other
processes.
- If you do send messages within the same process (and are using
SendMessage)
then only use the technique to send messages from a separate Thread.
- You must ensure that the pointer being sent is still valid when it is
used by the recipient. A simple
approach is to use
SendMessage rather than PostMessage.
Consider if you use PostMessage and then free the object
being sent, the recipient may pick up the reference to the object after it
has been freed - at best this will be a source of difficult to find bugs,
at worst it may crash your program.
These notes are believed to be correct for Delphi 6 and Delphi
7 running under Microsoft Windows.
|