Last week I posted a tip on my blog, on organizing product dependencies in your Delphi projects for Windows. This week I’ll be giving you a cross platform alternative to that technique, and giving you a free component to make it possible.
[Note, see comments for some known bugs in the FormResource component]
When faced with the problem of including dependencies within an executable, and in a cross-platform way, I knew that I’d faced this problem before. Back when I wrote a mini-series on my blog about building a sprite engine in Delphi, I’d demonstrated how to include the image resources for a game project into your Delphi project using a component to store the data within a form. I’d also built an IDE plugin which allowed you to insert your image data hierarchically into a component on a form.
Over the past two or three days I’ve been adjusting the code from my sprite engine, to create a component named “TFormResource”. This component allows you to store just about any kind of data within a form or module in your Delphi project. Not only that, but because the component is non-visual, it should function on any supported target platform, even within a WebModule for example.
So let me take you on a brief tour of the FormResource component, and show you how you can use it to organize dependencies for your project. Before we begin however, the obligatory disclaimer:
The Form Resource component and associated IDE extensions are provided AS-IS without any warranty or implied fitness for any purpose. These components are provided in source code form, for you to compile and use as you see fit. These components are provided without support. These components are provided without agreement of liability of any kind. I will not be held responsible for any damages caused by your use or misuse of these components.
Okay, that said, lets take a look at the component. Later in this post I’ll include installation instructions for the Form Resource component and it’s IDE extension, and for now I’ll assume either that you looked ahead and installed them already, or that you’d rather read about what they do first…
Go ahead and start a new project. It does not matter if this is a multi-device project, or a vcl project. Nor does it matter if it is a UI application or server module, but for now, lets stick with a UI application for simplicity. I’ll be creating a new multi-device application with a blank form..
Now drop a TFormResource component onto your main form:
Now right click the component and select “Show Editor”
You should be presented with an editor which looks a little like this…
What you’re looking at here is the root directory of a virtual file system, which is stored in the same data stream as the properties of the application form. For example, if you were to place a TEdit component on your form and set the ‘Text’ property to “Type Here”, where is the string “Type Here” stored? Well, Delphi streams that into a dedicated part of your application executable (the technical details of which vary among the target platforms). This TFormResource component will stream any data within the virtual file system to that same place.
So lets see FormResource in action. Click on the “ROOT” directory to ensure it is selected, and then click the little “+” icon at the top of the dialog. (Alternatively right click the selected “ROOT” directory and select “Add” from the context menu)…
In the dialog which appears, leave the drop down box on “Directory” and enter “SQL” into the edit box for a name…
When you click on Okay, your new “SQL” directory will appear beneath the “ROOT” directory..
Now click on your “SQL” directory to make sure it is selected, and again click the “Add” button at the top.
This time, add a “SQL Script” named ‘test.sql’, like this…
Now when you click okay, you’ll have a ‘test.sql’ file in your virtual file system. (* Note, you may need to expand the SQL directory manually, I’d planned to make it do that automatically, but that feature didn’t make it in yet, at the time of writing this. *)
If you haven’t done so already, click to select the test.sql item and note that the right side of this dialog has become a text editor. This editor is a syntax highlighting editor into which you can type your SQL statement. (It’s the synedit component for anyone that is wondering)
Type in a sql statement, for example “Insert into sometable (x,y) values (‘testA’,’testB’);”
You’ll notice that the SQL is highlighted, though you may not appreciate the color scheme as reserved words are simply made bold. At this time, there is no way to alter the syntax highlighting options for the variety of supported text files in this editor. That is planned for a future version, so watch this space for the enhancement 😀
Anyhow, go ahead and close the window, and you’ll find yourself back on your application form. Looking back at the screen shot above you can see that the path to your SQL statement is “ROOT/SQL/test.sql” and we’ll need this information in a moment.
Drop a TMemo on your form, and a TButton. We’re going to write a piece of code to copy the SQL from our FormStorage component into a memo on the form, and we’ll write this code in the TButton OnClick event handler. Go ahead and set the OnClick handler to the following…
procedure TForm1.Button1Click(Sender: TObject); var MS: TMemoryStream; begin MS := TMemoryStream.Create; try FormResource1.Resource['ROOT/SQL/test.sql'].SaveToStream(MS); MS.Position := 0; Memo1.Lines.LoadFromStream(MS); finally MS.DisposeOf; end; end;
Now, before you can build and run the project you need to add the FormResource lib directory to your search path.
Head into the menu “Project / Options” and then drop the “Target” box to “All Configurations”…
On the left, make sure “Delphi Compiler” is selected, and then set the “Search Path” option to the location of the lib directory for your copy of FormResource. (If you’re not sure where that is, revisit the installation notes, on my system the path is “D:\DigitalEnvy\public\formresource\out\lib”) Extend the path with “\$(Platform)\$(Config)” so that the project will compile for any target for which you’ve compiled FormResource.
Now run your application and click the button, you should see something like this…
Congratulations, you just loaded a SQL statement into your project from the FormResource virtual file system, built right into your application executable so there’s no need to distribute additional .sql files.
But that’s not all!
The FormResource component is not exclusively for including SQL files for a start, in fact, you can store any type of file within the FormResource component, text or binary. This means you can include HTML files for example, or PNG image files. Syntax highlighting is supported for many text file formats, but even text files for which there is not a syntax highlighter can be stored as simply “Text File”, take another look at the dialog that is presented when you click the “Add” button in the FormResource editor…
In the screenshot you can see “Text File” immediately beneath the “Directory” option, and then if you scroll down the list you’ll find some 57 text formats for which syntax highlighting is supported, including JSON, XML, HTML, SQL, Pascal, C++ and so on. Beyond the text formats however, you’ll come across “Binary File”…
You’ll also notice support for four image file formats, GIF, JPEG, PNG, and Bitmap, we’ll come to those in a moment, but first, go ahead and add a binary file to your project. I named mine “test.exe”…
Select your binary file and on the right pane you’ll see “0 bytes loaded” beneath a File menu.
From that File menu select “Import”, and select any file from your disk. (I selected C:\Windows\Notepad.exe)…
I now have some 243,200 bytes loaded into my ‘test.exe’ file, the entire notepad executable has been loaded in for me and will be stored as part of my application form.
The very same code which was used to read the SQL file, with the path altered to “ROOT/test.exe” will also read this executable, however, the executable is binary data and therefore will be displayed as random ascii junk…
Never the less, the data is there and can be accessed using a simple TStream, which means you could easily write the file from your form back out to disk. Therefore, you could use this to build a rudimentary installation application, which deploys the .dll files required by the application at run time. Or perhaps you have some other data you’d like to inject into your application?
There’s also images…
Just as we added a “Binary File” above, we can also add one of the following image formats “PNG, GIF, JPEG, BMP”, and the FormResource component editor knows how to display those for you…
Note, currently the image display pane does not scale the image, and therefore this image is stretched too large to be viewed in fully within the editor. I plan to correct this in a future update.
Other Functions (Import, Export, Load, Save, etc)
As you may have noticed, for each asset we add to the Form Resource component, on the right hand pane there is a File menu to allow importing and exporting that resource. There are also some additional buttons in the strip above the directory browser…
These buttons in order left to right are…
- Load – This allows you to load a previously saved virtual file system into Form Resource from an external file.
- Save – This allows you to save your entire virtual file system from Form Resource to an external file.
- Add – Adds a new item as a child of the selected item in the directory browser.
- Remove – Removes the selected item from the directory browser (including children).
- Move Up – Move the selected item up relative to it’s siblings within it’s parent directory.
- Move Down – Move the selected item down relative to it’s siblings within it’s parent directory.
Warning on data size.
This component has some good uses for isolating assets from your source code, however, that comes at a cost. Each time your form loads, it must load all of the resources into the Form Resource component. This could increase load times for your form within the running application, as well as within the IDE. Be sure not to overload a form with too much data.
More to come…
There are a number of features that I would like to add to this component. At this time I can’t make a commitment to do so, because I simply don’t know that I’ll have the time. This code is entirely open however and so you are welcome to update or alter it as you see fit. Perhaps you’d like to add features and submit the delta to me for inclusion?
Assuming I get time to add features, here are some of the features I’d like to add..
- Enhance the directory browser to be a little more intuitive.
- Display images correctly scaled.
- Encrypt data as it’s saved to the form.
- Provide options for the syntax highlighters
- Add the ability to launch external editing tools for various file types. (i.e. Photoshop/Gimp for images)
- Dynamic loading – Is it possible to load only the asset I need when I need it at runtime?
I hope this component is useful to you, and if it is, I ask for nothing in return except that you consider sending me an email with the subject “Thanks for FormResource” to craig [dot] chapman [at] embarcadero [dot] com.
Stay tuned for the installation instructions, otherwise,
Thanks for reading.
Installing Form Resource
Note: FormResource has been tested to install correctly under RAD Studio 10.2 Tokyo.
It should install without issue in at least RAD Studio, Delphi, C++ Builder of versions 10.1 Berlin and 10.2 Tokyo, your success with other versions may vary. I’d appreciate a comment on this post if you try it on other versions with success, or a note about any error messages given should it fail.
Installing Form Resource (Step 1) – Install SynEdit
From the RAD IDE, go to “Tools / Get It” and type “SynEdit” into the search box which is presented:
Click install and follow prompts to install SynEdit.
Installing Form Resource (Step 2) – Obtain source code.
Download the source code here: formresource
The source code for Form Resource is in my public subversion directory at: svn://public.chapmanworld.com/public/formresource You will need a subversion client in order to download it. If you’re not sure how to use a subversion client, I’d suggest you consider installing TortoiseSVN and doing a little reading online to see how to use it.
Once you have the source code, the directory will look a little like this:
Installing Form Resource (Step 3) – Build Packages.
Within the directory “formresource/src” you’ll find a project group named “grpFormResource.group”
Open the group and you’ll see two package projects:
Right click on “formresource.bpl” and select “Build”
When the package has built, expand the formresource.bpl tree item, and within that the “Target Platforms (xxx)” item, and double click on another target (i.e. 64-bit Windows) to set it as the default target. Again, right click “formresource.bpl” and select “Build”
Repeat this for each target platform that you intend use with FormResource.
When you have built all of your desired target platforms, switch back to the “32-bit Windows” target and then right click the “formresource.bpl” item and select “Install” – If all goes well you should see the following dialog.
Now right click on the package named “formresourceDesign.bpl” and select “Build” followed by right clicking and selecting “Install”…
You should see the following dialog.
Congratulations, Form Resource is now installed.