之所以要用类函数代替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;