今天我们来做一件坏事,我们都是坏孩子……
我们知道,FMX 是有 StyleBook,每个控件有自己的样式,但有时候,我们要绘制自绘一些状态,难道非要用户重新定义一堆样式吗?为啥不能利用现成的样式呢,比如,我就只是要自绘一个CheckBox,但我还不想放置一个TCheckBox组件,那么怎么来做呢?
第一:我们需要知道 TCheckBox 使用的样式名称, 按照官方的命名规则,它是去掉 T,变小写,然后再加 style,也就是说,样式的名称为 checkboxstyle。
第二:我们需要知道我们要找的样式的名称,对于 CheckBox,它是 background,当然你也可以不要去管它,你按类型来找,比如这里是它子对象中类型为 TCheckStyleObject 类型的对象。
第三:如果我们是通过名称来找的话,就需要判断下是不是对应的样式对象,如果不是,就不能继续了,如果是才能继续。如果是的话,我们就可以调用样式对象的 DrawToCanvas 方法,将其绘制到目标画布上了。
到了这一步,我们就画出了一个简单的复选框,但是如果我们要绘制一个选中的复选框怎么办?继续
第四:我们要添加一个IsChecked 属性,当然如果是别的属性(布尔值),你就需要设置 TCheckStyleObject 对象的 ActiveTrigger,设置后调用 StartTriggerAnimation 来启用这个触发器,比如 IsChecked。
第五:回到第三步,绘制到画布上就好了。
简单的参考代码如下:
uses fmx.styles.objects; {$R *.fmx} procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var ARes: TFMXObject; AStyle: TCheckStyleObject; begin ARes := TStyledControl.LookupStyleObject(nil, nil, Self, 'checkboxstyle', '', '', false); ARes := ARes.FindStyleResource('background', true); if Assigned(ARes) and (ARes is TCheckStyleObject) then begin AStyle := TCheckStyleObject(ARes as TCheckStyleObject); AStyle.StartTriggerAnimation(Self, 'IsChecked');//只绘制普通的选择框不需要它,更具体请看 Delphi 自己的源码实现 AStyle.DrawToCanvas(Canvas, RectF(10, 10, 10 + AStyle.Width, 10 + AStyle.Height)); end; end; function TForm1.GetIsChecked: Boolean; begin Result := true; end;
当然了,如果嫌这里调用 StartTrigger 麻烦,直接修改其私有的 FState 成员就得了,具体方法,参考以前的文章。
好吧,附个图,有图有真相: