Recently I had the need to create a styled FMX Delphi component. I had thought about that earlier, as I’m quite skilled at creating VCL components. FMX components are quite another matter though, and the fact that you need to take the style definition into account had just made things cumbersome and a bit awkward, I thought.
But then I googled the subject and found an article by Andrea Magni, an Italian Delphi coder, I think rather well known nowadays. He is the author of the Frame Stand component and often presents his stuff on the Embarcadero Code Rage events.
He described a technique to create the style part of the component using an ordinary FMX form. As it turns it, the resource code created by the IDE is very similar to the style resource code created by the style editor.
His article at http://blog.delphiedintorni.it/2013/11/tgmaillabel-un-esempio-di-custom.html explains this very well. You’ll just have to translate it into a language you understand, as it is in Italian (if that’s not a language you speak, that is).
But, for me at least, there was a couple of items of information missing, possibly lost in translation and a few broken links, so I thought I’d mention these things here.
As Andrea explains, when you’ve added all the components (TTexts, layouts, images or whatever you need), you merely Alt+F12 into the .fmx file and copy these definitions out. But the first thing that was unclear to me was that you should start with a TLayout that wraps everything else up. You should only copy the starter TLayout and all the components you’ve placed on it. Put all that in a text file that you call <componentName>.style.
Once you have that file open in a text editor, remove all the object names. The object name of an object in the .FMX file comes after the object keyword and before the colon.
Size.PlatformDefault = False end object ProductView: TVertScrollBox Align = Client
Remove the name and the colon.
Once all the names are gone, you should add the names of each component in the way that Delphi likes them. Add the property StyleName to the text.
Size.PlatformDefault = False end object TVertScrollBox StyleName = 'ProductViewStyle' Align = Client
What you choose to name each component doesn’t really matters, but you will be using these names to locate the style components in your code later on.
The next, and last, unclear thing were how some of the methods of the component code interacted with the style.
How the ApplyStyle method worked wasn’t clear after reading the article, perhaps because the link to the source code was broken (I found that at http://www.fmxexpress.com/wp-content/uploads/2014/01/GMailLabelComponent.zip after a little bit of googling).
As I understand it, the ApplyStyle basically looks for the objects created by the RTTL (or some other guy deep within Delphi) and returns the object to you. You should store this in a class variable and only free it in the FreeStyle method (and make sure that you do free it there).
procedure TPinteraProductPanel.ApplyStyle; begin inherited; if not Assigned( FProductRectangle ) then FProductRectangle := FindStyleResource( 'ProductRectangleStyle' ) as TRectangle; if Assigned( FProductRectangle ) then begin FProductRectangle.OnClick := OnClickHandler; end; if not Assigned( FTitleText ) then FTitleText := FindStyleResource( TitleStyle ) as TText; if Assigned( FTitleText ) then FTitleText.Text := FTitle;
The above snippet of code is not the complete ApplyStyle, but it shows you the gist of it. First, I call whatever inherited code there are.
Next, I get the rectangle object that covers the complete component (in my case) just to enable OnClick. This may not be needed or could be done another way, but this was the way I got it to work.
Thirdly, I look up the TText that I named FTitleText in the .style file and assigns it the value of FTitle (which is a string holding whatever value Title should be).
The FreeStyle simply frees all the objects I’ve retrieved in the ApplyStyle method, like so:
procedure TPinteraProductPanel.FreeStyle; begin inherited; FProductRectangle := nil;
Forgetting to free all those objects actually got me into a bit of trouble, so make sure that all the objects are freed (or nilled as it were).
Well, that’s it. With Andrea’s article and these additions you should be all set and should be able to whip up a styled FMX component in about half an hour or so (depending of course of the complexity of the component you’re trying to create).
Also, Andreas example of the Gmail label component I linked to above should help you out pretty nicely.
This is the code of my Product control. It won’t compile, there are some libs missing, but it might help you create your first styled FMX component.