luix10
luix10

Reputation: 49

SendMessage to Application.Handle not working

I've created an class that should propagate to the entire application a customized message when its going to be freed. I did it with PostMessage and it worked with few bugs

PostMessage(Application.Handle, UM_MYMESSAGE, 0, 0);

then I realized it should be synchronous - via SendMessage.

SendMessage(Application.Handle, UM_MYMESSAGE, 0, 0);

On my Form I was handling the messages with a TApplicationEvents component, but just switching SendMessage to PostMessage didn't make it handle the message

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
  if Msg.message = UM_MYMESSAGE then
  begin
    ShowMessage('Ok');

    Handled := True;
  end;
end;

It works if I pass the Form Handle but not working with Application.Handle... What am I doing wrong?

Upvotes: 0

Views: 2956

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596287

The TApplication(Events).OnMessage event is triggered only for messages that are posted to the main UI thread message queue. Sent messages go directly to the target window's message procedure, bypassing the message queue. That is why your OnMessage event handler works with using PostMessage() but not SendMessage().

To catch messages that are sent to the TApplication window, you need to use TApplication.HookMainWindow() instead of TApplication(Events).OnMessage, eg:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.HookMainWindow(MyAppHook);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Application.UnhookMainWindow(MyAppHook);
end;

function TForm1.MyAppHook(var Message: TMessage): Boolean;
begin
  if Message.Msg = UM_MYMESSAGE then
  begin
    ShowMessage('Ok');
    Result := True;
  end else
    Result := False;
end;

That being said, a better solution is to use AllocateHWnd() to create your own private window that you can post/send your custom messages to, eg:

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMyWnd := AllocateHWnd(MyWndMsgProc);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DeallocateHWnd(FMyWnd);
end;

procedure TForm1.MyWndMsgProc(var Message: TMessage);
begin
  if Message.Msg = UM_MYMESSAGE then
  begin
    ShowMessage('Ok');
    Message.Result := 0;
  end else
    Message.Result := DefWindowProc(FMyWnd, Message.Msg, Message.WParam, Message.LParam);
end;

Then you can post/send messages to FMyWnd.

Upvotes: 6

Related Questions