Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 03/13/25 in all areas

  1. ŁukaszDe

    Delphi 12.3 is available

    Links to Web installer and ISO are available in https://my.embarcadero.com
  2. Angus Robertson

    ICS for RAD Studio 12.3

    ICS V9.4 is ready for RAD Studio 12 Update 3, aka RAD Studio 12.3, and specifically the new 64-bit IDE. The ICS Delphi V9.4 design packages already have Windows 64-bit as a target, allowing them to be installed into the 64-bit IDE. The 32-bit IDE allows design packages to be built with target Windows 64-bit, but not installed. Note the 64-bit IDE does not support Windows 32-bit targets, only Windows 64-bit. If you use the IcsInstallVclFmx.groupproj Build Group, all design packages will be built for Windows 64-bit. All the main samples build OK in the 64-bit IDE, with a Windows 64-bit target being automatically added, unfortunately even when deliberately missing such as the OverbyteIcsNetMon sample that does work in Windows 64-bit. Currently, GetIt only works in read-only mode in the 64-bit IDE, so you will need to install ICS using GetIt from the 32-bit IDE, then start the 64-bit IDE and manually install the three design packages. The ICS V9.4 C++ Builder packages can be currently be installed successfully into C++ Builder 12.3 32-bit IDE for the Windows 32-bit target only. The 32-bit IDE should be able to build for Windows 64-bit and Win64x (Modern) as well, all the package paths are correct, but both targets currently give compiler errors. The C++ Windows 64-bit errors are four unresolved external, and the same error happens in Delphi 11, so should be fixable by someone with C++ knowledge. Building for Win64x (Modern) gives lots of undefined symbol errors due to RAD Studio being unable to import other packages compiled built with C++ Win64x, this error was reported six months ago for C++ 12.2 but is not fixed in 12.3. So ICS can not be used in the C++ 64-bit IDE that only supports Win64x (Modern), not Windows 64-bit. Separately, there is a new version of the DD Service Application Framework used by two of the ICS samples, adding support for 64-bit IDE Wizards. Available shortly from https://www.magsys.co.uk/delphi/ddservice.asp Angus
  3. havrlisan

    FMX learning resources?

    For starters, I recommend reading two FMX-related books: "Delphi GUI Programming with FireMonkey" by Andrea Magni, and "Fearless cross-platform development with Delphi" by David Cornelius. Together, they cover the most important parts of how FMX framework functions, and they both write about similarities and differences between VCL. I suggest you also play around and discover the RAD Studio Multi Device Samples, since they contain good chunks of code and UI components to see how to interact with FMX. If you have multiple devices with different platforms (Android, iOS, macOS), make sure you try the apps on all of them, to see how the deployment and functionality works across different platforms. As you start using FMX, I strongly recommend working with skia4delphi in every project. It is already integrated into FMX, but make sure to enable it in every project as it increases performance and provides you a ton of features that are missing in the stock FMX (such being Svg/Lottie support and right-to-left text). Good luck!
  4. Remy Lebeau

    Stdin and debugging in the IDE

    At program startup, detect the presence of the debugger (dynamically, or via a command-line parameter) and then use SetStdHandle() to replace STDIN with your own handle to a named pipe or anonymous pipe, and then write your desired debug data to that pipe. Or better, simply move your logic into a function that takes an input TStream as a parameter, and then decide whether you want to use a THandleStream for STDIN or a TStringStream or TMemoryStream for your debug data. On a side note - using a 'while (Position < Size)' loop is not a good idea. You should simply call Read() with a fixed-sized buffer, and let it tell you when it reaches the end of the stream, eg. SetLength(Buffer, SomeSize); repeat BytesRead := StdInStream.Read(Buffer, SomeSize); if BytesRead < 1 then Break; // do stuff until False;
  5. GabrielMoraru

    12.3 or 13/14 as next?

    Agree. We do need a roadmap....
  6. The best thing you can do is debug the identical procedure write in Pascal and see how the compiler acts ...
  7. vfbb

    VCL Skia *.svg display dependencies ?

    @CyberPeter Tip: When you enable Skia in your project (right-click on the project > Enable Skia), the next time you build the project, the sk4d.dll will be in the output folder along with your .exe.
  8. corneliusdavid

    FMX learning resources?

    Thank you, @havrlisan, for the plug for my book. I wrote that specifically for the Delphi programmer who already has VCL experience and wants to leverage their knowledge to expand to other platforms. I also have Andrea Magni's book and it's an excellent deep-dive into understanding and working with Firemonkey. Be aware that Linux development with Delphi requires at least the Enterprise version and does not officially support Firemonkey (yet).
  9. Patrick PREMARTIN

    VCL Skia *.svg display dependencies ?

    Skia is an open source library available under BSD Free Software License. We can use and deploy it with our projects. https://skia.org/about/ With the Skia4Delphi project I don't know if you can link it dynamically. Check with the developer team on https://github.com/skia4delphi/skia4delphi/discussions
  10. Patrick PREMARTIN

    VCL Skia *.svg display dependencies ?

    You need the Skia.dll file with projects using Skia. Check "Project / Deployment wizard" option to see where it's located on your development computer. It should be in the "bin" folder of RAD Studio installation. See https://docwiki.embarcadero.com/RADStudio/en/Skia4Delphi for other links and infos about using Skia in Delphi or C++Builder.
  11. Mmmm, I've tried a simple console program in Athens 12: program Project4; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.DateUtils, Winapi.Windows; var I: Integer; T1: Int64; T2: Int64; TD: Double; D1: TDateTime; D2: TDateTime; DiffMs: Int64; Frequency: Int64; function Delay: Integer; var I: Integer; begin Result := 0; for I := 0 to 1000000 do Inc(Result); end; begin FormatSettings.DecimalSeparator := '.'; FormatSettings.ThousandSeparator := ','; try QueryPerformanceFrequency(Frequency); D1 := Now(); QueryPerformanceCounter(T1); Delay; D2 := Now(); QueryPerformanceCounter(T2); TD := (T2 - T1) * 1000 / Frequency; DiffMs := MilliSecondsBetween(D2, D1); Writeln(Format('Now() delta = %d ms', [DiffMs])); Writeln(Format('QueryPerformance delta = %f ms', [TD])); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Result: Now() delta = 2 ms QueryPerformance delta = 2.15 ms The Delay is empirical, necessary just to have a little delay. Now() seems to capture 2ms of delta. Increasing delay of 10: Now() delta = 17 ms QueryPerformance delta = 16.42 ms I don't know why they report 1 sec of precision in the documentation, but if it can be so, is terribile, because my OPC UA server timings are based on TDateTime and 1ms of resolutions is already 10 time bigger than OPC-UA tick of 100ns.
  12. Die Holländer

    12.3 or 13/14 as next?

  13. 1. Python -- First appeared 20 February 1991; 34 years ago 2. C++ -- First appeared 1985; 40 years ago 3. Java -- First appeared May 23, 1995; 29 years ago 4. С -- First appeared 1972; 53 years ago ... 10. Delphi -- Initial release 1995 Attention! Dinosaurs have won prizes!
  14. Remy Lebeau

    Creating a Server Application using tidtcpserver

    It is generally not a good idea to share DB queries across threads, unless you Synchronize() access to them. It is better to give each thread its own DB connection (pooled if needed) and unique query components.
  15. Does not work in 10.2. I just checked three other text editor programs and MS word was the only one that supported it.
  16. I am pretty sure that this has never worked before - at least it does not in Delphi 7, Delphi XE8 or Delphi 12. So instead of filing a bug report this should probably better be a feature request. Besides that, I actually have problems using the mouse wheel while pressing the left mouse button, but that can also be caused by my age.
  17. Anders Melander

    [BUG] Mouse wheel no longer scrolls when highlighting

    It's not like I never use the mouse when coding (Ctrl+Click) but I find it much more efficient to use the keyboard as much as possible instead of switching back and forth. Selection is probably one of the things I would very rarely use the mouse for. I guess I would do word selection using Ctrl+arrow to move, Ctrl+Shift+arrow to select. etc. Place the caret using normal arrow navigation. Shift+up/down for selection, etc. It's not really something I think about but the fact that I didn't know that mouse-scroll.selection didn't work tells me that it isn't something that I have tried or something that I need. Anyway, we each have our own usage patterns. There's no right or wrong.
  18. You're right. I have the same behavior; I never noticed it before since I don't usually select code like that. That said, you should report it on the Quality Portal instead of here.
  19. I want to implement a variadic method in Delphi that behaves like Write and Writeln, where I can pass a variable number of arguments directly, without using brackets ([]) around the arguments. For example, instead of calling a method like this: MyWriteln(['Hello', 123, 45.67]); // Using array of const with brackets I want to call it like this: MyWriteln('Hello', 123, 45.67); // Without brackets, similar to Writeln I found that Delphi supports varargs for external DLL functions declared with cdecl, like this: procedure Test(aArgs: array of const); varargs; cdecl; external 'externalLibrary.dll'; However, since this approach is limited to external functions, I’d like to know if there’s any way to implement a similar variadic method directly in Delphi, avoiding the need for brackets around the arguments. My main questions are: How can I implement a Delphi variadic method that allows calling it without brackets, similar to Write/Writeln? If it's only possible using varargs with external DLLs, how would I correctly declare and call such a method? Any help or examples would be greatly appreciated! ----- I’m working on a Delphi console application where I want to redirect the standard Write and Writeln output to a synchronized memo viewer in a separate VCL application. Here's a simplified version of my current setup: unit Console.Output.MemoViewer; interface uses Winapi.Windows, System.SysUtils, System.Classes, System.SyncObjs, System.RTTI, System.Generics.Collections; type TOutputViewer = class private fVCLAppPath: string; fStartupInfo: TStartupInfo; fProcessInfo: TProcessInformation; fLogFileName: string; fLogFileStream: TFileStream; fStreamWriter: TStreamWriter; fFileLock: TCriticalSection; procedure SetFileHiddenAttribute(const aFilePath: string); procedure ExtractVCLApp(const aResourceName: string; const aOutputPath: string); procedure LaunchVCLApp; procedure WaitForVCLAppClose; procedure WriteOutput(const aText: string); public constructor Create; destructor Destroy; override; procedure mWriteln(const aArgs: array of const); procedure HandleConsoleClose; stdcall; end; implementation { TOutputViewer } constructor TOutputViewer.Create; begin fVCLAppPath := ExtractFilePath(ParamStr(0)) + 'MemoViewer.exe'; fLogFileName := 'ConsoleOutput.log'; fFileLock := TCriticalSection.Create; // Extract and launch the VCL app ExtractVCLApp('MEMOVIEWER', fVCLAppPath); LaunchVCLApp; // Initialize the log file for writing output fLogFileStream := TFileStream.Create(fLogFileName, fmCreate or fmShareDenyNone); fStreamWriter := TStreamWriter.Create(fLogFileStream, TEncoding.UTF8); end; destructor TOutputViewer.Destroy; begin fFileLock.Acquire; try FreeAndNil(fStreamWriter); FreeAndNil(fLogFileStream); finally fFileLock.Release; FreeAndNil(fFileLock); end; // Wait for VCL app to close and clean up WaitForVCLAppClose; inherited; end; procedure TOutputViewer.SetFileHiddenAttribute(const aFilePath: string); var LFileAttr: DWORD; begin LFileAttr := GetFileAttributes(PChar(aFilePath)); if LFileAttr <> INVALID_FILE_ATTRIBUTES then SetFileAttributes(PChar(aFilePath), LFileAttr or FILE_ATTRIBUTE_HIDDEN); end; procedure TOutputViewer.ExtractVCLApp(const aResourceName: string; const aOutputPath: string); var LResourceStream: TResourceStream; LFileStream: TFileStream; begin if not FileExists(aOutputPath) then begin LResourceStream := TResourceStream.Create(HInstance, aResourceName, RT_RCDATA); try LFileStream := TFileStream.Create(aOutputPath, fmCreate); try LFileStream.CopyFrom(LResourceStream, LResourceStream.Size); finally LFileStream.Free; end; finally LResourceStream.Free; end; SetFileHiddenAttribute(aOutputPath); end; end; procedure TOutputViewer.LaunchVCLApp; begin ZeroMemory(@fStartupInfo, SizeOf(fStartupInfo)); fStartupInfo.cb := SizeOf(fStartupInfo); if not CreateProcess(nil, PChar(fVCLAppPath), nil, nil, False, 0, nil, nil, fStartupInfo, fProcessInfo) then RaiseLastOSError; end; procedure TOutputViewer.WaitForVCLAppClose; begin WaitForSingleObject(fProcessInfo.hProcess, INFINITE); CloseHandle(fProcessInfo.hProcess); CloseHandle(fProcessInfo.hThread); if FileExists(fVCLAppPath) then DeleteFile(PChar(fVCLAppPath)); end; procedure TOutputViewer.WriteOutput(const aText: string); begin fFileLock.Acquire; try fStreamWriter.WriteLine(aText); fStreamWriter.Flush; finally fFileLock.Release; end; end; function VarRecToStr(const V: TVarRec): string; begin case V.VType of vtInteger: Result := IntToStr(V.VInteger); vtBoolean: Result := BoolToStr(V.VBoolean, True); vtChar: Result := V.VChar; vtString: Result := string(V.VString^); vtAnsiString: Result := string(AnsiString(V.VAnsiString)); vtWideString: Result := WideString(V.VWideString); vtUnicodeString: Result := string(UnicodeString(V.VUnicodeString)); vtInt64: Result := IntToStr(V.VInt64^); else Result := '[Unknown]'; end; end; procedure TOutputViewer.mWriteln(const aArgs: array of const); var LText: string; LArg: TVarRec; begin LText := ''; for LArg in aArgs do LText := LText + Format('%s', [VarRecToStr(LArg)]) + ' '; WriteOutput(LText.Trim); writeln(LText.Trim); end; procedure TOutputViewer.HandleConsoleClose; stdcall; begin TerminateProcess(fProcessInfo.hProcess, 0); WaitForVCLAppClose; Halt(0); end; end. program ConsoleMemoViewer; {$APPTYPE CONSOLE} uses SysUtils, Console.Output.MemoViewer in 'API\Console.Output.MemoViewer.pas'; var Viewer: TOutputViewer; begin try Viewer := TOutputViewer.Create; with Viewer do try mWriteln('Hello from redirected Writeln!:', 22, 35.7); mWriteln('This line uses redirected Write:', 22, ', Test 2: ', 35.7); mWriteln('Foo String: ', 22, ', Test 2: ', 35.7, 'Foo string:', 3333); finally Viewer.Free; end; except on E: Exception do Writeln('Error: ', E.Message); end; end. Currently, I'm using an array of const approach for mWriteln, but that requires enclosing the arguments in brackets, like this: mWriteln(['Hello', 123, 45.67]); // Requires brackets I’m aware of the overload solution where multiple versions of mWriteln can be created for different argument counts, but this is not practical when dealing with a large or unknown number of arguments.
  20. Remy Lebeau

    Creating a Server Application using tidtcpserver

    TIdTCPServer handles that just fine. It is your responsibility for tracking your objects and making sure they stick around between (re-)connects. But as for the actual association, TIdTCPServer provides two options: TIdContext has a public Data property, which you can use to associate a client with your custom data. You can derive a custom class from TIdServerContext, add whatever you want to it, and then assign that class type to the TIdTCPServer.ContextClass property before activating the server. Then, in the server's events, you can type-cast the provided TIdContext object to your custom class. When the client disconnects from the server an the owning thread is stopped. Most likely, yes. When a client connects, you can issue it a token. If the client reconnects, it can ask to reuse that same token. When the client is finished with the token, the server can invalidate it. Unless you have some other way to associate each client with a given resource, such as with a unique login userid, etc. The server will tell you in the OnDisconnect event. That is not necessary. The server is already running the client interaction in its own thread. If a client disconnects for any reason, the OnDisconnect event will be triggered, before the context is destroyed.
  21. The only way to make your ObjectIdentifier be a unique type in C++ is to declare it as a class or struct, either with an AnsiString data member, or maybe even derived from AnsiString. You could declare ObjectIdentifier as {$NODEFINE} on the Delphi side. But, you may or may not run into compatibility issues, so you should consider making ObjectIdentifier be a record on the Delphi side and then the compiler can general a compatible struct on the C++ side.
  22. DelphiUdIT

    Openssl dll questions

    You can read the sources of Indy to look how it works (with the OpenSSL 1.0.2u, the Indy develop with RAD Studio use this version). Look at guthub repo for more upgrades (https://github.com/IndySockets). Another way is to look how ICS works (https://wiki.overbyte.eu/wiki/index.php/ICS_Download or via GetIt).
  23. You should take some time and read this topic: Configuring Drivers (FireDAC) - RAD Studio (embarcadero.com)
  24. Darian Miller

    Is datasnap Webbroker a good approach?

    There are quite a few different avenues you could take to support API development. The first step in any is to get it "to work" which you seemed to have accomplished! Your next question is valid - will it scale? The question remains, how much do you need it to scale? How many concurrent connections are planned, what sort of total throughput is required and what are acceptable latencies? Once you define those, you can test those things yourself by using tools like JMeter and BlazeMeter and see if your performance is acceptable. If it's not, then you can look at scaling methods, either locally with Windows Clusters or migrating to cloud services on AWS or Azure. If the performance isn't satisfactory, you could also look into different implementations. One of the most commonly used frameworks is mORMot which has been highly optimized. If you join their community you'll likely get some help getting started. There's a LOT of code available, and much you can ignore to get started. Another option is to get a commercial finely-tuned multi-tier approach from Components4Developers. This option has been around a very long time and is quite mature, and quite performant. Another commercial option to look into is the Remoting SDK from remobjects. This also has been around quite a long time and is widely used. For a real simple and performant commercial toolkit, also look at RealThinClient components. There are plenty of other choices out there. The next step that I would recommend is to analyze your projected usage and start establishing some real testing metrics that you can validate current and future decisions on. Get the tools in place to back up your API infrastructure with measurements and validation. In addition to API testing, get line-by-line performance measurements with ProDelphi or Nexus Quality Suite to track down different implementations.
  25. Don't tell me - but this the almighty excuse brought up by the decision makers almost every time some issue like this is brought up - "but what about existing code" - like for that dreaded "directly passing result of ctor call to interface parameter issue" - what about existing code? Well existing code is most likely suffering from a defect. The stupidity of the Delphi compiler in almost every aspect and the unwillingness to change anything significant on that is making me furious!
×