Category: Firemonkey

How to fix "error creating form index out of range" in C++ FireMonkey?

I have this non usual error popping up whenever i open my project (not all projects): error creating form index out of range(25). Must be >= 0 and < 25. I was working with the project before this error totally fine, i really don't know what causes this. The project is for android device, and it's totally weird for me, because this never happened before this day. This happens when i open my project, it doesn't even let me see the main form, just the units and header files. My code was working fine.
Read More

How to post data to database immediately after editing is done in a firemonkey TStringGrid

In Rad Studio 10.3, I connect a StringGrid to a database by using LiveBindins Wizard and selecting FireDAC. Everything is fine except below issue: When user edits a cell and presses Enter the value is edited correctly but the new value does not post to database until user navigates to another row. In other words, if user changes a cell's value and stays at current row the new value is not posted to database. Is there any way to post the new value immediately after editing is done? If yes, how? If a sample is required here is the link of my issue's sample project.
Read More

Import IORegistryEntrySearchCFProperty from Macapi.IOKit in Delphi for OSX64

I used this import definition in OSX32 successfully: uses MacApi.ObjectiveC, MacApi.Foundation, Macapi.CoreFoundation, Macapi.Mach, Macapi.IOKit; type io_iterator_t = io_object_t; io_name_t = array[0..127] of AnsiChar; function IORegistryEntrySearchCFProperty(entry: io_registry_entry_t; plane: io_name_t; key: CFStringRef; allocator: CFAllocatorRef; options: IOOptionBits): CFTypeRef; cdecl; external libIOKit name _PU + 'IORegistryEntrySearchCFProperty'; function IOServiceGetMatchingServices(masterPort: mach_port_t; matching: CFDictionaryRef; var existing: io_iterator_t): kern_return_t; cdecl; external libIOKit name _PU + 'IOServiceGetMatchingServices'; function IOIteratorNext(name: io_iterator_t): io_object_t; cdecl; external libIOKit name _PU + 'IOIteratorNext'; const kIOSerialBSDServiceValue = 'IOSerialBSDClient'; kIOSerialBSDTypeKey = 'IOSerialBSDClientType'; kIOSerialBSDModemType = 'IOModemSerialStream'; kIOUSBDeviceClassName = 'IOUSBDevice'; kIOCalloutDeviceKey = 'IOCalloutDevice'; kIOTTYDeviceKey = 'IOTTYDevice'; kIOServicePlane = 'IOService'; kUSBInterfaceNumber = 'bInterfaceNumber'; kUSBVendorID = 'idVendor'; kUSBProductID = 'idProduct'; kIORegistryIterateRecursively = $00000001; kIORegistryIterateParents = $00000002; Since the migration to OSX64 I get a read access violation within the function IORegistryEntrySearchCFProperty. From my point of view, there is no change in the parameters of IORegistryEntrySearchCFProperty from 32bit to 64bit. The API function is used to read out vendor ID and the product ID of a USB device: function TSerialInterface.SearchUSBSerialDevice(const Service: string; VendorID, ProductID: cardinal): integer; var MatchingDictionary: CFMutableDictionaryRef; Iter: io_iterator_t; USBRef: io_service_t; ret: kern_return_t; ResAsCFString: CFTypeRef; aBsdPath: PAnsiChar; Bsd: array[0..1024] of AnsiChar; sBsd: string; VID, PID: Int32; begin result := 0; MatchingDictionary := IOServiceMatching(kIOSerialBSDServiceValue); ret := IOServiceGetMatchingServices(kIOMasterPortDefault, CFDictionaryRef(MatchingDictionary), Iter); if (ret = KERN_SUCCESS) and (Iter <> 0) then begin try repeat USBRef := IOIteratorNext(Iter); if USBRef <> 0 then begin // USB device found Bsd[0] := #0; VID := 0; PID := 0; ResAsCFString := IORegistryEntryCreateCFProperty(USBRef, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0); if assigned(ResAsCFString) then begin aBsdPath := CFStringGetCStringPtr(ResAsCFString, kCFStringEncodingASCII); if assigned(aBsdPath) then sBsd := string(aBsdPath) else if CFStringGetCString(ResAsCFString, @Bsd[0], sizeof(Bsd), kCFStringEncodingASCII) then sBsd := string(Bsd) else sBsd := ''; // Invalid device path end; ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, kIOServicePlane, CFSTR(kUSBVendorID), kCFAllocatorDefault, kIORegistryIterateRecursively + kIORegistryIterateParents); if assigned(ResAsCFString) then if not CFNumberGetValue(ResAsCFString, kCFNumberIntType, @VID) then VID := 0; ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, kIOServicePlane, CFSTR(kUSBProductID), kCFAllocatorDefault, kIORegistryIterateRecursively + kIORegistryIterateParents); if assigned(ResAsCFString) then if not CFNumberGetValue(ResAsCFString, kCFNumberIntType, @PID) then PID := 0; Log.d(name + ': USBDevice "' + sBsd + '" VID/PID: ' + IntToHex(VID) + '/' + IntToHex(PID)); end; until USBRef = 0; finally IOObjectRelease(Iter); end; end; I have implemented the above function also with C in XCode and can run this code without any troubles. At exception (EAccessViolation: Access violation at address 00007FFF3A929716, accessing adress 000000000000000000) I see the following call stack in the Delphi IDE: *System._DbgExcNotify(int, void*, System.SmallString<(unsigned char)255>*, void*, void*)(0,0x00000001039035e0,0x00000001012fa22e,0x00007fff3a929716,0x0000000000000000) System.NotifyReRaise(System.TObject*, void*)(0x00000001039035e0,0x00007fff3a929716) System._RaiseAtExcept(System.TObject*, void*)(0x00000001039035e0,0x00007fff3a929716) System.Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt)(140734176073494,0,11) :000000010003CDE0 System::Internal::Excutils::GetExceptionObject(NativeUInt, NativeUInt, unsigned long) :00007FFF3D27B2A0 IORegistryEntrySearchCFProperty Serialinterface.TSerialInterface.SearchComPortForUSB(System.UnicodeString, unsigned int, unsigned int)(0x000000020978e5e0,'USBser',2283,65287)* For deeper analyze, I have added here the generated assembler code of a small test procedure that calls IORegistryEntrySearchCFProperty. Object Pascal in Unit3.pas: procedure Test var USBRef: io_service_t; key: CFStringRef; allocator: CFAllocatorRef; ResAsCFString: CFTypeRef; begin USBRef := 0; key := CFSTR(kUSBVendorID); allocator := kCFAllocatorDefault; ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, kIOServicePlane, key, allocator, 0); end; The Delphi debugger CPU view shows the disassembled x64 code: Unit3.pas.38: USBRef := 0; 000000010079CC43 C745FC00000000 mov dword ptr [rbp - 0x4], 0x0 Unit3.pas.39: key := CFSTR(kUSBVendorID); 000000010079CC4A 488D355B881000 lea rsi, [rip + 0x10885b]; __unnamed_1 + 12 000000010079CC51 488D7DD8 lea rdi, [rbp - 0x28] 000000010079CC55 E8E69987FF call 0x100016640; System.UTF8Encode(System.UnicodeString) at System.pas:39603 000000010079CC5A EB00 jmp 0x10079cc5c; <+44> at Unit3.pas:39 000000010079CC5C 488B7DD8 mov rdi, qword ptr [rbp - 0x28] 000000010079CC60 E85B9B87FF call 0x1000167c0; System._LStrToPChar(System.AnsiStringT<(unsigned short)0>) at System.pas:28783 000000010079CC65 48898538FFFFFF mov qword ptr [rbp - 0xc8], rax 000000010079CC6C EB00 jmp 0x10079cc6e; <+62> at Unit3.pas:39 000000010079CC6E 488BBD38FFFFFF mov rdi, qword ptr [rbp - 0xc8] 000000010079CC75 E8767789FF call 0x1000343f0; Macapi::Corefoundation::__CFStringMakeConstantString(char*) 000000010079CC7A 48898530FFFFFF mov qword ptr [rbp - 0xd0], rax 000000010079CC81 EB00 jmp 0x10079cc83; <+83> at Unit3.pas:39 000000010079CC83 488B8530FFFFFF mov rax, qword ptr [rbp - 0xd0] 000000010079CC8A 488945F0 mov qword ptr [rbp - 0x10], rax Unit3.pas.40: allocator := kCFAllocatorDefault; 000000010079CC8E E8AD7A89FF call 0x100034740; Macapi.Corefoundation.kCFAllocatorDefault() at CFBaseImpl.inc:65 000000010079CC93 48898528FFFFFF mov qword ptr [rbp - 0xd8], rax 000000010079CC9A EB00 jmp 0x10079cc9c; <+108> at Unit3.pas:40 000000010079CC9C 488B8528FFFFFF mov rax, qword ptr [rbp - 0xd8] 000000010079CCA3 488945E8 mov qword ptr [rbp - 0x18], rax Unit3.pas.41: ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, 000000010079CCA7 8B7DFC mov edi, dword ptr [rbp - 0x4] 000000010079CCAA 0F28057F881000 movaps xmm0, xmmword ptr [rip + 0x10887f]; __unnamed_2 + 112 000000010079CCB1 0F2945C0 movaps xmmword ptr [rbp - 0x40], xmm0 000000010079CCB5 0F280564881000 movaps xmm0, xmmword ptr [rip + 0x108864]; __unnamed_2 + 96 000000010079CCBC 0F2945B0 movaps xmmword ptr [rbp - 0x50], xmm0 000000010079CCC0 0F280549881000 movaps xmm0, xmmword ptr [rip + 0x108849]; __unnamed_2 + 80 000000010079CCC7 0F2945A0 movaps xmmword ptr [rbp - 0x60], xmm0 000000010079CCCB 0F28052E881000 movaps xmm0, xmmword ptr [rip + 0x10882e]; __unnamed_2 + 64 000000010079CCD2 0F294590 movaps xmmword ptr [rbp - 0x70], xmm0 000000010079CCD6 0F280513881000 movaps xmm0, xmmword ptr [rip + 0x108813]; __unnamed_2 + 48 000000010079CCDD 0F294580 movaps xmmword ptr [rbp - 0x80], xmm0 000000010079CCE1 0F2805F8871000 movaps xmm0, xmmword ptr [rip + 0x1087f8]; __unnamed_2 + 32 000000010079CCE8 0F298570FFFFFF movaps xmmword ptr [rbp - 0x90], xmm0 000000010079CCEF 0F2805DA871000 movaps xmm0, xmmword ptr [rip + 0x1087da]; __unnamed_2 + 16 000000010079CCF6 0F298560FFFFFF movaps xmmword ptr [rbp - 0xa0], xmm0 000000010079CCFD 0F2805BC871000 movaps xmm0, xmmword ptr [rip + 0x1087bc]; __unnamed_2 000000010079CD04 0F298550FFFFFF movaps xmmword ptr [rbp - 0xb0], xmm0 000000010079CD0B 488B75F0 mov rsi, qword ptr [rbp - 0x10] 000000010079CD0F 488B55E8 mov rdx, qword ptr [rbp - 0x18] 000000010079CD13 4889E1 mov rcx, rsp 000000010079CD16 0F2845C0 movaps xmm0, xmmword ptr [rbp - 0x40] 000000010079CD1A 0F114170 movups xmmword ptr [rcx + 0x70], xmm0 000000010079CD1E 0F2845B0 movaps xmm0, xmmword ptr [rbp - 0x50] 000000010079CD22 0F114160 movups xmmword ptr [rcx + 0x60], xmm0 000000010079CD26 0F2845A0 movaps xmm0, xmmword ptr [rbp - 0x60] 000000010079CD2A 0F114150 movups xmmword ptr [rcx + 0x50], xmm0 000000010079CD2E 0F284590 movaps xmm0, xmmword ptr [rbp - 0x70] 000000010079CD32 0F114140 movups xmmword ptr [rcx + 0x40], xmm0 000000010079CD36 0F288550FFFFFF movaps xmm0, xmmword ptr [rbp - 0xb0] 000000010079CD3D 0F288D60FFFFFF movaps xmm1, xmmword ptr [rbp - 0xa0] 000000010079CD44 0F289570FFFFFF movaps xmm2, xmmword ptr [rbp - 0x90] 000000010079CD4B 0F285D80 movaps xmm3, xmmword ptr [rbp - 0x80] 000000010079CD4F 0F115930 movups xmmword ptr [rcx + 0x30], xmm3 000000010079CD53 0F115120 movups xmmword ptr [rcx + 0x20], xmm2 000000010079CD57 0F114910 movups xmmword ptr [rcx + 0x10], xmm1 000000010079CD5B 0F1101 movups xmmword ptr [rcx], xmm0 000000010079CD5E 31C9 xor ecx, ecx > Register content here > RBP: 00007FFEEFBFEA80 > RSP: 00007FFEEFBFEA00 > Memory content here > 00007FFEEFBFEA00 49 4F 53 65 72 76 69 63 IOServic > 00007FFEEFBFEA08 65 00 00 00 00 00 00 00 e....... 000000010079CD60 E82BFEFFFF call 0x10079cb90; Macapi::Iokit2::IORegistryEntrySearchCFProperty(unsigned int, System::StaticArray<char, 128>, __CFString*, __CFAllocator*, unsigned int) > Access violation at address 00007FFF2ADD716, accessing address 0 000000010079CD65 48898520FFFFFF mov qword ptr [rbp - 0xe0], rax 000000010079CD6C EB00 jmp 0x10079cd6e; <+318> at Unit3.pas:41 000000010079CD6E 488B8520FFFFFF mov rax, qword ptr [rbp - 0xe0] 000000010079CD75 488945E0 mov qword ptr [rbp - 0x20], rax 000000010079CD79 EB37 jmp 0x10079cdb2; <+386> at Unit3.pas:41 000000010079CD7B 89D1 mov ecx, edx 000000010079CD7D 48898540FFFFFF mov qword ptr [rbp - 0xc0], rax 000000010079CD84 898D48FFFFFF mov dword ptr [rbp - 0xb8], ecx 000000010079CD8A 488D7DD8 lea rdi, [rbp - 0x28] 000000010079CD8E E81D9F87FF call 0x100016cb0; System._LStrClr(void*) at System.pas:25402 000000010079CD93 8B8D48FFFFFF mov ecx, dword ptr [rbp - 0xb8] 000000010079CD99 488BBD40FFFFFF mov rdi, qword ptr [rbp - 0xc0] 000000010079CDA0 48898518FFFFFF mov qword ptr [rbp - 0xe8], rax 000000010079CDA7 898D14FFFFFF mov dword ptr [rbp - 0xec], ecx 000000010079CDAD E8863B0100 call 0x1007b0938; symbol stub for: _Unwind_Resume 000000010079CDB2 488D45D8 lea rax, [rbp - 0x28] Unit3.pas.47: end; 000000010079CDB6 4889C7 mov rdi, rax 000000010079CDB9 E8F29E87FF call 0x100016cb0; System._LStrClr(void*) at System.pas:25402 000000010079CDBE 48898508FFFFFF mov qword ptr [rbp - 0xf8], rax 000000010079CDC5 4881C480010000 add rsp, 0x180 000000010079CDCC 5D pop rbp 000000010079CDCD C3 ret Do I have shown all concerned registers? (Unfortunately, I'm too far away from understanding the details of this x64 code). Compared to the following C code written in XCode: void Test(void) { io_service_t usbRef = 0; CFStringRef key = CFSTR("idVendor"); CFAllocatorRef allocator = kCFAllocatorDefault; CFTypeRef cf_vendor; cf_vendor = IORegistryEntrySearchCFProperty(usbRef, kIOServicePlane, key, allocator, 0); } Generates this x64 assembly code: 0x100001c40 <+0>: pushq %rbp 0x100001c41 <+1>: movq %rsp, %rbp 0x100001c44 <+4>: subq $0x20, %rsp 0x100001c48 <+8>: xorl %r8d, %r8d 0x100001c4b <+11>: movq 0x3c6(%rip), %rax ; (void *)0x00007fff2fc755f0: kCFAllocatorDefault 0x100001c52 <+18>: leaq 0x4f7(%rip), %rcx ; @"idVendor" 0x100001c59 <+25>: movl $0x0, -0x4(%rbp) 0x100001c60 <+32>: movq %rcx, -0x10(%rbp) 0x100001c64 <+36>: movq (%rax), %rax 0x100001c67 <+39>: movq %rax, -0x18(%rbp) -> 0x100001c6b <+43>: movl -0x4(%rbp), %edi 0x100001c6e <+46>: movq -0x10(%rbp), %rdx 0x100001c72 <+50>: movq -0x18(%rbp), %rcx 0x100001c76 <+54>: leaq 0x263(%rip), %rsi ; "IOService" 0x100001c7d <+61>: callq 0x100001d12 ; symbol stub for: IORegistryEntrySearchCFProperty 0x100001c82 <+66>: movq %rax, -0x20(%rbp) 0x100001c86 <+70>: addq $0x20, %rsp 0x100001c8a <+74>: popq %rbp 0x100001c8b <+75>: retq Compared to the x86 code generated by Delphi 32bit compiler of the pascal test procedure which works as expected: Unit3.pas.38: USBRef := 0; 004BB6E1 33C0 xor eax,eax 004BB6E3 8945FC mov [ebp-$04],eax Unit3.pas.39: key := CFSTR(kUSBVendorID); 004BB6E6 6810000000 push $00000010 004BB6EB 55 push ebp 004BB6EC 68EDFEEFBE push $beeffeed 004BB6F1 83C4F4 add esp,-$0c 004BB6F4 83C4FC add esp,-$04 004BB6F7 8D55E8 lea edx,[ebp-$18] 004BB6FA 8D83A0B74B00 lea eax,[ebx+Test + $DC] 004BB700 E8276EB6FF call UTF8Encode 004BB705 83C404 add esp,$04 004BB708 8B45E8 mov eax,[ebp-$18] 004BB70B 83C4FC add esp,-$04 004BB70E E85904B6FF call @LStrToPChar 004BB713 83C404 add esp,$04 004BB716 50 push eax 004BB717 E8A0AD4400 call $009064bc 004BB71C 83C41C add esp,$1c 004BB71F FE4424F4 inc byte ptr [esp-$0c] 004BB723 8945EC mov [ebp-$14],eax 004BB726 8B45EC mov eax,[ebp-$14] 004BB729 8945F8 mov [ebp-$08],eax Unit3.pas.40: allocator := kCFAllocatorDefault; 004BB72C 83C4F4 add esp,-$0c 004BB72F E8602EB7FF call kCFAllocatorDefault 004BB734 83C40C add esp,$0c 004BB737 8945F4 mov [ebp-$0c],eax Unit3.pas.41: ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, 004BB73A 6820000000 push $00000020 004BB73F 55 push ebp 004BB740 68EDFEEFBE push $beeffeed 004BB745 83C4F4 add esp,-$0c 004BB748 6A00 push $00 004BB74A 8B45F4 mov eax,[ebp-$0c] 004BB74D 50 push eax 004BB74E 8B45F8 mov eax,[ebp-$08] 004BB751 50 push eax 004BB752 8D83B4B74B00 lea eax,[ebx+Test + $F0] > Register content here > EAX: 004BB7B4 >Memory content here: > 004BB7B4 49 4F 53 65 72 76 69 63 IOServic > 004BB7BC 65 00 00 00 00 00 00 00 e....... 004BB758 50 push eax 004BB759 8B45FC mov eax,[ebp-$04] 004BB75C 50 push eax 004BB75D E8BEA84400 call $00906020 004BB762 83C42C add esp,$2c 004BB765 FE4424F4 inc byte ptr [esp-$0c] 004BB769 8945F0 mov [ebp-$10],eax Unit3.pas.47: end; 004BB76C 688FB74B00 push $004bb78f 004BB771 011C24 add [esp],ebx 004BB774 8D45E8 lea eax,[ebp-$18] 004BB777 83C4F8 add esp,-$08 004BB77A E86DF7B5FF call @LStrClr 004BB77F 83C408 add esp,$08 004BB782 C3 ret Maybe someone can give me a tip, what I have to pay attention to here.
Read More

