说明:
Fiiremonkey 的跨平台能力,大家有目共睹(一码同介面跨四平台),唯独移动平台在几何绘图方面,质量始终不尽人意,我也曾试着去修正(如:),也曾找过第三方案(如:),但都不完美,我一直在想,移动平台有这么强的绘图能力及质量(Android & iOS),如果能直接拿来用,不是很好?为什么 Firemonkey 要自己重写?
目前网上许多针对此问题的改善方案,但多以控件形式,且需依各平台的绘图函数来绘图,或仅提供固定的几何图形控件,如果能延用现有的 TCanvas.Draw????? 绘图代码,只要加入几行代码(或编译开关),就能达到原生绘图的效果,岂不是很理想,于是开是构想这种方案的可行性,最后证实是可行的。
要先说明的是,这里提供的只是一种改善方案,而不是修正,最终还是希望能受到 EMB 官方的关注,由官方来改进这个问题。
用法及效果:
FMX 的绘图方法:
InflateRect(DesRect,-(Canvas.stroke.Thickness / <span style="color: #800080">2),-(Canvas.stroke.Thickness / <span style="color: #800080">2)); <span style="color: #008000">//<span style="color: #008000"> 线在区内
Canvas.FillRect(DesRect,<span style="color: #800080">30,AllCorners,<span style="color: #800080">1<span style="color: #000000">);
Canvas.DrawRect(DesRect,<span style="color: #800080">30,<span style="color: #800080">1<span style="color: #000000">);
<span style="color: #0000ff">end;
var Rect,DesRect: TRectF;
begin
Rect := PaintBox1.LocalRect;
Canvas.stroke.Thickness := 10;
Canvas.stroke.Kind := TBrushKind.solid;
Canvas.stroke.Dash := TstrokeDash.DashDotDot; <span style="color: #008000">{<span style="color: #008000">$IFDEF UseNativeDraw<span style="color: #008000">}Canvas.NativeDraw(Rect,<span style="color: #0000ff">procedure <span style="color: #0000ff">begin <span style="color: #008000">{<span style="color: #008000">$ENDIF<span style="color: #008000">} <span style="color: #008000">//<span style="color: #008000"> 原生绘图 by Aone
<span style="color: #cccccc"> DesRect := Rect;
InflateRect(DesRect,-(Canvas.stroke.Thickness / 2),-(Canvas.stroke.Thickness / 2)); // 线在区内
Canvas.FillRect(DesRect,30,1);
Canvas.DrawRect(DesRect,1);
<span style="color: #008000">{<span style="color: #008000">$IFDEF UseNativeDraw<span style="color: #008000">}<span style="color: #0000ff">end);<span style="color: #008000">{<span style="color: #008000">$ENDIF<span style="color: #008000">} <span style="color: #008000">//<span style="color: #008000"> 原生绘图 by Aone
<span style="color: #cccccc">end;
运作原理:
- 它的运作原理很简单,就是先配置一个原生的绘图区域 Bitmap,再将几何图形画在这个区域里,最后将这个区域里的内容,转回 TBitmap,再显示到 Canvas 里
- 利用 Delphi Pascal Helper 语言特性,针对 TCanvas 来做扩展,如此才能达到不改动原有的绘图代码
- 目前这个作法,相同的绘图代码,可以跨四个平台:
-
我们无法触及 FMX 的最核心,只能利用这种 Bitmap 方式来变通,要知道这种方式可能带来的问题(记忆体及效能),才不致错用
- 注意:如果引用了 FMX.Graphics.Native 就必需使用下面的方式来写绘图代码,否则请不要引用:
<span style="color: #008000">{<span style="color: #008000">$IFDEF UseNativeDraw<span style="color: #008000">}Canvas.NativeDraw(Rect,<span style="color: #0000ff">procedure <span style="color: #0000ff">begin <span style="color: #008000">{<span style="color: #008000">$ENDIF<span style="color: #008000">} <span style="color: #008000">//<span style="color: #008000"> 原生绘图 by Aone
<span style="color: #008000">//<span style="color: #008000"> 绘图代码
<span style="color: #008000">{<span style="color: #008000">$IFDEF UseNativeDraw<span style="color: #008000">}<span style="color: #0000ff">end);<span style="color: #008000">{<span style="color: #008000">$ENDIF<span style="color: #008000">} <span style="color: #008000">//<span style="color: #008000"> 原生绘图 by Aone
调用原生绘图的 TCanvas 函数:函数有质量问题)
- 支持所有涂刷特性,除了 Bitmap 涂色尚未支持(若有此需求,可自行修改源码,加入此特性)
- FMX 在移动平台是不支持画线加渐层涂色,使用原生绘图,已经可以轻松实现(支持 Linear 线渐层及 Radial 圆渐层效果):
原生FMX</tr>
<tr>
<td><img src="https://www.jb51.cc/res/2019/01-12/18/8b624ec2e99ecb2a9d631a3bdfa6f9a1.png" alt=""></td>
<td><img src="https://www.jb51.cc/res/2019/01-12/18/0ed9476e06ae334d9d2764a81c95f505.png" alt=""></td></tr>
</table>
Box1Paint(Sender: TObject; Canvas: TCanvas); =Box1.LocalRect; Canvas.stroke.Thickness := stroke.Kind :=rushKind.Gradient; Canvas.stroke.Dash :=strokeDash.DashDotDot; Canvas.stroke.Gradient.Color :=stroke.Gradient.Color1 :=<span style="color: #008000">{<span style="color: #008000">$IFDEF UseNativeDraw<span style="color: #008000">}Canvas.NativeDraw(Rect,<span style="color: #0000ff">procedure <span style="color: #0000ff">begin <span style="color: #008000">{<span style="color: #008000">$ENDIF<span style="color: #008000">} <span style="color: #008000">//<span style="color: #008000"> 原生绘图 by Aone
<span style="color: #000000">
DesRect :=<span style="color: #000000"> Rect;
InflateRect(DesRect,<span style="color: #800080">1<span style="color: #000000">);<span style="color: #008000">{<span style="color: #008000">$IFDEF UseNativeDraw<span style="color: #008000">}<span style="color: #0000ff">end);<span style="color: #008000">{<span style="color: #008000">$ENDIF<span style="color: #008000">} <span style="color: #008000">//<span style="color: #008000"> 原生绘图 by Aone
<span style="color: #0000ff">end;已知问题:
文件下载:
2017.06.22 新增 TestArc Demo(已更新到 GitHub):
参考资料:
相关文章
从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+...32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...