对于使用本机组件的多平台应用程序,标准的Delphi方法已不再适用.到目前为止,我们的结构只有部分:GUI(表单)和业务逻辑.我们现在需要将"Forms"部分拆分为两个,这在MVVM上下文中将是View和ViewModel.
View和ViewModel之间的绑定可以通过不同方式处理:
可能会有更多.我知道这对某些人来说是一个宗教问题,但我仍然希望能得到客观答案:
如果您在Firemonkey应用程序中使用适合长期视角的多平台开发的解决方案:您做出的决定背后有哪些考虑因素?
两个Cardinal和Single是4字节/ 32比特的数据类型,但是当我他们类型强制转换为彼此我得到一个Invalid Typecast错误的Delphi 10.1(柏林).
lSingleVar := Single(lCardinalVar);
Run Code Online (Sandbox Code Playgroud)
我不是在谈论在两种类型之间进行转换,因为它只存储23位基数数据(Single数据类型的小数部分).我需要将至少30位数据存储到Single变量中.我有充分的理由(类型无法更改),我将很乐意详述.
我如何对Single变量进行类型转换?
我正在将一个大型项目转换为Firemonkey,并且我们有一些自定义按钮,这些按钮不会显示在表单上.我已将问题分离到一个非常简单的项目:
使用下面的代码,在移动和桌面上(使用Delphi XE6中的默认新应用程序),创建tTestButton1工作正常,但tTestButton2不会在窗体上显示.怎么可能?
type
tTestButton1 = class(TButton);
tTestButton2 = class(tTestButton1);
tMainForm = class(TForm)
private
fTestButton: TButton;
public
constructor Create(aOwner: TComponent); override;
end;
constructor tMainForm .Create(aOwner: TComponent);
begin
inherited;
// fTestButton := tTestButton1.Create(Self); // this works fine (used instead of next line)
fTestButton := tTestButton2.Create(Self); //this button does not show up
fTestButton.Text := 'Test';
fTestButton.Parent := Self;
fTestButton.Visible := True;
fTestButton.Position.X := 20;
fTestButton.Position.Y := 20;
end;
Run Code Online (Sandbox Code Playgroud) 从时间戳(TDateTime)计算32位ID时,我得到一个奇怪的错误.在某些情况下,不同处理器的值不同.
该fTimeStamp字段是从DoubleSQLite数据库中的字段中读取的.下面的代码计算一个32位ID(lIntStamp)fTimeStamp,但在某些(罕见)情况下,即使源数据库文件完全相同(即文件中存储的Double相同),不同计算机上的值也不同.
...
fTimeStamp: TDateTime
...
var
lIntStamp: Int64;
begin
lIntStamp := Round(fTimeStamp * 864000); //86400=24*60*60*10=steps of 1/10th second
lIntStamp := lIntStamp and $FFFFFFFF;
...
end;
Run Code Online (Sandbox Code Playgroud)
TDateTime(Double)的精度是15位数,但代码中的舍入值仅使用11位数,因此应该有足够的信息正确舍入.
提一个值的例子:在特定的测试运行中,lIntStampWindows计算机上的值为74AE6699B,iPad上的值为74AE699A(=最后一位不同).
Round每个平台上的功能实现不同吗?
PS.我们的目标平台目前是Windows,MacOS和iOS.
编辑:
我根据评论做了一个小测试程序:
var d: Double;
id: int64 absolute d;
lDouble: Double;
begin
id := $40E4863E234B78FC;
lDouble := d*864000;
Label1.text := inttostr(Round(d*864000))+' '+floattostr(lDouble)+' '+inttostr(Round(lDouble));
end;
Run Code Online (Sandbox Code Playgroud)
Windows上的输出是:
36317325723 36317325722.5 36317325722
Run Code Online (Sandbox Code Playgroud)
在iPad上输出是:
36317325722 36317325722.5 36317325722
Run Code Online (Sandbox Code Playgroud)
区别在于第一个数字,它显示了中间计算的舍入,因此问题发生是因为x86具有比ARM(64位)更高的内部精度(80位).
我有一个包含许多自定义 firemonkey 组件的表单,其中每个组件都包含多个位图(从 PNG 图像文件加载)。每次保存表单时,FMX 文件中 PNG 图像的二进制数据都会发生变化!
这弄乱了我的版本控制日志 (SVN),因为仅更改表单中的一个属性会导致数千行更改。
有什么办法可以避免这种情况吗?
在此处查看 SVN 差异的屏幕截图:

表单保存时,DotInlay.PNG图像没有被我更改,甚至包含图像的控件也没有任何更改。
编辑: 根据评论,这是 Delphi 中的一个错误,所以我创建了一个新的 QP 报告:https : //quality.embarcadero.com/browse/RSP-11259
如果您认为应该解决它,请为它投票。
“Google Play 管理中心”中的“发布前报告概述”显示以下警告:
类型:
Non-SDK API
Run Code Online (Sandbox Code Playgroud)
应用程序编程接口:
Landroid/view/MotionEvent;-><init>()V
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪:
StrictMode policy violation: android.os.strictmode.NonSdkApiUsedViolation: Landroid/view/MotionEvent;-><init>()V
Run Code Online (Sandbox Code Playgroud)
此错误之前已在 Delphi 10.3 中修复,请参阅https://quality.embarcadero.com/browse/RSP-22046 ,但现在又回到了 Delphi 11 中?
我在 Google 上可以找到的解决方案是targetSdkVersion在中设置较新的AndroidManifest.xml
解决方案。但是,我们已经将其设置为 API 级别 30,因为需要部署到新的 Play 商店。在 AndroidManifest.xml 中我们有:
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="30" />
Run Code Online (Sandbox Code Playgroud)
最近有人在 Play 商店上的“Delphi 11”应用程序中看到过此错误吗?- 最终找到了解决方案吗?
从Windows API调用(GetUserPreferredUILanguages()),我得到一个字符串列表作为一个空分隔PWideChar.我需要将其转换为Delphi字符串列表.我开始编写代码来手动遍历列表,寻找#0字符.
有更聪明的方法吗?
PWideChar返回的示例GetUserPreferredUILanguages:
('e','n','-','U','S',#0,'f','r','-','F','R',#0,#0,...)
Run Code Online (Sandbox Code Playgroud)
(根据我在文档中读到的内容,因为当我在计算机上调用该函数时,它只返回一种语言,即'en-US'#0#0)
到目前为止,这是我的代码:
procedure GetWinLanguages(aList: TStringList);
var lCount, lSize: ULong;
lChars: array of WideChar;
lIndex, lLastIndex: integer;
begin
lSize := 1000;
SetLength(lChars, lSize);
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, @lCount, @lChars[0], @lSize);
// untested quick solution to convert from lChars to aList
lIndex := 0;
lLastIndex := -1;
while (lIndex<=lSize) do
begin
while (lIndex<lSize) and (lChars[lIndex]<>#0) do
inc(lIndex);
if (lIndex-lLastIndex)>1 then
begin
// here: copy range lLastIndex to lIndex, convert …Run Code Online (Sandbox Code Playgroud) delphi ×7
firemonkey ×5
delphi-xe7 ×3
android ×1
delphi-xe6 ×1
google-play ×1
mvvm ×1
png ×1
sqlite ×1