vcl啥意思_oval

vcl啥意思_ovalvcl grid原理

大家好,又见面了,我是你们的朋友全栈君。

网格(Grid)控件,可直观描述二维信息。因此它具有横向和纵向二轴,就是一个二维表格。

1、TCustomGrid为所有网格控件的父类,定义了网格控件的主要特征和网格控件的主要功能。在这里,我们着重要了解的是它的两个保护级(p

rotected)方法:
(1)procedure Paint;
所有TWinControl的子类都可通过Paint来绘制自身外形。在TCustomGrid.Paint中,主要实现两个功能:绘制网格线和填充网格数据。其中,网

格数据的填充具体实现由下述的DrawCell完成。在后面的内容,我会结合源代码详细解释Paint。
2)procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState:  TGridDrawState); virtual; abstract;
这是一个纯虚方法,被Paint调用,用以实现网格数据的填充。因此,所有TCustomGrid的子类都可以覆盖(override)这个方法,根据实际需

要实现填充方式。

2、TCustomDrawGrid并没有实际用处。它主要完成两件事情:
(1)覆盖TCustomGrid的抽象方法加以实现。TCustomDrawGrid不再是一个抽象类。
(2)添加了一些事件。
比如它覆盖了TCustomGrid.DrawCell,并在其中触发了OnDrawCell事件。因此,我们在OnDrawCell中添加代码,就可以改变特定行列网格中的

数据及其填充方式。但要注意的是TCustomDrawGrid覆盖DrawCell后,并没有真正实现数据填充(因为它还不知道数据是什么)。简化后的Draw

Cell源代码如下:
    procedure TCustomDrawGrid.DrawCell(ACol, ARow: Longint; ARect: TRect;
AState: TGridDrawState);
    begin
      if Assigned(FOnDrawCell) then
        FOnDrawCell(Self, ACol, ARow, ARect, AState);
    end;

3、TDrawGrid、TStringGrid都是用户可以在设计时使用的类,或者简单的说都是控件。但TDrawGrid是TCustomDrawGrid的一个简单包装,因此

DrawCell仍然只简单地触发事件OnDrawCell,而没有真正实现数据填充。也正因为如此,TDrawGrid的使用就相当灵活,我们可以利用它绘制文

本、图形图像等多种信息。
TStringGrid派生于TDrawGrid,专门用于描述文本信息。从以下源代码可以看到,它真正实现了数据填充:
    procedure TStringGrid.DrawCell(ACol, ARow: Longint; ARect: TRect;
AState: TGridDrawState);
    begin
      if DefaultDrawing then
        Canvas.TextRect(ARect, ARect.Left+2, ARect.Top+2, Cells[ACol, ARow]);{即这句}
      inherited DrawCell(ACol, ARow, ARect, AState);
    end;

4、TDBGrid是数据敏感类的网格控件。它是对TCustomDBGrid的简单包装,而TCustomDBGrid的实现原理和普通网格控件是类似的,主要的区别

在于数据源不同。比如TStringGrid的数据来自于TStringGrid.Cells,而TCustomDBGrid的数据来自于TCustomDBGrid.DataSource.DataSet。

二、TCustomGrid的主要功能
前面已经说了,TCustomGrid定义了网格控件的主要功能,具有网格控件的主要特征,因此要理解网格控件的基本原理,重点在于TCustomGrid

的两个方法:Paint和DrawCell。
DrawCell是一个纯虚方法,在Paint中被调用(具体过程参见下文),因此理解的重点是在两个地方:
(1)Paint有什么用,Paint是如何运作的。
(2)Paint中做了什么工作。

1、Paint的运作机制。
前面说过了,Paint用来绘制控件自身外形。Paint内部定义了具体的绘制方法,因此,只要在适当的时间和地点调用Paint,就可以改变控件外

观。
在VCL中,可将Paint方法简单理解为TControl对Windows标准消息WM_PAINT的反应。调用Win32

API中的UpdateWindow、RedrawWindow和InvalidateRect以及VCL中TControl的Repaint、Refresh和Update方法等都会直接或者间接引发相应的W

M_PAINT消息。
因此,网格控件的基本运作原理就是:数据或者数据源本身发生变化后,通过适当方式调用Paint方法,从而更新数据填充。拿TStringGrid为