Delphi Ensuring Left/alLeft or Top/alTop controls are positioned in the right order…

The post [WayBack] Why is my buttons not created in logical order? If I run this, my buttons area created ACB rather than ABC as I expected… – Johan Swart – Google+ reminded me the trouble of Delphi VCL and FMX have with alignment. Basically you have to position your control away from your intended alignment position in order for it to work. So this fails: procedure TForm1.FormCreate(Sender: TObject); var myToolBar: TToolBar; myCornerButton: TCornerButton; i: Integer; begin myToolBar := TToolbar.Create(Self); myToolBar.Parent := Self; for i := 0 to 2 do begin myCornerButton := TCornerButton.Create(tbarGrid); myCornerButton.Parent := myToolBar; myCornerButton.Align := TAlignLayout.Left; myCornerButton.Text := Chr(65 + I); end; end; Basically you have to set myCornerButton.Left to 1 before setting the Align property. Similar for the Top property and TAlignLayout.Top value. The same holds for VCL Align values alLeft with setting the Left property and alTop with setting the Top property before setting Align. See these for the actual properties and types: FMX: FMX.Types.TAlignLayout FMX.Controls.TControl.Align FMX.Controls.TControl.Left FMX.Controls.TControl.Top VCL: Vcl.Controls.TAlign Vcl.Controls.TControl.Align Vcl.Controls.TControl.Left Vcl.Controls.TControl.Top See also this question: [WayBack] Delphi: How to programmatically adjust visual ordering of components with align = alTop –jeroen
Read More

