Jump to content

Remy Lebeau

Members
  • Content Count

    2998
  • Joined

  • Last visited

  • Days Won

    135

Everything posted by Remy Lebeau

  1. Pointers are implicitly convertible to bool. A string literal is not itself a pointer, but it does decay into a pointer, which is then convertible. Note that NULL is not a pointer. It is an alias for a null pointer constant, either nullptr or integer literal 0 (depending on implementation), which can be assigned to any pointer.
  2. Remy Lebeau

    OpenSSL version questions...

    Indy in general (not just TIdSMTP specifically) indeed natively supports only up to OpenSSL 1.0.2, not OpenSSL 1.1.x and later. This is a LONG standing problem with no resolution in Indy itself at this time. But, there are a few 3rd party implementations available that add support for those versions, such as TaurusTLS: https://github.com/JPeterMugaas/TaurusTLS
  3. Got an interesting reply on the ticket: He meant this deprecated method instead: procedure AddStream(const AField: string; AStream: TStream; const AFileName: string = ''; const AContentType: string = ''; AHeaders: TStrings = nil); overload; deprecated 'Use AddStream with AOwnsStream parameter'; But yeah, that makes total sense now, C++'s overload resolution would indeed prefer to implicitly convert a string literal into a bool rather than a user-defined object (ie UnicodeString), and that would explain your crash if AOwnsStream were implicitly being set to 'true' and then you try to free both streams yourself. So, do the conversion explicitly and then you will hopefully see the warning: mfd->AddStream(_D("name"), send, String(_D("value")));
  4. Got a reply on my ticket: Yes
  5. What does line 1165 of processthreadsapi.h look like? I don't see ANY exception specifications in my copy of processthreadsapi.h, but I'm using 12.2 and not 12.3. It is the last line of this: ... On the closing '};' of the class? I don't see anything that would be considered "code in header" to trip up a precompiled header, unless the compiler is complaining about the static const members.
  6. I don't know why Embarcadero insists on putting the _DEPRECATED_ATTRIBUTE1 macro in between a function's name and its arguments. That just annoys me. All examples of [[deprecated]] and __attribute__(deprecated) that I have seen use it either in front or in back of the function declaration, not in the middle. Even the DocWiki documents it as belonging at the end of a declaration: https://docwiki.embarcadero.com/RADStudio/en/Deprecated That is because the _DEPRECATED_ATTRIBUTE1 (and __DEPRECATED_ATTRIBUTE3) macro ignores the message text when you are compiling with the classic compiler (at least in 12.2 - I don't have 12.3 installed yet to check this): // CLANG vs. BCC attributes #if !defined(__clang__) ... #define _DEPRECATED_ATTRIBUTE0 [[deprecated]] #define _DEPRECATED_ATTRIBUTE1(msg) [[deprecated]] // Ignore message as bcc's implementation is capped:( #define _DEPRECATED_ATTRIBUTE2 [[deprecated]] #define _DEPRECATED_ATTRIBUTE3(msg) [[deprecated]] // Ignore message as bcc's implementation is capped:( ... #else ... #define _DEPRECATED_ATTRIBUTE0 // Could use __attribute__((deprecated)) #define _DEPRECATED_ATTRIBUTE1(msg) // Could use __attribute__((deprecated( msg ))) #define _DEPRECATED_ATTRIBUTE2 __attribute__((deprecated)) #define _DEPRECATED_ATTRIBUTE3(msg) __attribute__((deprecated( msg ))) ... #endif This behavior is clearly wrong/outdated for the classic compiler, given that you demonstrated [[deprecated("message")]] is able to display message text just fine, and that behavior is even documented on the DocWiki: https://docwiki.embarcadero.com/RADStudio/en/Deprecated I have reported the issue: RSS-3285: _DEPRECATED_ATTRIBUTE1 and _DEPRECATED_ATTRIBUTE3 ignore message text for classic compiler Given the above macro declarations, the only possibility I can think of is that your real project is not actually compiling with the classic compiler (which you can verify by looking at the build output messages).
  7. Precompiled header being compiled only 1 time? Is it perhaps 7 messages for 7 different translation units (.cpp files) that are using the same header? Each translation unit is compiled independently, so output messages are not consolidated across TUs. What does line 772 actually look like?
  8. In <System.Net.Mime .hpp>, is there a 'deprecated' attribute on the declaration of AddStream()? Also, which C++ compiler(s) are you using, exactly? The DocWiki says only the classic bcc32 compiler supports deprecated messages.
  9. Have you tried TPath.GetCameraPath() yet? Does your app have permission to access the camera files?
  10. If they all have different names/types, then yes (provided you need getters/setters at all - see dummzeuch's examples). But, if they are all related, eg Name1, Name2, etc then you can use an indexed property instead, eg: Type TEmployee = class private FNames[0..49] : string; Function GetName(Index: Integer) : string; Procedure SetName(Index: Integer; const Value : string); public Property Names[Index: Integer] : string read GetName write SetName; end; implementation {$R *.dfm} Function TEmployee.GetName(Index: Integer): string; begin Result := FNames[Index]; end; Procedure TEmployee.SetName(Index: Integer; const Value: string); begin if Value = '' then raise Exception.Create('Value must not be empty'); FNames[Index] := Value; end; Alternatively, you could do something like this: const EmployeeNameIdx := 0; EmployeeEmailIdx := 1; ... Type TEmployee = class private FValues[0..49] : string; Function GetValue(Index: Integer) : string; Procedure SetValue(Index: Integer; const Value : string); public Property Name : string read GetValue write SetValue index EmployeeNameIdx; Property Email : string read GetValue write SetValue index EmployeeEmailIdx; end; implementation {$R *.dfm} Function TEmployee.GetValue(Index: Integer): string; begin Result := FValues[Index]; end; Procedure TEmployee.SetValue(Index: Integer; const Value: string); begin if Value = '' then raise Exception.Create('Value must not be empty'); FValues[Index] := Value; end; Yes, eg: Type TEmployee = class private ... public type TDetails = record ... end; ... end;
  11. In his example, nowhere. You would need a setter for that.
  12. @alank2 What you describe implies that either 1) TMultipartFormData is trying to free an invalid FStream object, or 2) you are trying to free an invalid TMultipartFormData object. Unfortunately, there is not enough detail provided to help you. You will have to debug the code for yourself, and double check the user of the pointers involved.
  13. Remy Lebeau

    Best way of handling Exceptions

    You should be able to do that, as each Exception object in the chain is preserved as-is and would carry its own CallStack, which JCL can populate as each Exception is raised. https://blog.eurekalog.com/2010/05/new-exception-class-in-delphi-2009-and_05.html Not really, because you are still raising twice. Whether you raise and then re-raise 1 object, or raise 2 objects, is up to you.
  14. Remy Lebeau

    Best way of handling Exceptions

    I (relunctantly) agree with ChatGPT on this one - you should not modify the original exception, but instead you should raise a new exception that captures the original exception into the new exception's InnerException property. However, the way that ChatGPT demonstrates this is wrong: Firstly, SysUtils.Exception does not have a public SetInnerException() method. ChatGPT suggests defining a new class, but then doesn't use that class. And that class is just trying to replicate a feature that already exists natively in SysUtils.Exception. Second, ChatGPT's approach does not release ownership of the original Exception, so the try..except will still try to free it when the except block exits, leaving the new Exception holding a dangling InnerException pointer to a now-dead Exception. The correct way to capture an InnerException is to use the SysUtils.Exception.RaiseOuterException() method, eg: try sqhpartyroles.sql := fsqlhandle.buildsql; sqhpartyroles.executesql; except Exception.RaiseOuterException(Exception.CreateFmt('error from sql %s', [sqhpartyroles.sql])); end; (I don't like this syntax, but it is what it is...) Higher up the call chain, you can then catch the new Exception and traverse its InnerException chain if you want to report/log all of the individual error messages, eg procedure MyForm.Application1Exception(Sender: TObject; E: Exception); begin repeat // use E as needed, then... E := E.InnerException; until E = nil; end;
  15. Remy Lebeau

    EnumFontFamiliesEx...

    Forget it...
  16. Remy Lebeau

    EnumFontFamiliesEx...

    Really? They all look the same to me... weird...
  17. Remy Lebeau

    EnumFontFamiliesEx...

    Of course the dialog may be localized based on the user's language. Most OS dialogs are. Bu that doesn't mean the OS makes those localized strings available to apps. So, you'll likely need to provide your own localized strings if you want to honor the user's language in your own UI/logging. Those are all the same values that @Kas Ob. showed you earlier, which Microsoft already documents in several places of MSDN. So you didn't need to go to that effort.
  18. Remy Lebeau

    EnumFontFamiliesEx...

    TFontDialog is just a wrapper for the Win32 ChooseFont() API, so it displays whatever the OS wants to display.
  19. Remy Lebeau

    EnumFontFamiliesEx...

    There is no Win32 API to get the same text that appears in the dialog. You have to use your own logic, using the numeric values shown by @Kas Ob. with a lookup array such as shown by @dwrbudr. The EnumFontFamiliesEx() API gives you the numeric value, you have to convert it to text yourself.
  20. Remy Lebeau

    Is this a change in 12.3??

    Don't forgot to call 'inherited Create(aOwner);'
  21. Remy Lebeau

    Is this a change in 12.3??

    Except in this case, as the properties shown are not declared as published, so not streamed by the DFM at all.
  22. Remy Lebeau

    Is this a change in 12.3??

    That won’t work as you describe. You can't add parameters to the OnCreate event. What you are proposing requires defining a new constructor instead.
  23. https://stackoverflow.com/questions/16150218/is-it-possible-to-create-a-type-alias-to-a-generic-record-in-delphi https://stackoverflow.com/questions/10060009/is-it-possible-to-create-a-type-alias-to-a-generic-class
  24. Remy Lebeau

    Some questions about password input and TDialogService

    The OP asked about Android, and modal dialogs are not supported on Android.
  25. Remy Lebeau

    Some questions about password input and TDialogService

    I can't answer your question. But an alternative approach would be to create your own dialog however you want, and then write your own class that implements the IFMXDialogServiceAsync interface to show your dialog, and then register that class with FMX using TPlatformServices.Current.AddPlatformService() (be sure to unregister the default implementation using TPlatformServices.Current.RemovePlatformService() first).
×