Jump to content

Remy Lebeau

Members
  • Content Count

    2633
  • Joined

  • Last visited

  • Days Won

    110

Everything posted by Remy Lebeau

  1. Remy Lebeau

    Generics and Interface

    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.
  2. Remy Lebeau

    Android 8.0 Permissions errors using Delphi Rio 10.3

    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?"
  3. Remy Lebeau

    The Android 64bit deadline warnings have started

    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.
  4. 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/
  5. 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:
  6. Remy Lebeau

    Restart the same App?

    That is what I get for not checking Delphi's pascal declarations before posting code examples.
  7. Remy Lebeau

    Restart the same App?

    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.
  8. 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".
  9. Remy Lebeau

    Cannot login to Quality Central - who to contact?

    Just to nitpick - quality.embarcadero.com is for Quality Portal. Quality Central (qc.embarcadero.com) is dead.
  10. Remy Lebeau

    how to change the color of the top row of stringgrid.

    See the TStringGrid.FixedColor property. See the TStringGrid.Color property. See the TStringGrid.DefaultColWidth, TStringGrid.ColWidths, and TStringGrid.GridLineWidth properties.
  11. Remy Lebeau

    Using Continue in repeat statement

    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.
  12. Remy Lebeau

    Restart the same App?

    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;
  13. Remy Lebeau

    Indy - rev.5507 compile problem

    The fix is checked in now.
  14. Remy Lebeau

    NTP which component to use?

    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.
  15. Remy Lebeau

    Indy - rev.5507 compile problem

    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;
  16. Remy Lebeau

    10.3.2 as next or waiting for 10.4?

    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
  17. 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.
  18. 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.
  19. Remy Lebeau

    How to know that a file is not used by another program?

    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;
  20. Remy Lebeau

    Android 8.0 Permissions errors using Delphi Rio 10.3

    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;
  21. 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.
  22. Remy Lebeau

    What options do I have to control custom releases?

    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.
  23. Remy Lebeau

    POSTing binary data with TIdHTTP

    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.
  24. Remy Lebeau

    Funny Code in System.Types

    https://quality.embarcadero.com/browse/RSP-24834
  25. Remy Lebeau

    Firedac and simultaneous connection to different version of Firebird

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