How to draw a border on a FireMonkey TListView object

If you drop a FMX.TStringGrid onto a new FireMonkey form, the grid gets shown with a thin border. If you drop a FMX.TTListView onto the form, there is no border. Neither component seems to have a property for enabling/disabling the border, or setting the border colour or width. I assume this is due to the cross-platform requirement, so how should it be done? Do I need to add a panel, then put the listview inside the panel? Or is it something to do with the style, as in needing a TStyleBook?
Read More

Delphi built-in data types and their memory sizes

Though 64-bit support was released back in 2011 with Delphi XE2, sometimes I forget which data type are native size and which keep their size no matter the compiler bitness (wiktionary/wikipedia). This post was motivated by via [WayBack] Having started with Delphi before the Cardinal type was available (Or has it always? I can’t remember.) I routinely declare 32 bit unsigned variables as… – Thomas Mueller (dummzeuch) – Google+ The most simple distinction is between Win32 and Win64, but there are more non-32 bit platforms, so these do not suffice any more: [WayBack] 64-bit Windows Data Types Compared to 32-bit Windows Data Types – RAD Studio 10.2 Tokyo [WayBack] 64-bit Windows Data Types Compared to 32-bit Windows Data Types – RAD Studio XE3 (yes, that did not get documented in XE2) The easiest for me are the below tables that only got introduced with Delphi 10.2 Tokyo: [WayBack] Delphi Data Types for API Integration – RAD Studio. I have bolded the ones that change size. Integer Data Types Type Description Pointer Byte 8-bit unsigned integer PByte ShortInt 8-bit signed integer PShortInt Word 16-bit unsigned integer PWord SmallInt 16-bit signed integer PSmallInt Cardinal 32-bit unsigned integer PCardinal LongWord 32-bit unsigned integer (32-bit Windows, OSX32, 32-bit iOS, and Android platforms) 64-bit unsigned integer (64-bit iOS and 64-bit Linux platforms) PLongWord FixedUInt 32-bit unsigned integer PFixedUInt Integer 32-bit signed integer PInteger LongInt 32-bit signed integer (32-bit Windows, OSX32, 32-bit iOS, and Android platforms) 64-bit signed integer (64-bit iOS and 64-bit Linux platforms) PLongint FixedInt 32-bit signed integer PFixedInt UInt64 64-bit unsigned integer PUInt64 Int64 64-bit signed integer PInt64 NativeUInt 64-bit or 32-bit platform-dependent unsigned integer PNativeUInt NativeInt 64-bit or 32-bit platform-dependent signed integer PNativeInt Floating-point Data Types Type Description Pointer Record Single Single precision floating-point value (4 bytes) PSingle TSingleRec Double Double precision floating-point value (8 bytes) PDouble TDoubleRec Extended Extended precision floating-point value (10 bytes on Win32, but 8 bytes on Win64) See page about multi-device applications. PExtended TExtended80Rec Real Alias of Double N/A N/A Earlier on, the Delphi XE2 documentation added a section describing the platform bitness effects in [WayBack] Simple Types (Delphi) – RAD Studio XE2 Delphi XE8 documentation added more information for 64-bit iOS in [WayBack] Simple Types (Delphi) – RAD Studio XE8 Delphi 10.2 Tokyo documentation added more information on other 64-bit POSIX platform in [WayBack] Simple Types (Delphi) – RAD Studio 10.2 Tokyo Platform-dependent integer types Type Platform Range Format Alias NativeInt 32-bit platforms -2147483648..2147483647 (-231..2^31-1) Signed 32-bit Integer 64-bit platforms -9223372036854775808..9223372036854775807 (-263..263-1) Signed 64-bit Int64 NativeUInt 32-bit platforms 0..4294967295 (0..232-1) Unsigned 32-bit Cardinal 64-bit platforms 0..18446744073709551615 (0..264-1) Unsigned 64-bit UInt64 LongInt 32-bit platforms and 64-bit Windows platforms -2147483648..2147483647 (-231..231-1) Signed 32-bit Integer 64-bit POSIX platforms include iOS and Linux -9223372036854775808..9223372036854775807 (-263..263-1) Signed 64-bit Int64 LongWord 32-bit platforms and 64-bit Windows platforms 0..4294967295 (0..232-1) Unsigned 32-bit Cardinal 64-bit POSIX platforms include iOS and Linux 0..18446744073709551615 (0..264-1) Unsigned 64-bit UInt64 Note: 32-bit platforms include 32-bit Windows, 32-bit macOS, 32-bit iOS, iOS Simulator and Android. Platform-Independent Integer Types Platform-independent integer types always have the same size, regardless of what platform you use. Platform-independent integer types include ShortInt, SmallInt, LongInt, Integer, Int64, Byte, Word, LongWord, Cardinal, and UInt64. Platform-independent integer types Type Range Format Alias ShortInt -128..127 Signed 8-bit Int8 SmallInt -32768..32767 Signed 16-bit Int16 FixedInt -2147483648..2147483647 Signed 32-bit Int32 Integer -2147483648..2147483647 Signed 32-bit Int32 Int64 -9223372036854775808..9223372036854775807 (-263..263-1) Signed 64-bit Byte 0..255 Unsigned 8-bit UInt8 Word 0..65535 Unsigned 16-bit UInt16 FixedUInt 0..4294967295 Unsigned 32-bit UInt32 Cardinal 0..4294967295 Unsigned 32-bit UInt32 UInt64 0..18446744073709551615 (0..264-1) Unsigned 64-bit Thomas Mueller blogged about the Alias at [WayBack] Delphi LongWord is not always a 32 bit unsigned integer – twm’s blog (via[WayBack] Did you known that LongWord in Delphi is not (any longer) always a 32 bit unsigned integer? – Thomas Mueller (dummzeuch) – Google+) and I think he understood it backwards from what Embarcadero means: NativeInt on 32-bit platforms is an alias of Integer (so it is Signed 32-bit) NativeInt on 64-bit platforms is an alias of Int64 (so it is Signed 64-bit) Some more fun links For a lazy afternoon: History [WayBack] Delphi 2007: Simple Types [WayBack] Delphi 2009: Simple Types [WayBack] compiler construction – Why is creating a 64bit Delphi so hard? – Stack Overflow [WayBack] Getting Ready for Delphi 64 [WayBack] The Oracle at Delphi: 64bit [WayBack] The Oracle at Delphi: More x64 assembler fun-facts–new assembler directives [WayBack] The Oracle at Delphi: x64 assembler fun-facts [WayBack] The Oracle at Delphi: Delphi check-in log entries of the day: [WayBack] The Oracle at Delphi: Divided and Confused [WayBack] The Oracle at Delphi: It’s my stack frame, I don’t care about your stack frame! [WayBack] The Oracle at Delphi: Delphi-Treff interview–In English –jeroen
Read More

