• TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)


    // 9个显示函数
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控件
    // 手法:固定不变的模式,或者简单调用,或者简单设置标志位,就不是虚函数。
    procedure Show; // 设置自己和所有祖先的visible标识
    procedure Hide; // 简单设置visible标识,与祖先无关
    procedure Refresh; // 简单调用Repaint虚函数,但Refresh本身不是虚函数。一般应该使用它,因为可以获得更多的无关性。
    procedure SendToBack;
    procedure BringToFront; // 图形控件也要用此能力啊,所以在TControl就已经定义了


    // 这三个函数,被TWinControl覆盖。即使使用,也是被inherited使用。
    // 而图形控件都没有覆盖着三个函数,因此会经常用到它们。摆明了就是给图形控件用的。
    // fixme 有空试试把它们都放到图形控件里去
    procedure Repaint; virtual; // 虚函数,取得父控件的DC,重画父控件的所有子控件。被TWinControl覆盖。
    procedure Invalidate; virtual; // 虚函数,调用非虚函数类函数InvalideControl,把自己需要重画的部分算清楚。被TWinControl覆盖。
    { 递归调用Parent的update,否则什么都不做。意思是,自己更新了,那么父控件也要更新。}
    procedure Update; virtual; // 虚函数,通知父控件自己更新了。而父控件的Update是可以被改写的,这样就达到了目的。被TWinControl覆盖。

    {
    看一下VCL的源码,就不难发现了。
    Paint是TCustomForm的Protected方法,实际就是调用OnPaint事件。
    Invalidate是TWinControl的方法,主要是发送一个CM_INVALIDATE消息,对控件的值作有效性判断。
    Update(其实)也是TWinControl的方法,是通过调用Win32API函数重画窗口。
    Repaint是TControl的虚方法,在TWinControl中override,程序只有2行,就是(1)Invalidate;(2)Update
    Refresh是TControl的方法,程序只有1句:Repaint.
    所以ReFresh和RePaint对于TWinControl的子类来说是等价的(除非又重载过),但是应该说Refresh是更规范的用法。
    至于Invalidate的Update一般是没有单独使用的必要的。
    }

    function TControl.GetDeviceContext(var WindowHandle: HWnd): HDC;
    begin
      if Parent = nil then
        raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);
      Result := Parent.GetDeviceContext(WindowHandle);
      SetViewportOrgEx(Result, Left, Top, nil);
      IntersectClipRect(Result, 0, 0, Width, Height);
    end;
    
    procedure TControl.InvalidateControl(IsVisible, IsOpaque: Boolean);
    var
      Rect: TRect;
    
      function BackgroundClipped: Boolean;
      var
        R: TRect;
        List: TList;
        I: Integer;
        C: TControl;
      begin
        Result := True;
        List := FParent.FControls;
        I := List.IndexOf(Self);
        while I > 0 do
        begin
          Dec(I);
          C := List[I];
          with C do
            if C.Visible and (csOpaque in ControlStyle) then
            begin
              IntersectRect(R, Rect, BoundsRect);
              if EqualRect(R, Rect) then Exit;
            end;
        end;
        Result := False;
      end;
    
    begin
      if (IsVisible or (csDesigning in ComponentState) and
        not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
        Parent.HandleAllocated then
      begin
        Rect := BoundsRect;
        InvalidateRect(Parent.Handle, @Rect, not (IsOpaque or
          (csOpaque in Parent.ControlStyle) or BackgroundClipped));
      end;
    end;
    
    procedure TControl.Invalidate;
    begin
      InvalidateControl(Visible, csOpaque in ControlStyle);
    end;
    
    procedure TControl.Hide;
    begin
      Visible := False;
    end;
    
    procedure TControl.Show;
    begin
      if Parent <> nil then Parent.ShowControl(Self);
      if not (csDesigning in ComponentState) or
        (csNoDesignVisible in ControlStyle) then Visible := True;
    end;
    
    procedure TControl.Update;
    begin
      if Parent <> nil then Parent.Update; // 图形控件没法刷新自己,让父控件去刷新
    end;
    
    procedure TControl.Refresh;
    begin
      Repaint;
    end;
    
    procedure TControl.Repaint;
    var
      DC: HDC;
    begin
      if (Visible or (csDesigning in ComponentState) and
        not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
        Parent.HandleAllocated then
        if csOpaque in ControlStyle then
        begin
          DC := GetDC(Parent.Handle);
          try
            IntersectClipRect(DC, Left, Top, Left + Width, Top + Height);
            Parent.PaintControls(DC, Self);
          finally
            ReleaseDC(Parent.Handle, DC);
          end;
        end else
        begin
          Invalidate;
          Update;
        end;
    end;

    PaintControls的意思是,重绘所有图形子控件

    --------------------------------------------------------------------------------

    例子1:可以看到Image1.的绘制过程

    image1.Refresh;

    例子2:

    Image1.Hide;

    例子3:

    var
    Image2 : TImage;
    begin
    Image2 := TImage.Create(self);
    Image2.Left := 100;
    Image2.Top := 50;
    Image2.Picture.LoadFromFile('c:pic.jpg');
    Image2.Parent := Form1;
    end;

  • 相关阅读:
    如何在 Linux 虚拟机上扩展根文件系统
    Linux 虚拟机中配置 GNOME + VNC
    在 Linux 中使用 Azure Premium 存储的基本优化指南
    如何为运行的 ARM Linux 启用 LAD2.3 版本的诊断扩展
    不要在构造函数中抛出异常
    vtk java
    富文本keditor的一些使用问题
    几个问题
    Java并发编程(十四)并发容器类
    FreeBSD编译安装emacs,不要用ports
  • 原文地址:https://www.cnblogs.com/findumars/p/4758432.html
Copyright © 2020-2023  润新知