J...
J...

Reputation: 31403

Custom Messages in Non-Windowed Classes - need a default handler?

With a class (TObject) I have :

private
  FHwnd : HWND;
  procedure HandleMyMessage(var Message : TMessage); message TH_MYMESSAGE;

where TH_MYMESSAGE = WM_USER + 1

In the class constructor:

FHwnd := AllocateHWND(HandleMyMessage);

The only object which receives a reference to FHwnd is a private custom TThread (created within this class) and the only message it posts is TH_MYMESSAGE. My understanding is that the message directive in the procedure declaration restricts its handling to only TH_MYMESSAGE.

This was working fine in testing, but upon integration into a much larger application I am getting feedback that HandleMyMessage is firing for other messages as well (with obvious undesired results).

This was easily corrected by adding if Message.Msg <> TH_MYMESSAGE then Exit; in HandleMyMessage. My question is : Why is this happening?

My best guess is that AllocateHWND has made HandleMyMessage the equivalent of a DefWndProc despite it having the message directive. Is there a correct way to implement this which I'm missing?

Upvotes: 17

Views: 1579

Answers (1)

Sertac Akyuz
Sertac Akyuz

Reputation: 54802

Well, yes of course. AllocateHWnd accepts a TWndMethod to act as the window procedure of the created window. The confusion, I guess, is caused by that the compiler accepts the messsage directive. Don't put it:

private
  FHwnd : HWND;
  procedure HandleMyMessage(var Message : TMessage);

..

procedure TMyClass.HandleMyMessage(var Message: TMessage);
begin
  case Message.Msg of
    TH_MYMESSAGE: //
  end;
  Message.Result := DefWindowProc(FHWnd, Message.Msg, Message.WParam, Message.LParam);
end;


edit: (Response to comment). To have the message handled on the class that created the utility window, you can route your message from the window AllocateHWnd creates to your class:

private
  FHwnd : HWND;
  procedure HandleMyMessage(var Message : TMessage);
  procedure THMyMessage(var Message: TMessage); message TH_MYMESSAGE;

..

procedure TMyClass.HandleMyMessage(var Message: TMessage);
begin
  case Message.Msg of
    TH_MYMESSAGE: Dispatch(Message);
  end;
  Message.Result := DefWindowProc(FHWnd, Message.Msg, Message.WParam, Message.LParam);
end;

procedure TMyClass.THMyMessage(var Message: TMessage);
begin
  //
end;

Upvotes: 13

Related Questions