VCL里为什么要用类函数代替API,为什么要用CM_消息代替虚函数

之所以要用类函数代替API,是因为VCL对它做了一些包装,好在API起作用之前和之后做一些额外的事情:通知和判断等等。
之所以类函数要包装一个CM_消息,是因为这样方便程序员(在调用类函数的基础上)截断和改写这个处理过程

举例:

procedure TWinControl.Invalidate;
begin
  // 注意,是简单执行函数,把消息当作参数,不是发送消息
  Perform(CM_INVALIDATE, 0, 0); // 注意,第二个参数即WParam是0,即要求API使自己失效,而不是仅仅做一个通知作用。
end;

procedure TWinControl.CMInvalidate(var Message: TMessage);
var
  I: Integer;
begin
  // 这个函数被所有Windows子控件所继承,只要没有被程序员(或者控件程序员)覆盖,那么就会使用API将整个客户区全部都声明为无效区域,其实过程很简单
// 其实最后就是简单调用API,但是就是被VCL库框架包装了一遍

if HandleAllocated then
  begin
    // 相当于子控件要重画,必须通知一下父控件,而且是挨个通知,父控件想处理就处理,不处理就算了(大部分情况下不会处理)。
    if Parent <> nil then
      Parent.Perform(CM_INVALIDATE, 1, 0); // 递归,先通知父类。
      
    // 父控件通知完了,就该重画自己了。
if Message.WParam = 0 then
    begin
      InvalidateRect(FHandle, nil, not (csOpaque in ControlStyle)); // API,第二个参数为NULL的话,则重画整个客户区;第三个参数TRUE则背景重绘。
      { Invalidate child windows which use the parentbackground when themed }
if ThemeServices.ThemesEnabled then
        for I := 0 to ControlCount - 1 do
if csParentBackground in Controls[I].ControlStyle then // important
            Controls[I].Invalidate;
    end;
  end;
end;
原文地址:https://www.cnblogs.com/findumars/p/4102723.html