XE7下修改FMX.Grid.pas解决Grid列头与文本内容的样式设定,实现标题栏文字居中,内容的文本可右对齐。
2014-09-20 16:18
573 查看
在XE6上,已经有人研究过 Grid 的样式。在QQ群里,【深圳从头再来】说它的XE5,对于设置列头列内容的样式很完美,并帮我做了一个测试例子,可是发给我在XE6上编译,却没有想要的结果。尽管对于列头的样式,在点过按钮中确实生效,但是我想在Create事件中调用按钮的样式设定,却不成功,不知是什么原因。后来,我把XE6卸载,安装了XE7,运行后,与XE6上的不理想效果一致,这令我很惊讶。按道理,工具版本的升级,只可能更方便更完美,却是如此的不尽人意。网上也参考了【红鱼儿糊思乱想】的Grid试用结果,并且,后来【广州weii】也进行了试验,博文如下:http://www.cnblogs.com/weii/p/3977320.html。weii是最接近效果的,它设置标头的办法与红鱼儿博文中差不多。另外,对StringGrid进行了TextSettings设置,这个参数影响到网格内所有列的显示样式。仍然是不能独立为各个列设置对齐方式。
我们的习惯,标题的文字一定是居中的,并且有时为了突出显示,或是设为粗体,或是红色什么的。对于内容,比如显示的字符长度固定,往往居中;对于金额,右对齐。可是,目前来说这个Grid,已有的属性无法做到。而且,在设置统一右对齐时,太靠右了,列头右线和内容右线也有1个像素的偏差。如下图所展现的:
要找到解决办法,我先尝试着看一看TStringGrid类的代码,它在C:\Program Files (x86)\Embarcadero\Studio\15.0\source\fmx\FMX.Grid.pas文件中。因此,我们可以把这个源文件复制一份,放在当前测试的工程目录下。然后对代码进行更改,因为编译时,对于同名单元,优先当前目录的源文件。TStringGrid是TCustomGrid的子类,同样,TGrid也是从TCustomGrid继承而来的。TCustomGrid中各列,其基类是TColumn,所以不管是TStringColumn, TDateColumn,TCheckColumn,都有一些共同属性。通过对FMX.Grid.pas的研究修改,最终实现了想要的效果。现把要FMX.Grid.pas中增加的代码发布出来:
1. TColumn类定义进行修改,第4行代码是原来的设置值为2,注释掉,设为5,使得显示的内容离左、右边线稍远一点点。
2. TColumn的Create方法,设置加入属性的默认值,此处设置列头(标题栏)默认居中。
3. 列内容的绘制效果定义,全在DefaultDrawCell中了。
从上面代码第36~39行可知,原来在Grid中设置的TextSettings值,在所有列都应用它的设定值了。因此,添加第42~47行代码替换。
4. 列头样式的设定,需要更改TCustomGrid.UpdateHeader部分:
至此,源码部分已经更改完毕。我们测试例子,放上Button1加载数据,Button2对齐数据,添加代码如下:
运行效果如下:
后记:所增加的10个参数,最理想的是在可视化设计时设置。可惜我不知道FMX.Grid.pas是在系统的哪个dpk包,所以没法重编译安装一下。
并且,之所以用10个参数,而不能像TStringGrid的TextSetting参数,是因为之前我也用了两个
FHeadSettings : TTextSettings
FTextSettings : TTextSettings
来包含现在的,但是这是一个组合的属性类,在TColumn的Create时也创建FHeadSettings,FTextSettings,并且在Destory释放。
但是在测试例子赋值后,DefaultDrawCell,UpdateHeader执行时却仍得不到期望的,所以只得精简出10个有用的来设置。
使用方法:将更改过的 FMX.Grid.pas 拷到你的Project目录下,并最好加到 Project 中。至于其它版本,应该根据这个思路修改,再去测试调整。
本测试例子,感谢【[深圳]从头再来(358880222)】给我的帮助,以及网络资源一大堆我记不住名字的有名氏。
有改进的东东,比如多行标题,某标题列还能合并,加入合计栏等... 不妨email给我一份:3822640@qq.com,共同学习。
我们的习惯,标题的文字一定是居中的,并且有时为了突出显示,或是设为粗体,或是红色什么的。对于内容,比如显示的字符长度固定,往往居中;对于金额,右对齐。可是,目前来说这个Grid,已有的属性无法做到。而且,在设置统一右对齐时,太靠右了,列头右线和内容右线也有1个像素的偏差。如下图所展现的:
要找到解决办法,我先尝试着看一看TStringGrid类的代码,它在C:\Program Files (x86)\Embarcadero\Studio\15.0\source\fmx\FMX.Grid.pas文件中。因此,我们可以把这个源文件复制一份,放在当前测试的工程目录下。然后对代码进行更改,因为编译时,对于同名单元,优先当前目录的源文件。TStringGrid是TCustomGrid的子类,同样,TGrid也是从TCustomGrid继承而来的。TCustomGrid中各列,其基类是TColumn,所以不管是TStringColumn, TDateColumn,TCheckColumn,都有一些共同属性。通过对FMX.Grid.pas的研究修改,最终实现了想要的效果。现把要FMX.Grid.pas中增加的代码发布出来:
1. TColumn类定义进行修改,第4行代码是原来的设置值为2,注释掉,设为5,使得显示的内容离左、右边线稍远一点点。
TColumn = class(TStyledControl) private const { 边距设大一点,效果更美观些 } // HorzTextMargin = 2; HorzTextMargin = 5; {\\\ end add 2014/9/18} VertTextMargin = 1; private ...... [Weak] FGrid: TCustomGrid; {/// 为列头和内容设置样式的参数 } FHeadAlign : TTextAlign; // 列头文字对齐方式 FHeadFontColor : TAlphaColor; // 列头文字颜色 FHeadFontName : TFontName; // 列头文字字体 FHeadFontSize : Single; // 列头文字大小 FHeadFontStyle : TFontStyles; // 列头文字样式 FTextAlign : TTextAlign; // 内容文本对应方式 FTextFontColor : TAlphaColor; // 内容文本颜色 FTextFontName : TFontName; // 内容文本字体 FTextFontSize : Single; // 内容文本大小 FTextFontStyle : TFontStyles; // 内容文本样式 {\\\ end add 2014/9/18} procedure SetHeader(const Value: string); ...... published {/// 放出参数可进行设置 } property HeadAlign : TTextAlign read FHeadAlign write FHeadAlign; property HeadFontColor : TAlphaColor read FHeadFontColor write FHeadFontColor; property HeadFontName : TFontName read FHeadFontName write FHeadFontName; property HeadFontSize : Single read FHeadFontSize write FHeadFontSize; property HeadFontStyle : TFontStyles read FHeadFontStyle write FHeadFontStyle; property TextAlign : TTextAlign read FTextAlign write FTextAlign; property TextFontColor : TAlphaColor read FTextFontColor write FTextFontColor; property TextFontName : TFontName read FTextFontName write FTextFontName; property TextFontSize : Single read FTextFontSize write FTextFontSize; property TextFontStyle : TFontStyles read FTextFontStyle write FTextFontStyle; {\\\ end add 2014/9/18} ...... end;
2. TColumn的Create方法,设置加入属性的默认值,此处设置列头(标题栏)默认居中。
constructor TColumn.Create(AOwner: TComponent); begin inherited; {/// 增加参数设置默认值 } FHeadAlign := TTextAlign(0); // 列头默认居中 FHeadFontColor := TAlphaColors.Black; FHeadFontName := 'Tahoma'; FHeadFontSize := 12.0; FHeadFontStyle := []; FTextAlign := TTextAlign(1); FTextFontColor := TAlphaColors.Black; FTextFontName := 'Tahoma'; FTextFontSize := 12.0; FTextFontStyle := []; {\\\ end add 2014/9/18} FLastRow := -1; FDrawLayouts := TObjectList<TTextLayout>.Create; Width := 100; HitTest := False; CanFocus := False; FEditMode := -1; FApplyImmediately := True; end;
3. 列内容的绘制效果定义,全在DefaultDrawCell中了。
procedure TColumn.DefaultDrawCell(const Canvas: TCanvas; const Bounds: TRectF; const Row: Integer; const Value: TValue; const State: TGridDrawStates); var R: TRectF; Layout: TTextLayout; LocalRow: Integer; begin if FDrawable <> nil then FDrawable.DrawCell(Canvas, Bounds, Row, Value, State) else begin R := Bounds; { 根据对齐设置,进行调整 } // R.Inflate(-HorzTextMargin, -VertTextMargin); // 原来是这句,注释了,由下面部分来设定。解决右对齐时太靠边线的问题 if FTextAlign = TTextAlign.Leading then R.Inflate(-HorzTextMargin, -VertTextMargin) else if FTextAlign = TTextAlign.Trailing then R.Inflate(HorzTextMargin, -VertTextMargin); {\\\ end add 2014/9/18} LocalRow := Row - Grid.TopRow; if LocalRow >= FDrawLayouts.Count then begin Layout := TTextLayoutManager.DefaultTextLayout.Create(Canvas); FDrawLayouts.Add(Layout); end else Layout := FDrawLayouts[LocalRow]; Layout.BeginUpdate; try Layout.TopLeft := R.TopLeft; Layout.Text := ValueToString(Value); Layout.MaxSize := PointF(Width, Grid.RowHeight); Layout.WordWrap := False; Layout.Opacity := AbsoluteOpacity; Layout.HorizontalAlign := Grid.TextSettingsControl.ResultingTextSettings.HorzAlign; Layout.VerticalAlign := Grid.TextSettingsControl.ResultingTextSettings.VertAlign; Layout.Font.Assign(Grid.TextSettingsControl.ResultingTextSettings.Font); Layout.Color := Grid.TextSettingsControl.ResultingTextSettings.FontColor; Layout.Trimming := TTextTrimming.Character; { 设置文本内容显示的样式 } Layout.Font.Family := FTextFontName; Layout.Font.Size := FTextFontSize; Layout.Font.Style := FTextFontStyle; Layout.Color := FTextFontColor; Layout.HorizontalAlign := FTextAlign; Layout.VerticalAlign := TTextAlign(0); // 如有特别要求,可注释此行 {\\\ end add 2014/9/18} finally Layout.EndUpdate; end; Layout.RenderLayout(Canvas); end; end;
从上面代码第36~39行可知,原来在Grid中设置的TextSettings值,在所有列都应用它的设定值了。因此,添加第42~47行代码替换。
4. 列头样式的设定,需要更改TCustomGrid.UpdateHeader部分:
procedure TCustomGrid.UpdateHeader; var I: Integer; Item: THeaderItem; C: TFmxObject; LHeader: TOpenHeader; begin if not Assigned(FHeader) then Exit; LHeader := TOpenHeader(FHeader); LHeader.Sizing := TGridOption.ColumnResize in Options; LHeader.DragReorder := TGridOption.ColumnMove in Options; { 加1个值,让列头与内容右线对齐 } LHeader.Offset := -ViewportPosition.X + 1; {\\\ end add 2014/9/18} LHeader.RemoveObject(LHeader.LastItem); ...... for I := 0 to ColumnCount - 1 do begin TGridHeaderItem(LHeader.Children[I]).Text := Columns[I].Header; TGridHeaderItem(LHeader.Children[I]).Width := Columns[I].Width; TGridHeaderItem(LHeader.Children[I]).Visible := Columns[I].Visible; TGridHeaderItem(LHeader.Children[I]).Column := Columns[I]; { 设置列头的样式 } with TGridHeaderItem(LHeader.Children[I]) do begin StyledSettings := []; // 如果没有这句,则字体大小,颜色不会改变 TextAlign := Columns[I].HeadAlign; Font.Family := Columns[I].HeadFontName; Font.Size := Columns[I].HeadFontSize; Font.Style := Columns[I].HeadFontStyle; FontColor := Columns[I].HeadFontColor; end; {\\\ end add 2014/9/18} end; LHeader.Realign; if FHeader.Visible <> (TGridOption.Header in FOptions) then begin FHeader.Visible := TGridOption.Header in FOptions; RealignContent; end; end;
至此,源码部分已经更改完毕。我们测试例子,放上Button1加载数据,Button2对齐数据,添加代码如下:
procedure TForm1.FormCreate(Sender: TObject); begin Button1Click(nil); end; procedure TForm1.Button1Click(Sender: TObject); var i,j:Integer; begin StringGrid1.RowCount := 10; StringGrid1.BeginUpdate; for j := 0 to 2 do begin StringGrid1.Columns[j].Width := 80; for I := 0 to 9 do StringGrid1.Cells[j, I] := 'XE7-'+inttostr(i)+inttostr(j); end; StringGrid1.EndUpdate; end; procedure TForm1.Button2Click(Sender: TObject); var i: Integer; begin StringGrid1.BeginUpdate; for i := 0 to StringGrid1.ColumnCount - 1 do begin // 设置所有列头文字,蓝色粗体并大一些, StringGrid1.Columns[i].HeadFontColor := TAlphaColors.Blue; StringGrid1.Columns[i].HeadFontSize := 15; StringGrid1.Columns[i].HeadFontStyle := [TFontStyle.fsBold]; //StringGrid1.Columns[i].HeadAlign := TTextAlign(2); // 默认是居中了,也可以更改 end; // 设置第二列文本,居中,绿字 StringColumn2.TextAlign := TTextAlign(0); StringColumn2.TextFontName := '宋体'; StringColumn2.TextFontColor := TAlphaColors.Green; // 设置第三列文本,右对齐,红字 StringColumn3.TextAlign := TTextAlign(2); StringColumn3.TextFontColor := TAlphaColors.Red; StringGrid1.RealignContent; // 使内容文本样式有效 StringGrid1.EndUpdate; // 使列头文字样式有效 end;
运行效果如下:
后记:所增加的10个参数,最理想的是在可视化设计时设置。可惜我不知道FMX.Grid.pas是在系统的哪个dpk包,所以没法重编译安装一下。
并且,之所以用10个参数,而不能像TStringGrid的TextSetting参数,是因为之前我也用了两个
FHeadSettings : TTextSettings
FTextSettings : TTextSettings
来包含现在的,但是这是一个组合的属性类,在TColumn的Create时也创建FHeadSettings,FTextSettings,并且在Destory释放。
但是在测试例子赋值后,DefaultDrawCell,UpdateHeader执行时却仍得不到期望的,所以只得精简出10个有用的来设置。
使用方法:将更改过的 FMX.Grid.pas 拷到你的Project目录下,并最好加到 Project 中。至于其它版本,应该根据这个思路修改,再去测试调整。
本测试例子,感谢【[深圳]从头再来(358880222)】给我的帮助,以及网络资源一大堆我记不住名字的有名氏。
有改进的东东,比如多行标题,某标题列还能合并,加入合计栏等... 不妨email给我一份:3822640@qq.com,共同学习。
相关文章推荐
- Android UI 之居中绘制文本内容的正确方法——实现自定义一个TextView
- input文本框、文字、按钮、图片 垂直居中对齐的解决办法
- 解决Android中RadioButton图片和文本居中及底部经常被工具烂覆盖掉内容
- 【使用JSOUP实现网络爬虫】修改数据-设置元素的文本内容
- Android编程实现修改标题栏位置使其居中的方法
- input文本框、文字、按钮、图片 垂直居中对齐的解决办法
- DevExpress实现自定义GridControl中按钮文字内容的方法
- 一个解决表单中的文字和文本区域(textarea)上对齐的方法
- ckeditor:复制内容到ckeditor时,只保留文本,忽略其样式解决方法
- 针对bootstrap内联单选框input与文字不能居中对齐的解决办法
- 使用PYTHON实现如何修改文本文件中的内容
- 完美解决固定容器高度,文字内容一行或多行,文字上下居中,解决兼容性
- ie6下li内图片和文字不居中对齐的解决办法
- 【使用JSOUP实现网络爬虫】修改数据-设置元素的文本内容
- css 文字按钮实现样式submit按钮以文本的形式显示出来
- 实现 多行文本在父容器里 先居中 并且每行文本都左对齐
- Android UI 之居中绘制文本内容的正确方法——实现自定义一个TextView
- CSS入门之文本样式用法(文本对齐,首行缩进,文本竖排,文字方向)
- HTML textarea 文本区域 外面说明文字垂直居中对齐的问题
- 纯CSS实现文字一行居中,多行左对齐的方法