Delphi cross-platform system utilities for system file functions [on hold]

I am migrating a Delphi 10.3 VCL application to Firemonkey. The units that do not use the GUI compile without any modification except for those which use the Windows-specific system functions mentioned below. Can anyone point me to cross-platform system file utilities in Delphi/Firemonkey 10.3, or alternative workarounds, to carry out the following actions needed to complete my project: Extract the system icon for a file or application on the basis of its extension or MIME type Execute a system shell command, e.g. to open a file (equivalent to WinAPI ShellExecute) Launch an external program in a child process and wait for its termination (e.g. create a child process using WinAPI CreateProcess and wait using WaitForSingleObject) Get/set a file’s TimeCreated, TimeModified, & TimeAccessed timestamps so that a file copy may be made having the same timestamps as the source file. I have Googled for these but the hits I have seen only refer to Windows functions. Some hits indicate that Free Pascal provides a TProcess class and ExecuteProcess(), RunCommand(), and OpenDocument() procedures that are described as being cross-platform. Regarding the timestamps, it is possible to obtain these using the FindFirst and FindNext functions and then reading timestamps in the TSearchRec returned. But I didn't find how to set the timestamps in the FMX version, which I did in the VCL version using relevant Win API functions. I am not asking for opinions or recommendations about the best out of a number of possible options, but for a factual answer to a specific question about Delphi 10.3's cross-platform support for basic system functions that one would expect to find in any mature GUI OS, such as Windows and Unix-based OS's. I searched for the an answer in the Delphi help system and on Google without success before posting the question on Stackoverflow. The first answer in this thread does just that. That I appreciate.
Read More

Canvas.FillText not working in TGrid.OnDrawColumnCell event handler

I am having difficulty understanding what is going on in a FireMonkey owner-drawn grid I am trying to develop in Delphi 10.3. I have set the Grid1.DefaultDrawing property to False and assigned the following event handler to Grid1.OnColumnCellDraw: procedure TFormFolderCptPairArray.Grid1DrawColumnCell1(Sender: TObject; const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF; const Row: Integer; const Value: TValue; const State: TGridDrawStates); var Grid: TGrid; ColIndex, RowIndex: integer; CellStr: string; CellStringSize: TSizeF; CellStrPosn: TPointF; CellStrRect: TRectF; begin {Retrieve Grid reference:} Grid:= Sender as TGrid; {Retrieve column and row indices:} ColIndex:= Column.Index; RowIndex:= Row; {Determine text to be drawn in cell:} GetGridCellText(ColIndex, RowIndex, CellStr); {Determine cell text position and bounds:} if CellStr<>'' then begin {Calculate size of cell string:} CellStringSize.cx:= Canvas.TextWidth(CellStr); CellStringSize.cy:= Canvas.TextHeight(CellStr); {Calculate posn of cell string:} if ColIndex=0 then begin {Align to centre} CellStrPosn.x:= (Bounds.Left + Bounds.Right - CellStringSize.cx) / 2; end else case (ColIndex-1) mod CFolderFieldCount of 0: CellStrPosn.x:= Bounds.Left + CCellMargin; {Align to left} 1..4: CellStrPosn.x:= (Bounds.Left + Bounds.Right - CellStringSize.cx) / 2 ; {Align to centre} 5: CellStrPosn.x:= Bounds.Right - CCellMargin - CellStringSize.cx; {Align to right} end; CellStrPosn.y:= (Bounds.Top + Bounds.Bottom - CellStringSize.cy) / 2; {Draw cell text:} {Calculate cell strings bounding rect:} CellStrRect.Left:= CellStrPosn.x; CellStrRect.Top:= CellStrPosn.y; CellStrRect.Right:= Bounds.Right - CCellMargin; CellStrRect.Bottom:= CellStrRect.Top + CellStringSize.cy; Canvas.FillText(CellStrRect, CellStr, True, 1.0, [], TTextAlign.Leading); end; end; On my first attempt, I hadn't explicitly set the Grid1.DefaultDrawing property, so it was True by default. However I assigned the event handler. At some stage, I obtained some text being rendered in the grid cells, but it was very faint and in the wrong color. It looked as if the control had been painted with some semi-transparent background color after the text had been rendered, thereby changing the text color from the specified font color of black to pink. This only happened if I removed the OnGetCell value event handler. When this handler was assigned to the grid, text was rendered automatically by the control, but not as I wanted it to appear, which was the reason why I want to override the automatic cell drawing with the custom OnDrawColumnCell event handler. In my latest attempt, I set Grid1.DefaultDrawing set to False. I am finding that more or less the same code is producing no visible text whatsoever. However, when a cell is clicked, the correct text briefly appears in washed out colors, if an OnGetValue event handler has been assigned to the grid. Can anyone suggest what might be preventing the text from being rendered by the OnDrawColumnCell event handler?
Read More

