-
Content Count
2633 -
Joined
-
Last visited
-
Days Won
110
Everything posted by Remy Lebeau
-
Generics and Interface
Remy Lebeau replied to chkaufmann's topic in Algorithms, Data Structures and Class Design
The DocWiki is correct. Generics are not supported on interface methods. Nor does it make sense to allow that anyway. The main reasons to use interfaces are polymorphism and predictable functionality contracts. If two classes implement the same interface, but they implement the same methods using different parameter/return types, then polymorphism and contracts go out the window. There is no viable use-case where allowing Generics on interface methods makes sense. No. Why do you think you need this? You don't. Find another design. -
Android 8.0 Permissions errors using Delphi Rio 10.3
Remy Lebeau replied to Jose Morango's topic in Cross-platform
You didn't answer my question: "So, have you looked at the implementation code that is meant to run on Androidd 6.0+? Does THAT code call AOnDisplayRationale as expected?" -
The Android 64bit deadline warnings have started
Remy Lebeau replied to Yaron's topic in Cross-platform
You and I don't agree on much very often, but we can agree on this point. For instance, I'm a programmer, who happens to work primarily in C++ and Delphi, but I will reach into Java and C# and even VB and Assembly when a task requires it. I think in terms of logic and tasks, and then write specific code in the syntax of whatever language I'm working with at the time to accomplish those things. Programming is programming, differences between various languages are just a matter of syntax and libraries available. -
Grant lifetime subscription to Andreas Hausladen (IDE Fix Pack creator)
Remy Lebeau replied to santiago's topic in Delphi IDE and APIs
Andreas just released a new Fix Pack update for 10.3.2: https://www.idefixpack.de/blog/2019/07/ide-fix-pack-6-4-3-for-delphi-10-3-2/ -
[bug] : Rad Studio 10.3.2 - Custom Component works fine with Tokio but not with Rio
Remy Lebeau replied to gioma's topic in FMX
Perhaps. On the other hand, it turns out that the introduction of TFieldsCache in 10.3.2 has broken backwards compatibility with 10.3 RTM, so be careful: -
That is what I get for not checking Delphi's pascal declarations before posting code examples.
-
That would only be needed if you are using Delphi Xe or earlier. In XE2 and later, you should use "Winapi.Windows". Though, you can omit the "Winapi" prefix if you have "Winapi" included in your project's "Unit scope names" list. Because I wasn't targeting any specific Delphi version. The code I suggested should work in older versions, too. Well, XE and later anyway, since 2010 and earlier did not have a version of FindCmdLineSwitch() that returns a string value, but that is not hard to write a manual replacement for if needed. "Windows" and "Winapi.Windows" are the same unit, so you can't "use" it twice in the same unit. The latter simply has a "Unit scope name" applied to it in XE2 and later.
-
[bug] : Rad Studio 10.3.2 - Custom Component works fine with Tokio but not with Rio
Remy Lebeau replied to gioma's topic in FMX
Not specifically, someone will have to do a diff of the RTL source code between 10.3 and 10.3.2. All the release note says is "VCL DFM files loading optimization". -
Cannot login to Quality Central - who to contact?
Remy Lebeau replied to A.M. Hoornweg's topic in General Help
Just to nitpick - quality.embarcadero.com is for Quality Portal. Quality Central (qc.embarcadero.com) is dead. -
how to change the color of the top row of stringgrid.
Remy Lebeau replied to sadabat's topic in Databases
See the TStringGrid.FixedColor property. See the TStringGrid.Color property. See the TStringGrid.DefaultColWidth, TStringGrid.ColWidths, and TStringGrid.GridLineWidth properties. -
Using Continue in repeat statement
Remy Lebeau replied to Kryvich's topic in RTL and Delphi Object Pascal
As others have stated, it is working as designed. You need to change your 'until True' condition to 'until False' instead so the loop can run more than once. Personally, I would just re-write the condition to not use 'Continue' at all: program RepContinue; {$APPTYPE CONSOLE} {$R *.res} var i: Integer; begin i := 5; repeat Writeln(i); Dec(i); until i <= 0; Readln; end. -
You definitely don't want to use those kind of functions in this situation. You don't need that. A process knows its own ID, you can query it directly. You need something like this: uses ..., Windows; function RestartApp: Boolean; var si: STARTUPINFO; pi: PROCESS_INFORMATION; CmdLine: string; begin CmdLine := Format('"%s" /pid:%d', [ParamStr(0), GetCurrentProcessID()]); ZeroMemory(@si, sizeof(si)); GetStartupInfo(@si); Result := CreateProcess(nil, PChar(CmdLine), nil, nil, False, 0, nil, nil, si, pi); if Result then begin CloseHandle(pi.hThread); CloseHandle(pi.hProcess); Application.Terminate; end; end; Then in your app's startup code, such as in your main DPR file, you can do this before initializing your UI or anything else: uses ..., Windows; var pid: string; h: THandle; begin if FindCmdLineSwitch('pid', pid) then begin h := OpenProcess(SYNCHRONIZE, FALSE, StrToInt(pid)); if h <> 0 then begin WaitForSingleObject(h, INFINITE); CloseHandle(h); end; end; ... continue starting up normally ... end;
-
The fix is checked in now.
-
More accurately, it just says that the NIST ITS's usage of the TIME protocol is obsolete and NTP is preferred, not that the TIME protocol itself is obsolete. This page explains it a bit better: https://www.nist.gov/pml/time-and-frequency-division/services/internet-time-service-its Yes.
-
My bad, there are a few erroneous {$ENDIF} statements that don't belong. Try the following instead, it should work. If so, I will check in the fix: type {$IFDEF HAS_ComponentPlatformsAttribute} [ComponentPlatformsAttribute( {$IFDEF HAS_ComponentPlatformsAttribute_AllPlatforms}pidAllPlatforms {$ELSE} pidWin32 {$IFDEF HAS_ComponentPlatformsAttribute_Win64} or pidWin64{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_OSX32} or pidOSX32{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_iOS_Simulator32}or pidiOSSimulator32{$ELSE} {$IFDEF HAS_ComponentPlatformsAttribute_iOS_Simulator} or pidiOSSimulator{$ENDIF}{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_Android32Arm} or pidAndroid32Arm{$ELSE} {$IFDEF HAS_ComponentPlatformsAttribute_Android} or pidAndroid{$ENDIF}{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_Linux32} or pidLinux32{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_iOS_Device32} or pidiOSDevice32{$ELSE} {$IFDEF HAS_ComponentPlatformsAttribute_iOS_Device} or pidiOSDevice{$ENDIF}{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_Linux64} or pidLinux64{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_WinNX32} or pidWinNX32{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_WinIoT32} or pidWinIoT32{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_iOS_Device64} or pidiOSDevice64{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_WinARM32} or pidWinARM32{$ELSE} {$IFDEF HAS_ComponentPlatformsAttribute_WinARM} or pidWinARM{$ENDIF}{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_OSXNX64} or pidOSXNX64{$ELSE} {$IFDEF HAS_ComponentPlatformsAttribute_OSX64} or pidOSX64{$ENDIF}{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_Linux32Arm} or pidLinux32Arm{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_Linux64Arm} or pidLinux64Arm{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_Android64Arm} or pidAndroid64Arm{$ELSE} {$IFDEF HAS_ComponentPlatformsAttribute_Android64} or pidAndroid64{$ENDIF}{$ENDIF} {$IFDEF HAS_ComponentPlatformsAttribute_iOS_Simulator64} or pidiOSSimulator64{$ENDIF} {$ENDIF} )] {$ENDIF} TIdAntiFreeze = class(TIdAntiFreezeBase) public procedure Process; override; end;
-
It was released today: http://blog.marcocantu.com/blog/2019-august-delphi-1032.html https://community.idera.com/developer-tools/b/blog/posts/announcing-the-release-of-delphi-c-builder-and-rad-studio-10-3-2
-
Why is this code not thread safe (Delphi 7)
Remy Lebeau replied to Yaron's topic in Algorithms, Data Structures and Class Design
Actually, a manual critical section is not good enough, because behind the scenes the main UI thread will periodically reach inside any TCanvas objects that are not locked via their Lock() method. A manual critical section will not prevent that, you have to use the critical section that TCanvas.Lock() uses internally. -
Why is this code not thread safe (Delphi 7)
Remy Lebeau replied to Yaron's topic in Algorithms, Data Structures and Class Design
Yes, very sure. This is a very well-known issue with TBitmap's implementation. If your threads are not calling Canvas.Lock() on their TBitmap objects then your rendering code is not thread-safe, and you have just been lucky so far that it hasn't failed on you yet. For instance, if your main UI thread is not processing any messages while your threads are rendering, then the main thread's GDI garbage collection will not occur to trash your TBitmap resources. But that is not a guarantee you should rely on, unless you explicitly code for that situation, ie by blocking the main UI thread while your rendering threads are running, which is probably not what you want to do. Otherwise, don't use TBitmap in threads, use a different implementation that doesn't suffer from threading issues, such as TBitmap32 from http://www.graphics32.org. Or, simply don't manipulate TBitmap objects in worker threads. Prepare the pixel data as needed, and then sync with the main UI thread to transfer the data into TBitmap. -
How to know that a file is not used by another program?
Remy Lebeau replied to Juan C.Cilleruelo's topic in Cross-platform
The FileExists() check is unnecessary and should be removed. It introduces a race condition (the file may exist before FileExists() is called, and then gets deleted before CreateFile() is called) as well as a possible failure point (FileExists() is not 100% accurate in all possible situations, there are cases where it returns a wrong result). Calling CreateFile() by itself with OPEN_EXISTING is good enough. If the file really does not exist, CreateFile() will fail with an ERROR_FILE_NOT_FOUND error code. Also, your code does not take ERROR_SHARING_VIOLATION into account, which would mean the file is actually in use but you don't have access to open it. Try this instead: function IsFileInUse(FileName: TFileName): Boolean; var HFileRes: THandle; begin HFileRes := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (HFileRes <> INVALID_HANDLE_VALUE) then begin CloseHandle(HFileRes); Result := False; end else Result := (GetLastError() = ERROR_SHARING_VIOLATION); end; -
Android 8.0 Permissions errors using Delphi Rio 10.3
Remy Lebeau replied to Jose Morango's topic in Cross-platform
I don't have Rio installed to look at, but the implementations you have shown are not invoking any Android APIs to request permissions from the user. That makes me think you are looking at implementation code which is meant to run on Android versions prior to v6.0, in which case it makes sense that AOnDisplayRationale would not be called since permissions would be implicitly granted by app manifest only, which would explain why the implementation code you show is populating the GrantResults array with TPermissionStatus.Granted regardless of what is being requested, and ignoring AOnDisplayRationale. There is no simply reason to display a rationale prompt to the user in that situation. So, have you looked at the implementation code that is meant to run on Androidd 6.0+? Does THAT code call AOnDisplayRationale as expected? On a side note, application code should be calling PermissionsService.IsPermissionGranted() or PermissionsService.IsEveryPermissionGranted() before calling PermissionsService.RequestPermissions(), eg: procedure TForm6.btnStartScanClick(Sender: TObject); begin if PermissionsService.IsPermissionGranted(FLocationPermission) then StartBLEDiscovery else PermissionsService.RequestPermissions([FLocationPermission], RequestPermissionsResult, DisplayRationale); end; -
Why is this code not thread safe (Delphi 7)
Remy Lebeau replied to Yaron's topic in Algorithms, Data Structures and Class Design
In VCL, the TBitmap.Canvas must be locked while using the TBitmap in a worker thread. The RTL keeps track of all GDI resources it allocates, and the main UI thread runs a routine periodically that frees GDI resources that are not locked. Which is very bad for TBitmap used in a worker thread. The alternative is to not use TBitmap at all, just use the Win32 API directly for all GDI operations in a worker thread. -
What options do I have to control custom releases?
Remy Lebeau replied to Mike Torrettinni's topic in General Help
You could put that information in your program's Version info. Define an .rc file that builds the version details conditionally. Then use compiler conditionals to control which features are turned on/off in code, and which details are shown/hidden in the version info when the .rc file is compiled. -
Why not continue using TIdMultipartFormDataStream for that? It has an overloaded AddFormField() method that lets you specify a TStream for the input data. You could store your bytes in a TMemoryStream or TBytesStream, or use Indy's own TIdMemoryBufferStream, etc. For example: procedure SendFromBytes( const buffer: array of byte ); var Strm: TIdMemoryBufferStream; Params: TIdMultipartFormDataStream; begin ... Strm := TIdMemoryBufferStream.Create(PByte(buffer), Length(buffer)); try Params := TIdMultipartFormDataStream.Create; try Params.AddFormField('name', 'application/octet-stream', '', Strm, 'filename'); http.Post('http://x.x.x.x:8996/service', Params, responseStream); finally end; finally Strm.Free; end; ... end; Yes, whatever value is specified in the "boundary" header, in the body it needs to have a leading "--" in front of each new MIME part, and a trailing "--" at the end of the last MIME part. TIdMultipartFormDataStream handles that internally for you.
-
https://quality.embarcadero.com/browse/RSP-24834
-
Firedac and simultaneous connection to different version of Firebird
Remy Lebeau replied to Jacek Laskowski's topic in Databases
I don't know how FireDAC works internally, or how it loads fbclient.dll, but have a look at Activation Contexts, which allow a process to load multiple versions of a DLL at the same time. Create a context for one DLL and connect to Firebird while that context is active, then create another context for the other DLL and connect to Firebird again. Not sure if it will work in your situation, but it is worth a try.