例,其Cells的数据改变后:
    procedure TStringGrid.SetCells(ACol, ARow: Integer; const Value: string);
    begin
      TStringGridStrings(EnsureDataRow(ARow))[ACol] := Value;
      EnsureColRow(ACol, True);
      EnsureColRow(ARow, False);
      Update(ACol, ARow); {这句内部调用Win32 API的InvalidateRect标记[ACol,

ARow]所指区域需要重画;系统接着就会发送一个WM_PAINT消息。最终引起Paint的执行。}
end;

2、Paint所做工作。先看看我简化后的源代码,更容易说清楚。以“★”为各功能部分划分标记:
    procedure TCustomGrid.Paint;
 
      procedure DrawLines(DoHorz, DoVert: Boolean; Col, Row: Longint;
        const CellBounds: array of Integer; OnColor, OffColor: TColor);
      begin
        {……}
      end;
 
      procedure DrawCells(ACol, ARow: Longint; StartX, StartY, StopX, StopY: Integer; Color: TColor; IncludeDrawState:

TGridDrawState);
      begin
        {……}
        {其中调用了TCustomGrid的纯虚方法DrawCell。
       因此TCustomGrid的子类可以覆盖这个方法,自定义数据的填充方式}
        DrawCell(CurCol, CurRow, Where, DrawState);
        {……}
      end;
 
    begin
      {★0:计算网络绘制参数}
      CalcDrawInfo(DrawInfo);
 
      with DrawInfo do
      begin
        {★1:绘制网格线(如果线宽>0)}
        if (Horz.EffectiveLineWidth > 0) or (Vert.EffectiveLineWidth > 0) then
        begin
          {左上角固定列}
          DrawLines(goFixedHorzLine in Options, goFixedVertLine in Options, 0, 0, [0, 0, Horz.FixedBoundary,

Vert.FixedBoundary], clBlack, FixedColor);
          {横向固定列}
          DrawLines(goFixedHorzLine in Options, goFixedVertLine in Options, LeftCol, 0, [Horz.FixedBoundary, 0,

Horz.GridBoundary, Vert.FixedBoundary], clBlack, FixedColor);
          {纵向固定列}
          DrawLines(goFixedHorzLine in Options, goFixedVertLine in Options, 0, TopRow, [0, Vert.FixedBoundary,

Horz.FixedBoundary, Vert.GridBoundary], clBlack, FixedColor);
          {非固定列}
          DrawLines(goHorzLine in Options, goVertLine in Options, LeftCol, TopRow, [Horz.FixedBoundary, Vert.FixedBoundary,

??? Horz.GridBoundary, Vert.GridBoundary], LineColor, Color);
        end;
 
        {★2:填充数据}
        {左上角固定列}
        DrawCells(0, 0, 0, 0, Horz.FixedBoundary, Vert.FixedBoundary, ??? FixedColor, [gdFixed]);
        {横向固定列}
        DrawCells(LeftCol, 0, Horz.FixedBoundary – FColOffset, 0, ??? Horz.GridBoundary, Vert.FixedBoundary, FixedColor,

[gdFixed]);
        {纵向固定列}
        DrawCells(0, TopRow, 0, Vert.FixedBoundary, Horz.FixedBoundary, ?Vert.GridBoundary, FixedColor, [gdFixed]);
        {非固定列}
        DrawCells(LeftCol, TopRow, Horz.FixedBoundary – FColOffset, Vert.FixedBoundary, Horz.GridBoundary, Vert.GridBoundary,

Color, []);
 
        {★3:给被选中网格绘制外框}
        Canvas.DrawFocusRect(FocRect);
 
        {★4:填充客户区中未被网格占用的区域}
        {横向部分}
        if Horz.GridBoundary < Horz.GridExtent then
        begin
          Canvas.Brush.Color := Color;
          Canvas.FillRect(Rect(Horz.GridBoundary, 0, Horz.GridExtent, ??? Vert.GridBoundary));
        end;
        {纵向部分}
        if Vert.GridBoundary < Vert.GridExtent then
        begin
          Canvas.Brush.Color := Color;
          Canvas.FillRect(Rect(0, Vert.GridBoundary, Horz.GridExtent, Vert.GridExtent));
        end;
      end;
    end;

从以上代码可见,TCustomGrid.Paint主要可以分为五个部分。其中★0用于计算当前绘制参数,结果用于后面4个部分。接下来4个部分中,★1

和★2是主体。因此我们关注的重点是★0、★1和★2。★1和★2已有详细注解,所以不逐行解释了,有兴趣但看不懂的可慢慢琢磨。最后对★0

的DrawInfo作个解释。
DrawInfo为TGridDrawInfo类型,定义如下:
    TGridDrawInfo = record {网络绘制参数}
      Horz, Vert: TGridAxisDrawInfo; {分为横向和纵向两个部分}
    end;
 