Firemonkey TCameraComponent settings restoring problem

I've problem with TCameraComponent (Delphi Rio 10.3.1), similar to this one: Firemonkey TCameraComponent quality change when reactivated but neither accepted answer nor comments suggestion work for me. procedure TForm1.CameraOn; begin Camera := TCameraComponent.Create(Self); Camera.Quality := TVideoCaptureQuality.LowQuality; Camera.OnSampleBufferReady := CameraSampleBufferReady; Camera.Active := True; end; procedure TForm1.CameraOff; begin Camera.Active := False; Camera.OnSampleBufferReady := nil; //Self.RemoveComponent(Camera); //FreeAndNil(Camera); Camera.DisposeOf; Camera := nil; end; Setting quality to Low works only once. Then destroying and recreating TCameraComponent always restores quality settings to default (high). I'm quite aware of ARC issues with destroying objects, but none of methods I know work.
Read More

UWP App flickers, if installed via Microsoft Store, but not, if installed in program folder

I transformed a 64bit-program, created with Delphi XE6 - FireMonkey, manually to the UWP and sent it to the Microsoft Store. When it was published, some users informed me, that all buttons in the app are flickering. I sent them the original 64bit-program and this was working fine on their machine. On my computer both app and program are working fine. I noticed that the button of the callout-element on my machine looks different in app and program. In the app it has two checkmarks, in the program there is only one checkmark. What can I do, to solve this problem? This is my appxmanifest.xml: <?xml version="1.0" encoding="utf-8"?> <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"> <Identity Name="..." Version="5.1.0.0" ProcessorArchitecture = "x64" Publisher="..."/> <Properties> <DisplayName>...</DisplayName> <PublisherDisplayName>...</PublisherDisplayName> <Logo>images\small_icon.png</Logo> </Properties> <Resources> <Resource Language="de" /> </Resources> <Dependencies> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.0.0" MaxVersionTested="10.0.17134.765" /> </Dependencies> <Capabilities> <rescap:Capability Name="runFullTrust"/> </Capabilities> <Applications> <Application Id="..." Executable="....exe" EntryPoint="Windows.FullTrustApplication"> <uap:VisualElements DisplayName=".." Description="...." Square150x150Logo="images\icon.png" Square44x44Logo="images\small_icon.png" BackgroundColor="#464646" /> <Extensions> <uap:Extension Category="windows.fileTypeAssociation"> <uap:FileTypeAssociation Name="..."> <uap:Logo>images\small_icon.png</uap:Logo> <uap:SupportedFileTypes> <uap:FileType>....</uap:FileType> <uap:FileType>....</uap:FileType> <uap:FileType>....</uap:FileType> </uap:SupportedFileTypes> </uap:FileTypeAssociation> </uap:Extension> </Extensions> </Application> </Applications> </Package>
Read More

