RBA
RBA

Reputation: 12584

Delphi - replace control WindowProc and dispatch the message

Starting from Way of getting control handle from TMessage question, I've created my own implementation in order to replace the Windowproc with my own one, in order to make some processing when mouse left button is pressed.

  TOverrideMessage = class
  public
    FControl: TWinControl;
    FOldWndProc: TWndMethod;
    procedure OverrideWindowProc(var Message: TMessage);
  end;

implementation:

procedure TOverrideMessage.OverrideWindowProc(var Message: TMessage);
begin
  if Message.Msg = WM_NCLBUTTONDOWN then
    begin
      FOldWndProc(Message);
      if FControl is TSomeCustomControl then
        ShowMessage(TSomeCustomControl(FControl).Caption);//this property exists
    end
  else
   Dispatch(Message);
end;

And replace the windowprocs of each of the controls I want with an instance of my class:

  LOverrideMessage := TOverrideMessage.Create;
  LOverrideMessage.FControl := TSomeCustomControl(lControl4);
  LOverrideMessage.FOldWndProc := TWinControl(lControl4).WindowProc;
  TWinControl(lControl4).WindowProc := LOverrideMessage.OverrideWindowProc;

The problem I have is that the messages are not dispatched correctly further to the controls so the controls are not drawing correctly,etc. Also I'm not receiving the WM_NCLBUTTONDOWN message in the class implementation. What's wrong?

Upvotes: 0

Views: 2198

Answers (1)

David Heffernan
David Heffernan

Reputation: 612804

Your main problem is the failure to call FOldWndProc. You need to call that rather than Dispatch. When you call Dispatch you will get the base TObject handling, which does nothing.

procedure TOverrideMessage.OverrideWindowProc(var Message: TMessage);
begin
  FOldWndProc(Message);
  if Message.Msg = WM_NCLBUTTONDOWN then
    if FControl is TSomeCustomControl then
      ShowMessage(TSomeCustomControl(FControl).Caption);//this property exists
end;

If WM_NCLBUTTONDOWN doesn't arrive, then the message is not being sent to your control.

I am concerned by your casting. When you write:

LOverrideMessage.FControl := TSomeCustomControl(lControl4);  
LOverrideMessage.FOldWndProc := TWinControl(lControl4).WindowProc;
TWinControl(lControl4).WindowProc := LOverrideMessage.OverrideWindowProc;

why do you need any of those casts? If lControl4 was derived from TWinControl then you would not need those casts. If lControl4 has a compile time type that is less derived, then at least include an is check.

Upvotes: 4

Related Questions