正确覆盖WndProc

时间:2018-04-26 10:54:53

标签: delphi controls wndproc

前一天我开始重写我的一个旧组件,并决定提高其可读性。 我的组件是一个典型的TWinControl,它覆盖了WndProc来处理我自己的很多消息。每条消息都有很多代码,我阅读代码成了一个问题 因此,在寻找改进WndProc内部代码的解决方案时,我已经在每次在WndProc中传递适当消息时调用的过程中组织了这些大量代码。这就是它现在的样子:

procedure TMyControl.WndProc(var Message: TMessage);
begin
  case Message.Msg of        
    WM_WINDOWPOSCHANGED: 
      WMWINDOWPOSCHANGED(Message);
    WM_DESTROY: 
      WMDESTROY(Message);
    WM_STYLECHANGED: 
      WMSTYLECHANGED(Message);
    //  lots of the same procedures for Windows messages
    //  ...
    MM_FOLDER_CHANGED: 
      MMFOLDERCHANGED(Message);
    MM_DIRECTORY_CHANGED: 
      MMDIRECTORYCHANGED(Message);
    //  lots of the same procedures for my own messages
    //  ...
  else
    Inherited WndProc(Message);
  end;
end;

不幸的是,这些程序中的Inherited字不再有效!

重要说明:在某些WM_XXX消息中,我没有调用Inherited来执行我自己对此类消息的处理,因此下面显示的代码将分解我的实施工作一些功能。

procedure TMyControl.WndProc(var Message: TMessage);
begin
  Inherited WndProc(Message);
  case Message.Msg of        
    WM_WINDOWPOSCHANGED: 
      WMWINDOWPOSCHANGED(Message);
    //  further messages
    //  ...
  end;
end;

我还想避免在每个消息ID之后插入Inherited,如下所示,因为它看起来很糟糕,我认为存在更优雅的方式来覆盖WndProc

procedure TMyControl.WndProc(var Message: TMessage);
begin      
  case Message.Msg of        
    WM_WINDOWPOSCHANGED: 
    begin
      Inherited WndProc(Message);
      WMWINDOWPOSCHANGED(Message);
    end;
    //  further messages
    //  ...
  end;
end;

所以我的问题是:
如何正确覆盖WndProc,以便能够使用在程序中分组的代码,并且只能为某些消息调用原始窗口过程?

2 个答案:

答案 0 :(得分:5)

正如RM的回答所述,您的邮件处理方法可以调用inherited WndProc(Message)而不只是inherited,这样就可以了。

但是,通过引入与正在处理的消息具有相同名称的方法,您将了解正在处理的特定消息。因此,您可能会发现使用Message Methods而不是覆盖WndProc更容易,例如:

type
  TMyControl = class(...)
  private
    procedure WMWindowPosChanged(var Message: TMessage); message WM_WINDOWPOSCHANGED;
    procedure WMDestroy(var Message: TMessage); message WM_DESTROY;
    procedure WMStyleChanged(var Message: TMessage); message WM_STYLECHANGED;
    // and so on ...
  end;

您的message方法可以根据需要调用inherited(或不),例如:

procedure TMyControl.WMWindowPosChanged(var Message: TMessage);
begin
  inherited;
  //...
end;

答案 1 :(得分:4)

从WMWINDOWPOSCHANGED调用继承的WndProc将调用继承的WndProc。所以你可以这样做:

procedure WMWINDOWPOSCHANGED(var Message: TMessage)
begin
  // call inherited WndProc if you need to
  inherited WndProc(Message);
  .. do you own processing
end;