Delphi - 替换控件 WindowProc 并发送消息

Delphi - replace control WindowProc and dispatch the message

Way of getting control handle from TMessage question, I've created my own implementation in order to replace the Windowproc开始用自己的,为了在按下鼠标左键时做一些处理。

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

实施:

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;

并用 class:

的实例替换我想要的每个控件的 windowprocs
  LOverrideMessage := TOverrideMessage.Create;
  LOverrideMessage.FControl := TSomeCustomControl(lControl4);
  LOverrideMessage.FOldWndProc := TWinControl(lControl4).WindowProc;
  TWinControl(lControl4).WindowProc := LOverrideMessage.OverrideWindowProc;

我遇到的问题是消息没有正确发送到控件,所以控件没有正确绘制等等。另外,我在 class 实现中没有收到 WM_NCLBUTTONDOWN 消息。怎么了?

您的主要问题是无法调用 FOldWndProc。您需要调用它而不是 Dispatch。当您调用 Dispatch 时,您将获得基本的 TObject 处理,它什么都不做。

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;

如果 WM_NCLBUTTONDOWN 没有到达,则消息没有发送到您的控件。

我很担心你的选角。当你写:

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

为什么需要这些演员?如果 lControl4 是从 TWinControl 派生的,那么您将不需要这些转换。如果 lControl4 具有派生较少的编译时类型,则至少包括 is 检查。