This answer assumes you want the messages to be received by controls on a form.
These messages are non-queued and are sent directly to the control. That explains why your two attempts to receive them have failed.
The only way to receive them is through the window procedure of the control. You have the following options.
- Subclass the control and handle the message. This is perhaps most easily done with and interposer class.
- Use the
WindowProc
property of the control to replace the window procedure without deriving a new class.
You might find that TForm.SetFocusedControl
could help. It is called in response to a control receiving WM_SetFocus
messages, as well as being called in some other situations (see the VCL code for details).
Option 1: Interposer
unit uWindowProc;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TEdit = class(StdCtrls.TEdit)
protected
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
end;
TMyForm = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
end;
var
MyForm: TMyForm;
implementation
{$R *.dfm}
{ TEdit }
procedure TEdit.WMSetFocus(var Message: TWMSetFocus);
begin
inherited;
Beep;
end;
end.
Option 2: WindowProc
unit uWindowProc;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMyForm = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
procedure FormCreate(Sender: TObject);
private
FOriginalWindowProc: TWndMethod;
procedure NewWindowProc(var Message: TMessage);
end;
var
MyForm: TMyForm;
implementation
{$R *.dfm}
procedure TMyForm.FormCreate(Sender: TObject);
begin
FOriginalWindowProc := Edit1.WindowProc;
Edit1.WindowProc := NewWindowProc;
end;
procedure TMyForm.NewWindowProc(var Message: TMessage);
begin
if Message.Msg=WM_SETFOCUS then
Beep;
FOriginalWindowProc(Message);
end;
end.