码迷,mamicode.com
首页 > 其他好文 > 详细

一行代码设置TForm颜色的前世今生

时间:2014-11-24 00:50:13      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   ar   color   sp   for   on   

来自万一的帖子:
http://www.cnblogs.com/del/archive/2008/04/27/1173658.html
的确做到了一行代码设置颜色的TForm控件。真实的情况是,VCL框架在这个过程中做了大量的工作,经过多次消息的发送,才达到了目的,大致顺序如下:

procedure TForm1.Button4Click(Sender: TObject);
begin
  Self.Color := clRed;
end;

procedure TControl.SetColor(Value: TColor);
begin
  if FColor <> Value then
  begin
    FColor := Value;
    FParentColor := False;
    Perform(CM_COLORCHANGED, 0, 0); // 第一个消息
  end;
end;

procedure TCustomForm.CMColorChanged(var Message: TMessage);
begin
  inherited;
  if FCanvas <> nil then FCanvas.Brush.Color := Color; // 说到底,还是通过FCanvas.Brush起作用,类属性Color只是表象
end;

procedure TWinControl.CMColorChanged(var Message: TMessage);
begin
  inherited;
  FBrush.Color := FColor;
  NotifyControls(CM_PARENTCOLORCHANGED); // 第二个消息,组建消息并传播,通知子控件,但没有任何子控件响应
end;

procedure TControl.CMColorChanged(var Message: TMessage);
begin
  Invalidate;
end;

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

procedure TWinControl.CMInvalidate(var Message: TMessage);
var
  I: Integer;
begin
  if HandleAllocated then
  begin
    if Parent <> nil then
      Parent.Perform(CM_INVALIDATE, 1, 0); // 第四个消息,递归,先通知父类。Form1的Parent是Application,它没有响应。
    if Message.WParam = 0 then
    begin
      // API,第二个参数为NULL的话,则重画整个客户区;第三个参数TRUE则背景重绘。
      InvalidateRect(FHandle, nil, not (csOpaque in ControlStyle)); // 总算初步达到目的,使Form1失效,后面还要自绘
      { 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;

以上过程使Form1的画板失效(说到底,还是通过Form1.FCanvas.Brush起作用,类属性Color只是表象),接下去还要用TForm的函数自绘:

TForm继承自TWinControl,而不是TCustomControl,而且响应WM_PAINT消息并覆盖了WMPaint函数,所以Windows会把WM_PAINT直接发给Form1:
TCustomForm.WMPaint(var Message: TWMPaint);
TWinControl.WMPaint(var Message: TWMPaint);
TWinControl.PaintHandler(var Message: TWMPaint);
TCustomForm.PaintWindow

一行代码设置TForm颜色的前世今生

标签:style   blog   http   io   ar   color   sp   for   on   

原文地址:http://www.cnblogs.com/findumars/p/4117783.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!