Category: StackOverflow

Change folder attribute to hidden on iOS (FMX, C++)

I want to create a directory at runtime and make it hidden. Using this example i tried the following code and it works fine on Win32 but errors on iOS build: UnicodeString TestPath; TestPath = System::Ioutils::TPath::GetDocumentsPath() + "\\test\\"; TDirectory::CreateDirectory(TestPath); TFileAttributes dirattribs; dirattribs = TDirectory::GetAttributes(TestPath); dirattribs = dirattribs << TFileAttribute::faHidden; TDirectory::SetAttributes(TestPath, dirattribs); The build error i get when building for iOS or Android is no member named 'faHidden' in 'System::Ioutils::TFileAttribute'. So, how can i change folder attributes on iOS and Android? p.s. Using Rad Studio 10.3.2 (C++ Builder).
Read More

Printing Bitmap Using Bluetooth Thermal Printer With Firemonkey Android

I have this code is success for printing text with bluetooth thermal printer using android using firemonkey delphi, my friend modified for printing bitmap, but any some error access violation with procedure bitmaptostr. procedure TBluetoothPrinter.Send(Data: TArray<Byte>); begin if Data = nil then Exit; // nothing to write Check(OutputStream <> nil, 'Cannot retrieve output stream'); OutputStream.write(ToJavaByteArray(Data)); end; procedure Printing(sText: string); begin with TBluetoothPrinter.Create do begin Send(TEncoding.ANSI.GetBytes(sText + CRLF)); end; end; function BitmapToStr(BMP: TBitmap; EscapeStr:String; SliceEscapeStr:String; BitsSlice: Byte = 8):String; var BMPData: TBitmapData; AColor: TAlphaColor; nCol, nRow, nIndex: integer; nOffset, nBytePos, nBitPos: integer; nSliceIndex, nLum: integer; nSlice, nBit, nTmpBit, BytesSlice: byte; ADots: Array of boolean; sSlice: String; begin try SetLength(ADots, (BMP.Height * BMP.Width)); nIndex := 0; for nRow := 0 to BMP.Height-1 do begin for nCol := 0 to BMP.Width-1 do begin AColor := BMPData.GetPixel(nCol, nRow); nLum := Trunc((TAlphaColorRec(AColor).R * 0.3) + (TAlphaColorRec(AColor).G * 0.59) + (TAlphaColorRec(AColor).B * 0.11)); ADots[nIndex] := (nLum < 127); inc(nIndex); end; end; BytesSlice := (BitsSlice div 8); if BitsSlice mod 8 > 0 then inc(BytesSlice); Result := EscapeStr; nOffset := 0; while (nOffset < BMP.Height) do begin Result := Result + SliceEscapeStr; for nCol := 0 to BMP.Width-1 do begin for nSliceIndex := 0 to BytesSlice - 1 do begin nSlice := 0; for nBit := 0 to 7 do begin nBytePos := (((nOffset div 8) + nSliceIndex) * 8) + nBit; nBitPos := (nBytePos * BMP.Width) + nCol; nTmpBit := 0; if (nBitPos < Length(ADots)) then begin if ADots[nBitPos] then nTmpBit := 1 else nTmpBit := 0; end; nSlice := nSlice or (nTmpBit shl (7 - nBit)); end; Result := Result + Chr(nSlice); end; end; inc(nOffset, BitsSlice); Result := Result + CRLF; end; finally ADots := nil; end; end; anyone have some solution or sample reference?
Read More

How to add and remove Android notification channels in Delphi Rio10.3.2

I would like to implement multiple notification channels for Android on an FMX project. RAD 10.3.2 now provides some support for API >= 26 and a "fallback" notification channel is automatically created. Its default description is "Notification channel for Firebase" and I would like to change this description as well as to add some new channels. In RAD 10.3.2, the new Options/Application/Services parameters provide a "Default local notification channel Id" which, I suppose, is there to change the value of the fcm_fallback_notification_channel_label stored in the Strings.xml file generated when building or deploying the App. However, when I write an Id like "Infos" in this field, this has no effect on the generated Strings.xml file content. I've thus copied the Strings.xml file in another directory, edited it manually and modified the deployment in order to use this file rather than the automatic one. This is working if I uninstall the App and reinstall it with the changed channel description. The final user may now see the correct name of the channel. However, I've still got only one channel and I don't know how to add more ones. I've searched in the Android support and I see that the channels are supposed to be added via notificationManager.createNotificationChannel(channel) in the starting code of an App. However, I've found no access to these method in TPushService or TPushServiceConnection. Is there a "standard" way in Delphi for adding and removing notification channels ?
Read More

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

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 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