当前位置:网站首页>vcl啥意思_oval
vcl啥意思_oval
2022-08-04 13:09:00 【全栈程序员站长】
大家好,又见面了,我是你们的朋友全栈君。
网格(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.cn/107087.html原文链接:https://javaforall.cn
边栏推荐
猜你喜欢

项目里的各种配置,你都了解吗?

手搓一个“七夕限定”,用3D Engine 5分钟实现烟花绽放效果

Interviewer: Tell me the difference between NIO and BIO

How to stress the MySQL performance indicators TPS\QPS\IOPS?

漏洞复现 - - - Alibaba Nacos权限认证绕过

双目立体视觉笔记(二)

CLS-PEG-DBCO,胆固醇-聚乙二醇-二苯基环辛炔,可用于改善循环时间

技术分享| 小程序实现音视频通话

GeoAO:一种快速的环境光遮蔽方案

《社会企业开展应聘文职人员培训规范》团体标准在新华书店上架
随机推荐
Is the code more messy?That's because you don't use Chain of Responsibility!
基于双层共识控制的直流微电网优化调度(Matlab代码实现)
正确使用Impala的invalidate metadata与refresh语句
Two years of independent development experience Programmers tell us the experience of making money (listen to the masters who really make money)
持续交付(四)Jenkins多线程任务执行
智能电视可以打开小程序应用,再也不用头痛内存了
Geoffrey Hinton:深度学习的下一个大事件
双目立体视觉笔记(二)
关于mysql join 的一些说明
永磁同步电机FOC驱动代码讲解
A Collection of Flutter Tutorials (2022 Edition)
Django框架MySQL数据库到models模型的映射关系
判断密码是否包含键盘连续字母
并发刺客(False Sharing)——并发程序的隐藏杀手
RK1126编译gdb 板子上gdb调试程序
持续交付(三)Jenkinsfile语法使用介绍
router---动态路由匹配
Unity 3D模型展示框架篇之资源打包、加载、热更(Addressable Asset System | 简称AA)
d不要直接用转串
荧光磷脂PEG衍生物之一磷脂-聚乙二醇-荧光素,Fluorescein-PEG-DSPE