runtime allocation of array (C++, FMX)

i need an array at runtime to hold some x-y coordinate data. It may be anywhere from a few dozen points to several thousands. So, to be efficient i'd like to allocate the array at runtime. I found an example but i can't extend it. Here is what i have now: double *A; A = new double[NumSamp]; // NumSamp is an int set in earlier code at runtime for (int y = 1; y < NumSamp ; y++) { A[y] = y; } delete [] A; A = NULL; This code works fine, but when i try to change to two dimensions i get E2034 Cannot convert double( *)[2] to double*. Here is the line i changed that caused the error: A = new double[NumSamp][2]; How should i be doing this? I'm working in C++Builder (10.3.1) and will target Win32, iOS, and Android.
Read More

Communication between Android APP and Windows Desktop Application [on hold]

My project contains two application, a windows desktop based one developped with Delphi, and second one an Android APP. Win Desktop app is the central management software for managing business activities, and the android APP is a tool to collect data when i am outside office with my phone and once back to office sync with Windows Desktop app and transfer collected data for treatment on my PC. The Windows Desktop app is already developed under Delphi, i prefer develop the Android app with Android studio for better design and functionnalities. My question is, once the android app developped is there a way to make it communicate with the Windows Desktop app via TCP, Bluetooth or USB to sync data. Please notice that the sync will occurs once a day when getting back to office after collecting data with y phone
Read More

Error in FMX.Treeview function TTreeViewContent.GetLastVisibleObjectIndex

