<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <title>Code-Kungfu.com - The Modern Object Pascal Coding Blog</title>
    <link href="https://code-kungfu.com/feed.xml" rel="self" />
    <link href="https://code-kungfu.com" />
    <updated>2025-06-28T01:47:41+02:00</updated>
    <author>
        <name>Glenn Dufke</name>
    </author>
    <id>https://code-kungfu.com</id>

    <entry>
        <title>RAD Studio 13 Beta is now open!</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/rad-studio-13-beta-is-now-open.html"/>
        <id>https://code-kungfu.com/rad-studio-13-beta-is-now-open.html</id>
            <category term="RAD Studio"/>
            <category term="Productivity"/>
            <category term="Delphi"/>
            <category term="Call for Testing"/>
            <category term="C++Builder"/>
            <category term="Beta Testing"/>

        <updated>2025-06-28T00:40:37+02:00</updated>
            <summary>
                <![CDATA[
                    <p>Beta signup is now open - are you ready to participate?</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p>Beta signup is now open - are you ready to participate?</p>

<p>Embarcadero has opened up for the participation of the next major version of RAD Studio! You might already seen the previous blog posts about the next version which they have already announced will be 13 and named Florence.</p>
<p>As this is a major release, breaking changes will be introduced and it looks like this release will be feature packed!</p>
<p>If you're eligible - that is, you have an active update subscription, you can follow the link to with instructions on how to <strong><a href="https://blogs.embarcadero.com/update-subscription-customers-invited-to-join-rad-studio-ganymede-beta/" target="_blank" rel="noopener noreferrer">sign up</a></strong></p>
<p>I would highly recommend participating in the beta and test out every area. Your feedback is invaluable to Embarcadero and helps shape the product - don't delay, sign up and participate today!</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Have you tried turning it off and on again?</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/have-you-tried-turning-it-off-and-on-again.html"/>
        <id>https://code-kungfu.com/have-you-tried-turning-it-off-and-on-again.html</id>
            <category term="Maintenance"/>
            <category term="Dumpster"/>

        <updated>2025-02-09T02:13:00+01:00</updated>
            <summary>
                <![CDATA[
                    One of my goals for 2025 is to write more on this blog/website, so I've decided to do a revamp.
                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p>One of my goals for 2025 is to write more on this blog/website, so I've decided to do a revamp.<br>Out with the old and in with the new. Well, at least switched to a static site generator which should speed things up further and reduce the level of maintenance.</p>
<p>Don't get me wrong, I really enjoy working with Joomla. It's a great a feature-rich CMS system, I just had to realize I don't have the same amount of time for maintenance today, as I used to in the past.<br><br>While we're doing a remodel, expect some content to be temporarily gone until it has been ported over to this new platform.<br>I'm trying out the Publii Open Source CMS for static sites. It's decent, though it is an electron app after which is absolutely atrocious.<br>Maybe I should write a native implementation where you can switch generator backends? 🤔</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Restoring Code Completion and Error Insight functionality in Delphi 11.2</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/restoring-code-completion-and-error-insight-functionality-in-delphi-112.html"/>
        <id>https://code-kungfu.com/restoring-code-completion-and-error-insight-functionality-in-delphi-112.html</id>
            <category term="RAD Studio"/>
            <category term="HotFix"/>
            <category term="Delphi"/>
            <category term="11.2"/>

        <updated>2022-12-30T21:46:00+01:00</updated>
            <summary>
                <![CDATA[
                    Delphi 11.2 has been out for some months now. Unfortunately, issues have crept into the 11.2 version of DelphiLSP -&hellip;
                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p>Delphi 11.2 has been out for some months now.<br>Unfortunately, issues have crept into the 11.2 version of DelphiLSP - the compiler driven LSP server which provides ErrorInsight and Code Completion information to the IDE.<br>This often results in the LSP server stops returning any results, from within minutes to hours when loading a project - much to frustration for users, inclusive myself and required frequent restarts of the LSP server.<br><br>Just after the release of 11.2 and reports started to mount with how unstable Code Completion was, I discovered you can use the more stable Delphi 11.1 LSP server to restore the most important functionality - Code Completion and Error Insight.<br>Given that the first reports were inconsistent, I was holding off to propose this temporary workaround until Embarcadero had a chance to assess the scope of the instabilities and how to address them, hence the blog post now.<br>Thanks to how LSP works, we can easily apply this fix.<br>Please keep in mind it is a temporary workaround, especially if your project is large.<br>Some functionality will not work, like mouse hovering a method or variable.<br>This can of course be a deal breaker for some, but I think it is an acceptable tradeoff for having stable code completion until 11.3 comes around (The beta is now open for customers with active update subscription. I'd encourage you to sign up and help test the next release, especially around code completion as your input will help improve this area significantly).<br><br>You can download the Delphi 11.1 LSP Server <a href="https://altd.embarcadero.com/releases/studio/22.0/DelphiLSP_11_1.zip">directly from Embarcadero Here</a><br>SHA256: ae83aa461612206241bcce993a1a50f84275df09d1bfcc2b09331f4ca1884aea<br><br><br></p>
<p>To install, follow the steps below:</p>
<ol>
<li>First make sure the RAD Studio IDE is closed</li>
<li>Navigate to the install directory of RAD Studio, where bds is located. A default install are usually %programfiles(x86)%\Embarcadero\Studio\22.0\bin</li>
<li>Make a backup copy of DelphiLSP.exe</li>
<li>Verify the SHA256 signature of the downloaded zip file</li>
<li>Extract DelphiLSP from the zip file, and copy it over into the bin folder as noted above.</li>
<li>Make sure the executable is still named DelphiLsp.exe</li>
<li>Start the IDE and test code completion.</li>
</ol>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Custom Editor Themes for Delphi and RAD Studio</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/custom-editor-themes-for-delphi-and-rad-studio.html"/>
        <id>https://code-kungfu.com/custom-editor-themes-for-delphi-and-rad-studio.html</id>
            <category term="Tip"/>
            <category term="RAD Studio"/>
            <category term="Productivity"/>
            <category term="IDE Enhancement"/>
            <category term="Delphi"/>

        <updated>2022-12-30T20:57:00+01:00</updated>
            <summary>
                <![CDATA[
                    I've been asked multiple times what editor theme I'm using in Delphi dark mode during webinars and presentations, and I&hellip;
                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p class="align-left">I've been asked multiple times what editor theme I'm using in Delphi dark mode during webinars and presentations, and I thought I would share the story behind.<br><br>The standard editor theme shipped with Delphi isn't taking into account if the display is dim or if you're using a tool like <a href="https://justgetflux.com/" target="_blank" rel="noopener noreferrer">f.lux</a> to adjust the red tint based on your time zone (It's a great, free tool which makes working in evenings and nights less painful for your eyes). This makes it harder to distinguish keywords and other values in the editor.<br><br>After enough frustration, I made my own editor theme using <a href="https://github.com/RRUZ/delphi-ide-theme-editor/releases/" target="_blank" rel="noopener noreferrer">DITE</a> which works a lot better (at least for me, I hope, for you too).<br>Download the file below, extract the xml file and drop it into %ProgramData%\DITE\Themes<br>Restart DITE and you'll see the theme "<strong>GD-1337NiteDark</strong>" in the list.<br>For this theme I recommend the <a href="https://fonts.google.com/specimen/Source+Code+Pro" target="_blank" rel="noopener">Souce Code Pro</a> font at size 12, but you can of course configure the editor font to your own liking.<br><br><a href="https://code-kungfu.com/media/files/GD-1337NiteDark.theme.zip">Click here to download the theme</a></p>
<p><code>File: GD-1337NiteDark.theme.zip</code><br><code>SHA256: A72B9C15D61C01AFF2858406B654937421D5CE99B47406EA7A65E3A327C5FB52</code></p>
<figure class="post__image post__image--center"><img loading="lazy"  src="https://code-kungfu.com/media/posts/10/DITETheme.png" alt="" width="744" height="490" sizes="(max-width: 48em) 100vw, 768px" srcset="https://code-kungfu.com/media/posts/10/responsive/DITETheme-xs.png 300w ,https://code-kungfu.com/media/posts/10/responsive/DITETheme-sm.png 480w ,https://code-kungfu.com/media/posts/10/responsive/DITETheme-md.png 768w"></figure>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Getting Started with Azure Function Apps in Delphi</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/getting-started-with-azure-function-apps-in-delphi.html"/>
        <id>https://code-kungfu.com/getting-started-with-azure-function-apps-in-delphi.html</id>
            <category term="RAD Studio"/>
            <category term="Delphi"/>
            <category term="Cloud"/>
            <category term="Azure"/>
            <category term="10.4+"/>

        <updated>2021-07-15T00:01:00+02:00</updated>
            <summary>
                <![CDATA[
                    In extension to a recent Webinar abut the same topic I did together with Stephen Ball from Embarcadero (Watch here),&hellip;
                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p>In extension to a recent Webinar abut the same topic I did together with Stephen Ball from Embarcadero (Watch here), I’ve condensed and added additional information I was unable to show during the initial Webinar in the following blog post. This is intended as a primer to get started with Azure Function Apps and Delphi.<br>Azure Function Apps is a handy component in the category of “serverless”, part of the Microsoft Azure Cloud Platform.<br><br></p>
<p>Authors opinion:<br><em>Personally I don’t subscribe to the buzzword “Serverless” as we do need servers to make things work, rather it’s a managed event driven framework which abstracts some of the manual labor away with dynamic resource allocation and so on.<br>“Serverless” is a sellable buzzword for less management cost – but it does require servers at the end of the day.<br>Call it what it is - managed event driven modules.<br>Plan accordingly, and evaluate carefully, as “Serverless” isn’t the holy grail for every scenario.</em></p>
<p>In a nutshell, Azure Function Apps are self-contained web servers that respond to an event – an api endpoint and allows you to scale up and down based on demand without you having to worry about a lack of resources.</p>
<p>Not too long ago, Microsoft added support for running a native compiled binary, granted it follow certain conventions, as a Function App. They demonstrated this by showing how you could implement a custom http trigger in Go and Rust, both compiled languages, however these languages don’t offer the same advantages as Object Pascal does. This means you’re not limited to a managed language like C# or interpreted languages like JavaScript or Python.</p>
<p>In production you can either target a 64-bit Linux or Windows Function App Runtime – thankfully Delphi conveniently have compilers for both targets!</p>
<p>Before we get started, we need to install a few prerequisites. To avoid “Don’t Repeat Yourself”, I will be linking to setup guides from the Microsoft documentation, as they already have covered the basics well. The first section is setting up your <a href="https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-other?tabs=go%2Cwindows#configure-your-environment" target="_blank" rel="noopener">environment</a>, but in essence we need:</p>
<ul>
<li data-mce-word-list="1"><strong>Azure Functions Core Tools</strong> – A local version of the Function Apps runtime also found in the cloud.<br>- In this demo I’m using the 32-bit version of the Function Core Tools framework, but for production it is 64-bit only.</li>
<li data-mce-word-list="1"><strong>Visual Studio Code</strong> – For the time being, until my RAD Studio Azure plugin is ready, VS Code has the Azure Extension which makes it easier to create and deploy Function Apps.</li>
<li data-mce-word-list="1"><strong>Azure Functions Extension for VS Code</strong> – Connects to your Azure Cloud account and makes it easier to create and deploy Azure Functions</li>
</ul>
<p>As we’re using Delphi, we won’t need either the Go or Rust elements.</p>
<p>Once the prerequisites are installed, either clone the demo projects from this <a href="https://github.com/code-kungfu/Delphi-AzureFunctionApps" target="_blank" rel="noopener">GitHub repository</a>, or set up a new blank Azure Function Apps custom handler project, following the <a href="https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-other?tabs=go%2Cwindows#create-an-azure-functions-project" target="_blank" rel="noopener">guide outlined here</a></p>
<figure class="post__image post__image--center">For project management simplicity I would encourage you to follow this folder structure when creating an Azure Function App in Delphi:<br><img loading="lazy"  src="https://code-kungfu.com/media/posts/7//FuncApp1.png" alt="" width="200" height="236" sizes="(max-width: 48em) 100vw, 768px" srcset="https://code-kungfu.com/media/posts/7//responsive/FuncApp1-xs.png 300w ,https://code-kungfu.com/media/posts/7//responsive/FuncApp1-sm.png 480w ,https://code-kungfu.com/media/posts/7//responsive/FuncApp1-md.png 768w"></figure>
<p><strong>DelphiFunctionApp</strong> – This folder contains the actual Delphi project. The project file has been set up to output the binary one level above. Go to Project Options -&gt; Building -&gt; Delphi Compiler and set the Output directory to ..\</p>
<p><strong>DelphiTrigger</strong> – This folder contains the Azure Function descriptor “function.json” which instructs the Function Runtime how to handle this custom trigger and what methods the function app supports.</p>
<figure class="post__image post__image--center"><strong>“host.json”</strong> – This file instructs the Function Runtime how to load our custom HTTP trigger (Our Delphi app) – the “defaultExecutablePath” and in this case, also instructs the Function Runtime to forward the HTTP requests with the setting “enableForwardingHttpRequest”: true – for our purpose it greatly simplifies development.<br>Remember to rename the name of the executable according to what Function App Runtime stack (Windows or Linux) you’re executing on in the production environment.<br><br><img loading="lazy"  src="https://code-kungfu.com/media/posts/7//FuncApp2.png" alt="" width="614" height="581" sizes="(max-width: 48em) 100vw, 768px" srcset="https://code-kungfu.com/media/posts/7//responsive/FuncApp2-xs.png 300w ,https://code-kungfu.com/media/posts/7//responsive/FuncApp2-sm.png 480w ,https://code-kungfu.com/media/posts/7//responsive/FuncApp2-md.png 768w"></figure><br>For now, we won’t focus on the rest of the files listed in the directory.<br><br></p>
<h4><strong>Now let’s write some Delphi code!<br></strong></h4>
<p> </p>
<p>In these demo projects, I’ll use the Standalone WebBroker project template built directly into Delphi, based around the Indy components. For a future post, we will be investigating other compact webserver offerings for Delphi.</p>
<p>The first demo project, “Example001_SimpleHelloWorld” we will start with an empty WebBroker project, trim out unnecessary code, add a Linux target for convenience, and test that the local Function Runtime is able to execute the code and emit a HelloWorld JSON string to the browser.</p>
<p>In the second demo project, “Example002_ParsingRequestParameters” we’ll explore how to parse provided URL parameters and return a response based on the parsed input.<br><br>If you don’t set the enableForwardingHttpRequest option to true, the Function Runtime will send a JSON payload to your http handler (your Delphi app). In a future blog post we’ll explore how you can parse this payload and manage the data received.</p>
<p>Common for a standalone console webbroker template, is the interactive menu.<br>We want the web server component to boot up immediately, so we are going to cut out the additional fluff added, which leaves us with the methods:</p>
<p>BindPort()<br><br>CheckPort()</p>
<p>StartServer()</p>
<p>StopServer()</p>
<p>RunServer()</p>
<p>And the main application entry point.</p>
<p>Handling the request happens in the default webmodule created in the DefaultHandlerAction.<br><br></p>
<pre class="language-pascal line-numbers"><code>procedure TwmAzureFunction.WebModule1DefaultHandlerAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const
  cJSON = 'application/json';
var
  LJSONObject: TJSONObject;
begin
  LJSONObject := TJSONObject.Create;
  try
    LJSONObject.AddPair('HelloWorldFunction', TJSONBool.Create(False));
    if Request.PathInfo.Equals('/api/DelphiTrigger') then
      begin
        Response.ContentType := cJSON;
        Response.Content := LJSONObject.ToJSON;
        FunctionRequested := True;
      end;
  finally
    LJSONObject.Free;
  end;
end;</code></pre>
<p>Once you have implemented your DefaultHandlerAction and everything is set up, compile the project to produce an exe file.</p>
<figure class="post__image post__image--center">Open a command prompt or PowerShell window, and navigate to the root folder of the Function Apps project (Where you have the host.json file). Run the command: func start --verbose<br>If everything is set up, the Function Apps Runtime will boot up and load our custom HTTP trigger and webbroker executable.<br>Try opening a browser and navigate to the URL listed in the output of your command prompt / PoweShell window.<br><br><img loading="lazy"  src="https://code-kungfu.com/media/posts/7//FuncApp3.png" alt="" width="541" height="72" sizes="(max-width: 48em) 100vw, 768px" srcset="https://code-kungfu.com/media/posts/7//responsive/FuncApp3-xs.png 300w ,https://code-kungfu.com/media/posts/7//responsive/FuncApp3-sm.png 480w ,https://code-kungfu.com/media/posts/7//responsive/FuncApp3-md.png 768w"></figure>
<p>You should see the Function App Runtime receiving the request, forwarding it to our Delphi app and return the response our Delphi app forwarded.</p>
<p>In our second example, where we handle the parameters, provided in the URL, we reuse most of our existing hello world example.</p>
<p>The change is how the parameter URL is provided, and how we handle the Request in our WebModule.</p>
<p>By modifying our DefaultHandlerAction we can check whether additional queries have been added.<br>If we provide these parameters here “?Name=Glenn&amp;Age=32&amp;Adult=True” appended to our trigger, we get a valid JSON response.<br>If we’re not providing the correct parameters, we’ll get an error.<br><br></p>
<pre class="language-pascal line-numbers"><code>procedure TwmAzureFunction.WebModule1DefaultHandlerAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const
  cJSON = 'application/json';
var
  LJSONObject: TJSONObject;
begin
  LJSONObject := TJSONObject.Create;
  try
    if Request.PathInfo.Equals('/api/DelphiTrigger') then
      begin
        if Request.QueryFields.Count = 3 then
          begin
            LJSONObject.AddPair('PersonName', TJSONString.Create(Request.QueryFields.Values['Name']));
            LJSONObject.AddPair('PersonAge', TJSONNumber.Create(Request.QueryFields.Values['Age'].ToDouble));
            LJSONObject.AddPair('PersonIsAdult', TJSONBool.Create(Request.QueryFields.Values['Adult'].ToBoolean));
          end
        else
          LJSONObject.AddPair('Error', 'Not enough parameters');
        Response.ContentType := cJSON;
        Response.Content := LJSONObject.ToJSON;
        FunctionRequested := True;
      end;
  finally
    LJSONObject.Free;
  end;
end;</code></pre>
<p>For greater control, you can even send JSON objects!</p>
<p>Reach out to me using any of the mediums listed on the <a href="https://code-kungfu.com/about.html">About Page</a> if you have further questions!</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Sign your code - And use SHA-2!</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/sign-your-code-and-use-sha-2.html"/>
        <id>https://code-kungfu.com/sign-your-code-and-use-sha-2.html</id>
            <category term="Tip"/>
            <category term="Developer News"/>
            <category term="Cyber Security"/>
            <category term="Code Signing"/>

        <updated>2021-04-22T12:19:00+02:00</updated>
            <summary>
                <![CDATA[
                    Code signing your production executable and supplementary dlls, has been treated as optional for many developers for a long time.
                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p>Code signing your production executable and supplementary dlls, has been treated as optional for many developers for a long time.<br><strong>This should stop and become mandatory practice to sign everything you ship!</strong><br>It is a topic I have tried to bring more awareness to, not only to ensure you ship a trustworthy application, but also to combat stricter execution environments.<br>As a side note, code signing certificates are cheap nowadays. Getting an OV certificate, which would suffice for most developers out there, <span style="text-decoration: line-through;">is as low as $84 for a year at <a href="https://www.ksoftware.net/code-signing-certificates/">ksoftware</a></span>. Pricing is noted as this time of writing this article and might change in the future.<br>- There's really no excuse for not signing today.<br>EV certificates is also an option, though they serve a different purpose, are more expensive and have a more rigorous validation process.</p>
<p>For those who already are familiar with code signing, you might have noted we've been signing with SHA-1 for a very long time. It's kind of been the norm.<br>A couple years back, however, security experts demonstrated weaknesses in the SHA-1 hashing algorithm and deemed it unsafe.<br>This has also resulted in code signing should at least use SHA-256 instead - also known as SHA-2.<br>Recently, Microsoft published a blog post detailing the cut-off date, which basically means the SHA-1 Trusted Root Certificate will expire and their updates, and everything shipped from them, will be signed with SHA-2 only.<br>While it might not affect you directly at first, your current code signing certificate might be linked to this root certificate, and the expiration might result in validation issues.<br>I would encourage you, dear reader and fellow developer, to sign your code you ship and start using SHA-2 and reduce the headache with customer support tickets.</p>
<p>Link to the <a href="https://techcommunity.microsoft.com/t5/windows-it-pro-blog/microsoft-to-use-sha-2-exclusively-starting-may-9-2021/ba-p/2261924">Microsoft</a> blog post</p>
<p>As always, I hope you learned something.</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Delphi Managed Records - Making your code smart</title>
        <author>
            <name>Glenn Dufke</name>
        </author>
        <link href="https://code-kungfu.com/delphi-managed-records-making-your-code-smart.html"/>
        <id>https://code-kungfu.com/delphi-managed-records-making-your-code-smart.html</id>
            <category term="RAD Studio"/>
            <category term="Managed Records"/>
            <category term="Language Feature"/>
            <category term="Delphi"/>
            <category term="10.4+"/>

        <updated>2020-10-13T02:01:00+02:00</updated>
            <summary>
                <![CDATA[
                    With Delphi 10.4, Managed Records language feature was introduced. As some might remember, it was originally intended for Delphi 10.3,&hellip;
                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                <p>With Delphi 10.4, Managed Records language feature was introduced. As some might remember, it was originally intended for Delphi 10.3, but Embarcadero wisely decided to postpone the feature, to ensure a solid implementation - and now we have it!<br><br>It is important to mention, this is a language feature available with Delphi 10.4 and newer.</p>
<p>Managed Records opens up many new possibilities to write smarter and more effective code without syntactic sugar and bloat which other popular languages suffer from. This is one of the many reasons I keep using Delphi - the language is simple, yet powerful and allows you to eloquently write software.<br>Writing software is after all an art, just like writing a novel.<br><br>Anyways, back to the actual topic - Managed Records.<br><br>In this article, I want to share a little clever tidbit of how you can utilize the automatic initialization and finalization calls of Managed Records. <br>INI files is still one of the easiest ways to have a key-value settings storage across platforms, and usually it takes some legwork to create the object, read or write your settings and ensuring the object is destroyed again.<br>What if you could access the INI Read or Write features right away and don't worry about keeping track of the object life-cycle?<br>- Managed Records to the rescue!<br><br>In a recent feedback tool I've been working on for another client project, I had the need to save and load a few settings throughout the application.<br>I figured I didn't want to do the classic create object, do my operation in a try-finally block and close down the object again and thought that Managed Records automatic initialization and finalization should be able to do the trick.<br>The following snippet illustrates how this can be done:</p>
<pre class="line-numbers language-pascal"><code>unit MRTest.AppSettings;

interface

uses
  System.SysUtils,
  System.Classes,
  System.IOUtils,
  System.IniFiles;

type
  TAppSettings = record
  strict private const
    cIniFileName: string = 'TestSettings.ini';
  strict private
    FAppConf: TMemIniFile;
    class function TAppSettings.InternalGetFullIniFile: string; static;
  public
    class operator Initialize(out ADest: TAppSettings);
    class operator Finalize(var ADest: TAppSettings);
    property AppConf: TMemIniFile read FAppConf write FAppConf;
  end;

implementation

{ TAppSettings }

class operator TAppSettings.Initialize(out ADest: TAppSettings);
begin
  ADest.FAppConf := TMemIniFile.Create(ADest.InternalGetFullIniFile);
  ADest.FAppConf.AutoSave := True;
end;

class operator TAppSettings.Finalize(var ADest: TAppSettings);
begin
  ADest.FAppConf.Free;
end;

class function TAppSettings.InternalGetFullIniFile: string;
begin
  Result := TPath.Combine(TPath.GetDocumentsPath, cIniFileName);
end;

end.</code></pre>
<p>Now you can just include the unit in your project where needed and automatically allocate a variable of the type TAppSettings (Or whatever name your record type has).<br>The example below has been reduced for the simplicity to give you a gist of how it can be approached.</p>
<pre class="language-pascal line-numbers"><code>uses
  MRTest.AppSettings;


procedure LoadSettings;
begin
  var LApp: TAppSettings;
  CheckBox1.Checked := LApp.AppConf.ReadBool('Settings', 'FirstStart', True);
end;

procedure SaveSettings;
begin
  var LApp: TAppSettings;
  LApp.AppConf.WriteBool('Settings','FirstStart', CheckBox1.Checked);
end;</code></pre>
<p>As you see, everything is encapsulated in the record type and the managed nature automatically takes care of creating the INI object with the correct settings when it goes into scope, and unloads it again once it goes out of scope.<br><br>I hope you found this information useful.</p>
            ]]>
        </content>
    </entry>
</feed>