下面以横向为例,解释TGridAxisDrawInfo的含义:
    TGridAxisDrawInfo = record
      EffectiveLineWidth: Integer;    {网格线宽}
      FixedBoundary: Integer;        {网格固定列总宽度(含网格线)}
      GridBoundary: Integer;        {网格各列总宽度(含网格线、固定列)}
      GridExtent: Integer;        {网格客户区总宽度}
      LastFullVisibleCell: Longint;    {当前最后一个未超出客户区(即能全部看见)的列}
      FullVisBoundary: Integer;    {当前可全部看见列的总宽度(含网格线)}
      FixedCellCount: Integer;    {固定列个数}
      FirstGridCell: Integer;    {第一个非固定列,即LeftCol(横向)或者TopRow(纵向)}
      GridCellCount: Integer;    {即ColCount,总列数}
      GetExtent: TGetExtentsFunc;    {一个函数,用于取得列宽,相当于ColWidths[Index]}
end;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107087.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 项目管理复习题

    项目管理复习题蓝字位注释,红字为错误原因,紫字为重点本复习题链接:https://pan.baidu.com/s/1ZJ4l6mKxAt9dqhw0Qa58xA提取码:j4jz第一章一、填空题1.敏捷模型包括(4)个核心价值,对应(12)个敏捷原则。2.项目管理包括(启动过程组)、(计划过程组)、(执行过程组)、(控制过程组)、(收尾过程组)5个过程组。二、判断题1、搬家属于项目。(√)2、项目是为了创造一个唯一的产品或提供一个唯一的服务而进行的永久性的努力。(×)3、过程管理就是.

    2022年6月11日
    48
  • “请在微信客户端打开链接”解决方案[通俗易懂]

    “请在微信客户端打开链接”解决方案[通俗易懂]1、“请在微信客户端打开链接”解决方案https://blog.csdn.net/weixin_41190571/article/details/829908392、微信调试工具无法点击授权按钮https://blog.csdn.net/Call_me_small_pure/article/details/801013073、微信web开发工具https://mp.weixin.qq.c…

    2022年5月6日
    296
  • cmd: cd /D %~dp0 的含义「建议收藏」

    cmd: cd /D %~dp0 的含义「建议收藏」cd/d%~dp0是什么意思啊?批处理文件中的一条语句意思是 更改当前目录为批处理本身的目录 有些晕吧?不急,我举例 比如你有个批处理a.bat在D:\qq文件夹下 a.bat内容为 cd/d%~dp0在这里cd/d表示直接转换到后面的路径,否则如果切换盘符,就需要再输入盘符才能切换路径cd/d%~dp0的意思就是cd/dd:\qq %0代表批处理本身…

    2026年1月28日
    4
  • Postman报错Unsupported Media Type

    Postman报错Unsupported Media Type报错信息如下:{“timestamp”:”2018-12-06T01:37:11.184+0000″,”status”:415,”error”:”UnsupportedMediaType”,”message”:”Contenttype’text/plain;charset=UTF-8’notsupported”,”path”:”/testgu/ycyzha…

    2022年5月9日
    230
  • 软件测试基础知识 + 面试理论(超详细)「建议收藏」

    软件测试基础知识 + 面试理论(超详细)「建议收藏」文章目录一、什么是软件?二、什么是软件测试?三、软件测试工程师的工作内容四、常见的软件生命周期模型五、软件开发的几个阶段六、软件bug的五个要素七、软件测试的分类八、什么是测试用例九、测试用例几大要素【面试理论知识】1、你的测试职业发展是什么?2、你认为测试人员需要具备哪些素质3、你为什么能够做测试这一行4、测试的目的是什么?5、测试分为哪几个阶段?6、单元测试的测试对象、目的、测试依据、测试方法?7、怎样看待加班问题8、结合你以前的学习和工作经验,你认为如何做好测试。9、你为什么选择软件测试行业10、根据

    2022年6月29日
    25
  • 0929【非常好】 库仑计计算电量 Fuel Gauge 锂离子电池及电池电量计介绍

    0929【非常好】 库仑计计算电量 Fuel Gauge 锂离子电池及电池电量计介绍锂离子电池及电池电量计介绍 Li ionBatteryan www richtek com Design 20Support Technical 20Document AN024 sc lang zh CN1 锂离子电池介绍 1 1 荷电状态 State Of Charge SOC 荷电状态可定义为电池中可用电能的状态

    2025年7月29日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号