I am migrating a VCL application to Firemonkey. It features a couple of TTreeview controls which display folder trees. In the main form's OnCreate event handler the paths of the folders are read from a .Ini file and the treeviews are set up. At some point before the main form appears on screen, an exception occurs in the FMX.TreeView TTreeViewContent.GetLastVisibleObjectIndex function, which is: function TTreeViewContent.GetLastVisibleObjectIndex: Integer; var Item: TTreeViewItem; begin if (FTreeView.FGlobalList.Count > 0) and (FTreeView.FLastVisibleItem < FTreeView.FGlobalList.Count) then begin Item := FTreeView.FGlobalList[FTreeView.FLastVisibleItem]; {etc.} end else Result := ControlsCount; end; I have inspected the values of the variables and found that FTreeView.FGlobalList.Count =1 and FTreeView.FLastVisibleItem = -1. The error occurs in the statement Item := FTreeView.FGlobalList[FTreeView.FLastVisibleItem]; since the array index is invalid. This code seems to be related to determining which treeview items are visible within the scrolling window of the treeview control. Since the error occurs before the form has been displayed, I tried making the treeview invisible during the update of the treview, as in the following code: procedure TFormMain.UpdateTreeview(var Folder: TFolder; Treeview: TTreeview); begin if Folder= FInputFolder then begin if not FTreeviewInputFolderValid then begin Treeview.Visible:= False; Treeview.BeginUpdate; FolderToTreeView(Folder, Treeview); //Treeview.InvalidateRect(Treeview.ContentRect); Treeview.ExpandAll; Treeview.EndUpdate; Treeview.Visible:= True; FTreeviewInputFolderValid:= True; end; end; {Ditto for FOutputFolder} end; If the program is run without setting up the treeview controls before the form is shown, i.e. by not reading the folder paths from a .ini file and not updating the treeview controls, then the error does not occur. Any suggestions about how to avoid what seems to be a coding error in function TTreeViewContent.GetLastVisibleObjectIndex? In answer to Tom, the code of FolderToTreeview is: procedure TFormMain.FolderToTreeview(Folder: TFolder; Treeview: TTreeview); var TreeviewOwner: TComponent; RootNode: TTreeViewItemFolderCpt; procedure AddFolderChildCpts(ParentTreeNode: TTreeViewItemFolderCpt; Folder: TFolder); var i: integer; FolderCpt: TFolderCpt; FileCpt: TFileCpt; SubFolder: TFolder; ChildTreeNode: TTreeViewItemFolderCpt; Found: Boolean; begin {Add all cpts of folder to child nodes of ParentTreeNode} for i:= 0 to Folder.CptCount-1 do begin FolderCpt:= Folder.Cpts[i]; ChildTreeNode:= TTreeViewItemFolderCpt.Create(ParentTreeNode); ParentTreeNode.AddObject(ChildTreeNode); ChildTreeNode.Parent:= ParentTreeNode; ChildTreeNode.FolderCpt:= FolderCpt; ChildTreeNode.OnPaint:= TreeViewItemPaint; if FolderCpt is TFileCpt then begin FileCpt:= FolderCpt as TFileCpt; ChildTreeNode.ImageIndex:= 1; end else if FolderCpt is TFolder then begin SubFolder:= FolderCpt as TFolder; ChildTreeNode.ImageIndex:= 0; {Recursively add subfolder:} AddFolderChildCpts(ChildTreeNode, SubFolder); end; end; end; begin if not Folder.IsSorted then Folder.Sort(True); {Delete all existing nodes in tree:} Treeview.Clear; {Create a new root node and add to tree:} RootNode:= TTreeviewItemFolderCpt.Create(Treeview); Treeview.AddObject(RootNode); RootNode.Parent:= Treeview; {Link folder object to root tree node:} RootNode.FolderCpt:= Folder; RootNode.ImageIndex:= 0; RootNode.OnPaint:= TreeViewItemPaint; {Now install child folder cpts:} AddFolderChildCpts(RootNode, Folder); end; TFolder, TFolderCpt, TFileCpt are elements of a separate class hierarchy to store in a memory tree structure the names and metadata of all files and folders under the root folder. The root object of class TFolder has a method Read(Path: string) which generates all its nodes by visiting the files and directories under the root directory using FindFirst and FindNext procedures. Folder.Read is called before FolderToTreeview is called. Because of this extra complication I don't think that you be able to run the FolderToTreeview method.
Read More

How to delete TChart (FMX, C++)

I can't figure out how to delete a TChart. This has to be simple, but I'm not seeing it. In the TListView ButtonClick code below, I delete a series from the active TChart and, if the series happens to be the last one, then I want to delete the entire TChart. TComponent *T; // find chart and delete the selected series for (int i = 0; i < (Form1->ComponentCount); i++) { T = Form1->Components[i]; if (T->ClassName() == "TChart") { int test = T->Tag; if (test == TappedChartTag) { //TappedChartTag is global if (TChart *TC = dynamic_cast<TChart *>(T)) { TC->RemoveSeries(AItem->Index); // this removes the series if (TC->SeriesCount()==0) { // if this was last series, delete chart TC->CleanupInstance(); } } } } } I can't find a way to completely get rid of the TChart. The TC->CleanupInstance(); wipes it completely (nothing visible), but the TChart is still there. I'm working in Embarcadero Rad Studio (C++ Builder 10.3 Update 1). UPDATE: I tried delete TC; in place of that TC->CleanupInstance(); and that works on Win32 but not on iOS.
Read More