VCL

Calculate square meters of an area in your favorite map service

TMS FNC Maps v3.0 brings a major new feature (more about HTML/CSS element containers in this blog), but along with it, a lot of smaller fixes and improvements. Basically each update brings quality of life improvements. Moving forward from the legacy TMS WebGMaps & WebOSMaps, which were based on the deprecated Internet Explorer technology, we need to port features that were available in those products. We always ask ourselves the question whether those features were implemented in an easy and intuitive way and with TMS FNC Maps our goal is to strive towards a more complete experience by analyzing each feature and then implement it in a way that benefits your application and the developer behind it. One of those improvements is a function that allows polygon area calculation. GeoJSON Polygons in TMS FNC Maps can be displayed by adding a collection of coordinates. Typically, those coordinates come from a database, or a file, or requested from a REST service in GeoJSON format (https://geojson.org/). In this sample, we used the coordinates of Germany. The code below demonstrates how to load GeoJSON data from a file. TMSFNCMaps1.BeginUpdate; TMSFNCMaps1.LoadGeoJSONFromFile(‘germany.geojson’); TMSFNCMaps1.EndUpdate; This will render the following polygon on the map. (map service used in the screenshot is MapBox) The polygon appearance can be changed. The code below demonstrates how to change the opacity of the polygon as well as fill and stroke color. var p: TTMSFNCMapsPolygon; begin p := TMSFNCMaps1.Polygons[0]; p.FillOpacity := 0.4; p.FillColor := gcGreenyellow; p.StrokeOpacity := 0.4; p.StrokeColor := gcGreen; Measuring the area The purpose of this blog post is to show how to calculate the polygon area in square meters (or square kilometer in the demonstrated sample). In the unit *.TMSFNCMapsCommonTypes.pas there is a MeasureArea function that accepts an array of coordinates. We already loaded our polygon from a GeoJSON file and have the coordinates available. var p: TTMSFNCMapsPolygon; m: Double; begin p := TMSFNCMaps1.Polygons[0]; //calculate area in square kilometers m := MeasureArea(p.Coordinates.ToArray) / 1000000; Displaying the results We now have the area in square kilometers of our polygon area. We can display it anywhere in our application, but this sample would not be complete without a demonstration of one of the most exciting features since TMS FNC Maps v3.0. For displaying the results, we chose the Element Containers feature (see this blog for more information). The complete code snippet can be found below as well as the final result. procedure TMapForm.RenderPolygon; var p: TTMSFNCMapsPolygon; m: Double; h: TStringList; e: TTMSFNCMapsElementContainer; begin TMSFNCMaps1.BeginUpdate; TMSFNCMaps1.LoadGeoJSONFromFile(‘germany.geojson’); TMSFNCMaps1.EndUpdate; p := TMSFNCMaps1.Polygons[0]; p.FillOpacity := 0.4; p.FillColor := gcGreenyellow; p.StrokeOpacity := 0.4; p.StrokeColor := gcGreen; //calculate area in square kilometers m := MeasureArea(p.Coordinates.ToArray) / 1000000; h := TStringList.Create; try h.Add(‘The surface area of Germany is approximately ‘ + Format(‘%.0f km²’, [m]) + ”); e := TMSFNCMaps1.AddElementContainer(h, nil, nil, poTopRight); e.UseDefaultStyle := False; finally h.Free; end; TMSFNCMaps1.EndUpdate; end; procedure TMapForm.FormCreate(Sender: TObject); begin TMSFNCMaps1.HeadLinks.AddStyleSheetLink(‘https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css’); TMSFNCMaps1.HeadLinks.AddScript(‘https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js’); TMSFNCMaps1.HeadLinks.AddScript(‘https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js’); TMSFNCMaps1.ReInitialize; end; Excited? Go ahead and download TMS FNC Maps. Explore the features and demos and feel free to leave a comment on this blog.

Read More

Upcoming interactive webinar: TMS WEB Core real-life apps and the best tips & tricks

On March 10 at 16h00 UTC (17h00 CET), we have another ‘first’ at TMS Web Academy: a webinar co-presented by five (5!) TMS WEB Core users who meanwhile have serious experience under their belt in building web applications with Delphi and TMS WEB Core and with apps deployed live.  Together with 5 co-presenters, we will show you these real-life web client applications, give an architectural overview and furthermore, share loads of tips and tricks to help building web client apps with Delphi faster and better. A very interesting part of the co-presenter team is each has used TMS WEB Core from a different angle. This not only highlights the flexibility of TMS WEB Core but also gives you an insight in the wide range of possibilities to create apps with TMS WEB Core. Co-presenters We’re extremely thankful and pleased with the bundled expertise we have for you on this webinar. Here is the list of long-time Delphi developers and TMS WEB Core power users with their specific area of expertise: – Dave Akerman  Building TMS WEB Core Miletus Raspberry Pi apps accessing the Raspberry Pi hardware directly – Russell Weetch  Building huge real-life TMS WEB Core web client apps driven by XData backends TMS Web Academy v2.5 This upcoming webinar experience with 5 co-presenters will also take advantage of the new release v2.5 of TMS Web Academy. The TMS Web Academy is built with TMS WEB Core itself. This new version will allow us to switch presenters & screen sharing live during the webinar. While useful for co-presented webinars, this new v2.5 feature will also help us when we introduce training sessions via the TMS Web Academy platform, allowing the presenter to see screens of users and have a more lively interaction.    Register now & participate! Register here for your unique opportunity to ask questions directly to 5 TMS WEB Core power users and exchange techniques, discuss technical choices and more… during the webinar on March 10, 2022 at 16h00 UTC (17h00 CET)

Read More

TMS MemInsight, Delphi runtime memory inspection: statistics and filters

Using TMS MemInsight is easy: drop a component on your form, set some properties and there you go. Altough the component and UI of TMS MemInsight are currently based on the VCL you can already use it in your FireMonkey (on Windows and without UI), Windows service or console applications or any other headless application, such as a TMX XData server. But in this blog, we dive deeper: TMS MemInsight has a wide API and offers all of its options and features by code. Let’s start by looking at some of the properties of the memory profiler first. To access it, as well as other parts of TMS MemInsight, use the units TMS.MI.Access and TMS.MI.Memory from within your code. These units contain some functions which serve as entry point to gain access to the interfaces needed to control tracing, filters as well as more advanced options like collecting memory statistics as it’s done within the UI. Another handy unit is TMS.MI.Core which offers some ready to use utility functions. You can enable/disable the profiler by setting it’s Active property. You can Suspend/Resume profiling for the current thread by calling the methods of the same name or exclude them completely to control and tune what is being traced. For this, TMS MemInsight also offers filters which allow for even more fine tuning. Filters can also be customized and attached and removed dynamically. The folder “Dev” contains a sample for such a filter which allows tracing of objects contained in certain units only. We will use it in our example below. Another useful method is SuspendMethod which disables tracing for the current thread until the current scope is exited. Usually this is, as the name suggests, the current method, although this has slightly changed in Delphi 11 Alexandria with the introduction of inline variables where the scope might be limited to the current begin/end block. The memory profiler includes three different filters. The Default filter allows to configure, which threads are being traced as well as setting the TraceTypes: mtString, mtObject, mtArray, mtRecord and mtUnknown. Beside of that you can, if your applications is build using run-time packages, select which package classes are shown. The IncludeFilter and ExcludeFilter allow fine grained tracing considering the class name of objects and supports pattern matching. This way you can limit the tracing to certain class names as well as class names matching something like “TYourPrefix*” or exclude class names matching similar patterns. All filters can be activated/deactivated by setting their Active property. You can store and reload these configurations for latter use. Let’s jump right into our first example: collecting memory statistics and dumping them into a file. Working with these statistics is, in almost all cases, my starting point when trying to understand why, where and what the application is consuming. As this is happening during run-time I can use the application, repeat certain functions and observe its behavior to isolate and concentrate on concrete spots. Limiting the tracing on these identified classes by using the above mentioned filters is also helpful. For the sake of this example we create five utility functions: InitializeProfiling, StartProfiling, StopProfiling, ResetStatistics and SaveToFile. InitializeProfiling will set up some default options and attach and configure the filter as well as the memory statistics. We also disable stack traces as […]

Read More

TMS WEB Core for Visual Studio Code 1.9.7.0 released

We’re happy to announce that with the new release of TMS WEB Core for Visual Studio Code, we stepped up the level of web client application development with Object Pascal. The key goals of this new release 1.9.7.0 are: Introduce visual form inheritance Framework synchronization with TMS WEB Core for Delphi Increased robustness, compatibility and stability Improved coding experience thanks to a new OmniPascal update Visual form inheritance Now you can take advantage of the visual form inheritance feature also from the TMS WEB Core Visual Studio Code IDE. This means you can design a form and created an inherited form and use base form class and inherited form live visually in the IDE. Any changes you apply to the base class will be immediately visible in the descending form class and modifications to the descending class are nicely managed and persisted. Using visual form inheritance should significantly increase your productivity when you deal with web application form logic with repeating patterns. See for yourself how this visual form inheritance feature is used in the IDE: Framework synchronization with TMS WEB Core for Delphi In the new release, all latest features & improvements of the TMS WEB Core framework are adopted in TMS WEB Core for Visual Studio Code. This includes: New : geMemo editor type added in TWebStringGrid New : WordWrap property added in TWebStringGrid New : TWebResponsiveGrid.OnGetItemTemplate event added New : Support for custom images added in TWebDBNavigator New : SelectCell() added in TWebTableControl New : ScrollRowInView() added in TWebTableControl New : MultiSelect option added to TWebResponsiveGrid New : Miletus use of USB UART on Raspberry Pi New : Miletus extensibility through libraries New : Hyperlinks clickable with Ctrl key in TWebRichEditToolbar New : Hyperlink button added in TWebRichEditToolbar New : FindCellFindNext functions added in TWebTableControl New : Filtering capability added in TWebTableControl TWebDBTableControl       + various smaller improvements and fixes. Given that the TMS WEB Core framework under TMS WEB Core for Visual Studio Code is identical to TMS WEB Core for Delphi, this means you can perfectly continue development projects handled by other team members in Delphi also from Visual Studio Code and vice versa.  Increased robustness, compatibility and stability. While TMS WEB Core for Visual Studio Code is younger than the version for Delphi, it comes with the additional challenge that it has a web technology based form designer. This means that it uses a full WYSIWYG form designer that also uses HTML elements or complete HTML templates live on the form designer. You can understand this brings increased complexities to manage in the designer and we focused on improving the experience at design-time in this new release. Improvements were done to the framework to handle this design-time situation better and we significantly extended the number of tests run from within the IDE itself to guarantee stability & compatibility. This new release should move this a significant step forward. Improved coding experience thanks to a new OmniPascal update Not really a part of this new TMS WEB Core for Visual Studio Code 1.9.7.0 release, but the new OmniPascal version will still improve your coding experience while developing in TMS WEB Core for Visual Studio Code. We worked together with the author of OmniPascal. This Visual Studio Code plugin provides code completion & highlighting […]

Read More

Embarcadero MVP Jens Fudge on FlexCel

TMS FlexCel is one of our flagship products, with well over 20 years of development going into it and meanwhile supporting the near entire Microsoft Excel feature set and as development tools Delphi, C++Builder and .NET via C#, VB.NET or .. actually any Windows language that can use DLL’s via TMS FlexCel DLL.  While FlexCel can be used to read and write .XLS and .XLSX files extremely fast, on-the-fly and most importantly, without the need to have Microsoft Excel installed, it can actually also being used as a reporting tool where it generates Excel, PDF, HTML, SVG, Image files… with  report templates defined in an Excel file and possibly also data coming from an Excel file. Today, we bring you a fantastic opportunity to discover how Jens Fudge, Embarcadero MVP in Denmark, frequent speaker at Delphi conferences uses FlexCel. Jens is not only Delphi expert, he was also Paralympic Champion Archery and still heavily involved with archery and training top sportspeople. And that’s not all, Jens runs his own Delphi development consulting company and published in 2020 also a book “Choose to be a Winner” about adopting a winning mindset for sports people but equally applicable to anyone wanting to get more out of life.  See in this video how Jens Fudge created score cards as reports from archery competition results using FlexCel: If you feel like discovering more of the power of FlexCel, Jens informed us that he was involved in setting up a one hour webinar for the Danish Delphi user group in March. So, stay tuned, as soon as we have the final information on this webinar, we’ll inform so you can also register and attend this webinar! 

Read More

FNC Conversion Components in TMS Analytics & Physics 3.3

From version 3.3, TMS Analytics & Physics library contains several FNC components for converting math formulae and units of measurement to special text formats. In this article, we’ll consider how to do the conversion and how then use the converted strings in Delphi applications.  Let’s begin with formula converters: TFNCFormula2PlainConverter – converts a formula to plain text. TFNCFormula2TeXConverter – converts a formula to TeX format. The TFNCFormula2PlainConverter component has the following published properties: Formula (string) – a formula to convert. PlainFormula (string) – the formula in plain text format (read-only). Valid (boolean) – the formula is valid for conversion (read-only). Error (string) – description of the error if occurred during conversion (read-only). The component provides a very simple functionality: when the ‘Formula’ property changes, the value is converted to plain text format and assigned to the ‘PlainFormula’ property.  What is the plain text format and when it could be useful? Plain text format just presents a formula as a string using special Unicode characters to make it closer to natural math notation. For example, the formula ‘x^2’ can be written with the superscript symbol as ‘x2’. In the following picture, an example of such conversion is presented. Here we should note that not all formulae can be presented in this format. If a formula is not valid for the conversion, an error message will be shown with the ‘Error’ property. Now let’s use this converter to make a fine math application. In one of the previous articles, we explained how to use curve fitting FNC math components. In the following picture, we showed an example of data approximated with a Taylor series.   On the FNC chart, we showed the formula of the fitted curve in the legend. Let’s use the converter and improve the design of the application. We just need to write a small piece of code: procedure TForm1.ShowCurveLegend(const formula: string);begin  FNCFormula2PlainConverter1.Formula:= formula;  TMSFNCChart1.Series[1].LegendText:= FNCFormula2PlainConverter1.PlainFormula;end;procedure TForm1.FNCApproxFunction1D1FormulaChanged(Sender: TObject; const formula: string);begin  ShowCurveLegend(formula);end; When a formula of the approximated function is changed, we convert it to plain text format and show the formula on the chart. The resulting form is presented in the picture below. As one can see, the formula of the fitted curve looks like a natural math expression, without superfluous symbols, like power operator ‘^’ and indexing brackets ‘[]’. One more example of the curve, fitted with a Fourier series, is shown in the following picture.   The full source code of the demo project is available with the latest version of TMS Analytics & Physics library.  We can use the same approach to present units of measurement in the form of natural physics notation with the TFNCUnit2PlainConverter component. An example of such conversion is shown in the picture below.   The next component TFNCFormula2TeXConverter has similar functionality, but it converts formulae to TeX format. This format is not for human reading, so, we need a drawing library to display formulae in natural math notation. We’ll use the MathJax library, as described in this article, together with the TTMSFNCWebBrowser component. Here is a simple code for converting a formula to TeX format and showing it in the browser component: procedure TForm1.DrawFormula(const formula: string);var  texf, htmlcode: string;begin  FNCFormula2TeXConverter1.Formula:= formula;  texf:= FNCFormula2TeXConverter1.TeXFormula;  htmlcode:= GetTeXHTML(texf);  DrawTeXInBrowser(htmlcode);end; Thus, we have a simple application to display math formulae. An example of a […]

Read More

TMS FNC Chart Update 1.8

TMS FNC Chart is designed to display different kinds of data such as financial and marketing data, monthly business sales, graphical and math data and much more as a chart. This chart is almost fully customizable. Updated Editor In this new update the editor was changed to work as the other editors in other FNC products. The editor adapts to your theme, it changes according to the Light or Dark style of the IDE. It now has high DPI aware controls that look crisp in run-time and in design-time on Delphi 11 Alexandria.And the editor is available in Visual Studio Code. Works together with TMS Analytics & Physics The TMS Analytics & Physics library is a set of classes that provide functionality for building powerful math applications with Delphi. And you can visualize the data or formulas with the TMS FNC Chart. More information on TMS FNC Chart can be found on the product page.

Read More

Delphi is 27, happy birthday and welcome to the new generation

Happy Birthday Delphi It is meanwhile a regular. It is again February 14 and it is the birthday of Delphi. We celebrate today 27 years! Not including its predecessor Turbo Pascal, it’s for a whole generation of software developers already well over the half of a career that Delphi gives us professional satisfaction as well as bread on the table. But today, I wanted to devote this birthday of Delphi to the next generation. The new generation that is at the start of a new software development career. The new generation that discovers Delphi and is feeling enthusiasm and the new generation for which Delphi still is a valuable & productive tool to accomplish real-life software development tasks that has an impact on people’s lives. Enough said, read the article Stephanie Bracke, our intern this year at TMS software wrote herself or watch the video she made herself! See or read & be amazed about what Stephanie accomplished for Delphi apps that can change people’s lives, including people with disabilities. Bruno Stephanie.Introduce(‘Hello world’); When I first started my internship at TMS software, I felt overwhelmed and that still feels like an understatement, but luckily my mentor Bruno repeatedly told me ( and I needed to hear that every time as well ) that in order to be able to run, you should learn how to walk. To get started and prepare myself during the summer holidays, I was given a two book, the first by Marco Cantù and another by Holger Flick. to try to get myself familiar with the Delphi IDE and also the Object Pascal language.  My project For my first real assignment I was given an open source library called Annyang! And was the task was to study this library and turn this into an easy to use speech to text component for TMS WEB Core.  I feel like creating the TSpeechToText component with Annyang! Is like entering a rabbit hole, in school we learned the basics, but the deeper you go, the more there is to learn!  In short, I created a web application with TMS WEB Core and only one button that starts Annyang. But of course, you can start the engine automatically at application startup or in different ways, if you don’t like that button. You’re as free as a bird here! Once the button on my webpage is clicked, the device microphone gets activated (see red little icon the caption) in your browser and Annyang starts to listen to your command. I added a few commands, for example:  Start -> starts the camera Snap ->takes a picture Listen -> Annyang starts listening to sentences and adds it to the memo Once you activate the “Listen” command, Annyang will still listen to single word commands and execute those as a priority instead of adding the recognized words in a TWebMemo control, whenever that single word is used in a sentence, the entire sentence will be written down without execution of said command. There are also commands like zoom, reset, pause and resume but those are for you to find out in the demo!   The more time I spend using Annyang as a component the more I can think of ways to enhance it, there are just so many ways and possibilities of using this component that I can’t wait to see what […]

Read More

Check your overflows

This topic has concerned me forever, but an exploit I read about a month ago triggered me to finally write something. The exploit itself is fascinating, so in case you haven’t read about it, I’ll leave the link here: https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html But what can be so fascinating about a vulnerability?, I can hear you say. We find exploits every day in every product, don’t we? To what I have to answer, “yes, we do”. And, while not the focus of this post, that’s exactly the problem. The exploit This was an exploit in a JBIG2 library. JBIG2 is not designed to execute code, so it is not simple to make it execute code. It is not like a flaw in a PDF javascript implementation, where you get access to the javascript engine when you shouldn’t, and once you are in, you just execute commands. There is nothing to execute here. And yet… The exploit starts simple, with an overflow bug. Basically you sum some numbers, say like: MemoryToAllocate := Length(data1) + Length(data2); …AllocatedMemory := AllocateMemory(MemoryToAllocate); FillWithData(AllocatedMemory); But what happens if I maliciously create a file where Length(data1) is near the maximum an integer can hold and then add the length of data2? In most programming languages, what will happen is that the integer will overflow, so 2147483647 + 1 = -2147483648 And of course, since I have control over both lengths, I can create a file that allocates, say 2 bytes, and then tries to write 100 bytes into the allocated memory, corrupting the stack. And now it is where it gets interesting. We want to execute code, not to corrupt the stack, and as mentioned before JBIG2 doesn’t really execute any code. So how do we continue? Simple: We find out a way to emulate a NAND gate with the stack corruption, and then construct our own computer from those NAND gates, where we can execute any code we want. As the article says, it is not as performant as JavaScript, but it gets the job done. Now you can infect a phone just by sending it a message, without the user even having to click on anything.   The takeaway In computing, we always tend to forget about border conditions. Usually, that works fine: I mean, what are the odds that an integer overflows in day-to-day images? The JBIG2 code was probably correct for virtually 100% of naturally occurring JBIG2 files. But when you add someone maliciously trying to break your code, the situation changes. No matter how small a hole you leave on your wall, someone will use it and build a 6-lane highway to enter your place. Give them a small overflow, and they will make a whole computer out of NAND gates. And what can we do about it? First steps first: we should always stay vigilant, not just about how invalid data can break our program, but more important, how maliciously created, completely-unlikely-to-exist-in-the-real-world data can break our apps.  WE NEED TO ALWAYS CONSIDER HOW SOMEONE COULD MALICIOUSLY ATTACK OUR CODE. IT IS NOT ENOUGH WITH JUST MAKING SURE IT WORKS IN THE EXPECTED OR REASONABLE CASES But I firmly believe that staying vigilant is not enough. We are humans, after all, and humans make mistakes. So we need all the extra help we can get, […]

Read More

Add custom controls to your map with TMS FNC Maps for Delphi

ElementContainers is a major new feature in TMS FNC Maps v3.0. With ElementContainers you can add custom controls on top of the map. These custom controls consist of HTML and CSS elements. Interaction with the map and the application can be added by using Actions. At runtime the content of the ElementContainers can be updated dynamically through JavaScript. ElementContainers are independent of the mapping service which means they will look and function identically regardless of your preferred mapping service. A preview is automatically available at design-time to make editing the HTML/CSS elements as straightforward as possible. In this blog post I’ll demonstrate how easy it is to add a custom interactive zoom control to the map. The Basics Position the container anywhere on the map with the Position and Margin properties. We’ll place the container in the bottom left corner of the map: set Position to poBottomLeft. Add an item to the Actions collection of the ElementContainer to interact with the map. Select the ID from the element to interact with from the HTMLElementID dropdown list. In this case pick “customRange1” to interact with the slider control. Set Event to heCustom and CustomEvent to input to catch the input event of the slider control. Set EventReturnValue to rvValue to retrieve the updated value of the slider control. Assign the ElementAction’s OnExecute event to add an event handler. The updated slider control value is returned as a string in the AEventData.CustomData property. We can use this value to update the map’s zoom level with the code below: procedure TForm1.TMSFNCMaps1ElementContainers0Actions0Execute(Sender: TObject; AEventData: TTMSFNCMapsEventData); var f: Double; v: string; begin f := 0; v := StringReplace(AEventData.CustomData, ‘”‘, ”, [rfReplaceAll]); if TryStrToFloatDot(v, f) then TMSFNCMaps1.SetZoomLevel(f); end; Assign the TTMSFNCMaps’s OnZoomChanged event to interact with the ElementContainer. When the map’s zoom level changes, get the new zoom level and update the label and slider control in the ElementContainer. procedure TForm1.TMSFNCMaps1ZoomChanged(Sender: TObject; AEventData: TTMSFNCMapsEventData); begin TMSFNCMaps1.GetZoomLevel; end; procedure TForm1.TMSFNCMaps1GetZoomLevel(Sender: TObject; AZoomLevel: Double); begin TMSFNCMaps1.ExecuteJavaScript(‘document.getElementById(“customRange1”).value = ‘ + FloatToStrDot(AZoomLevel)); TMSFNCMaps1.ExecuteJavaScript(‘document.getElementById(“customZoom1″).innerText = ‘ + FloatToStrDot(Round(AZoomLevel))); end; The custom control is now ready to be used. The Styling Using Bootstrap is a straightforward way to improve the visuals of HTML elements. With a few adjustments Bootstrap styling can be added to ElementContainers. Include the Bootstrap CSS library via the HeadLinks collection.Add an item to the HeadLinks collection; set Kind to mlkLink, URL to “https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css” and Rel to “stylesheet”. Add Bootstrap HTML classes to the ElementContainer’s HTML. Change the HTML value to: Zoom Level 12 Then set HTMLElementClassName to “card” and UseDefaulStyle to “False”. Suddenly the custom control looks a lot prettier. Notice that the ElementContainer’s content with Bootstrap styling is fully visible at design-time as well. Because ElementContainers are completely independent from the mapping service, the result looks exactly the same even when switching to a different service. The screenshot below shows the same ElementContainer with Service set to msHere. The Code Of course, the same result can also be achieved in code. procedure TForm1.FormCreate(Sender: TObject); var ElementContainer: TTMSFNCMapsElementContainer; ElementAction: TTMSFNCMapsElementAction; html: TStringList; begin TMSFNCMaps1.ClearElementContainers; TMSFNCMaps1.ClearHeadLinks; TMSFNCMaps1.BeginUpdate; TMSFNCMaps1.AddHeadLink(‘https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css’, mlkLink, ‘stylesheet’); html := TStringList.Create; html.Add(” + ‘Zoom Level ‘ + ’12’ +’ ‘ +’ ‘ +’ ‘ +”); ElementContainer := TMSFNCMaps1.AddElementContainer(html); ElementContainer.HTMLElementClassName := ‘card’; ElementContainer.Position := poBottomRight; ElementContainer.Margins.Bottom := 15; ElementContainer.UseDefaultStyle := False; ElementAction := ElementContainer.AddAction(‘customRange1’, heCustom); ElementAction.CustomEvent := ‘input’; […]

Read More