Cape Cod Gunny - Michael Riley
Husband, Father, Grandfather, U.S. Marine Corps Gunnery Sergeant (Retired), Software Artisan, Storyteller, Toastmaster, and Author (in progress) #capecodgunny #pilotlight #enlightment #delphi
Monday, June 2, 2025
The First Time I Met My Guardian Angel
Sunday, May 11, 2025
Delphi Tip of the Day: A Better Way to Center Modal Forms
Yesterday, I was going through some final aesthetic checks on my FMX desktop software application. I have two modal forms that popup up during click events. One is help about which I set to screen center. And the other contains code that centers the form on it's parent window.
I was testing the behavior of this form toggling between light and dark themes. I noticed that with light theme the window just appears but with the dark theme I could see the window move it's way from the top of the screen to it's centered position and then switch to dark.
In the OnShow event handler I was calculating Left and Top like I have always done to center the window. This was the first time I'd ever seen the window reposition itself. This is the first time I'd ever used a dark theme. And, this is the first major application I'd written with FMX.
Left := ParentForm.Left + (ParentForm.Width - Self.Width) div 2; Top := ParentForm.Top + (ParentForm.Height - Self.Height) div 2;To say the least, I was annoyed by this split second flash centering itself on the parent window. I tried all kinds of stuff to minimize this flash. Nothing work.
![]() |
FMX Form Position Property |
![]() |
VCL Form Position Property |
DocWiki Links:
Saturday, May 3, 2025
Delphi DOH! of the Day: Hardcoded Paths in TFDConnection.Params
//----------------------------------------------------------------------- // Build user paths //----------------------------------------------------------------------- ProgDataPath := IncludeTrailingPathDelimiter( TPath.GetHomePath) + VendorName + PathDelim + AppName; Database := ProgDataPath + PathDelim + DatabaseName;This works great. It allows me to test both Windows and MacOS. In addition, I can easily test this on non-development machines by making sure I put the SQLite database file in the corresponding Application Path. It lets me simulate how everything would work if the application had been installed using an installer.
I wrapped exception logic inside OnCreate event handlers.
"I may not be the brightest bulb on the tree..."
begin Application.Initialize; Application.CreateForm(TdmImages, dmImages); Application.CreateForm(TdmSQLite, dmSQLite); Application.CreateForm(TfMain, fMain); Application.Run; end.
- There's nothing SQLite related in the dmImages data module.
- It's not getting to fMain.
- It must be dmSQLite.
Explanation from ChatGPT:
- Delphi loads the .dfm or .fmx file and instantiates all the components declared within it.
- This includes setting all published properties like FDConnection.Params, FDQuery1.Connection, Button1.text, etc.
- This happens before the OnCreate event fires.
- After all components are created and their published properties are set, OnCreate is triggered.
🛠 Your Specific Case
If TFDConnection.Params had hardcoded values (e.g. a file path or server name that doesn't exist on the test machine), they were already applied before OnCreate — meaning the connection could already try to auto-connect or be used by another component, causing a crash.
- 80 miles an hour is faster than 100 miles an hour. When you rush you make mistakes.
- Published Properties inside .dfm and .fmx files are set before any corresponding OnCreate event handlers.
- Make it a priority to View forms and data modules as text when troubleshooting.
- Remember Occams Razor: "The simplest explanation is usually the best one."
Thursday, March 13, 2025
Delphi FMX Air.Style Missing 'scrollboxstyle' Definition
I've been upgrading my flagship software product Zilch, from Delphi 5 VCL to Delphi 11 FMX. I'm finally in the report development phase. I'm using the FMX version of FastReports.
Things have been going along quite well, other than the typical stumbling around, which happens when learning the ins and outs of a new component suite (FastReports).
Back in May 2024, I decided to implement a dark theme after watching Ian Barker's presentation called "The fundamental secrets of good UI design". https://www.youtube.com/live/TL2YVio_eTo
During this presentation Barker pleads with the audience to include a dark theme option because it makes life much easier for people like him. Those who suffer with severe cataracts.
I am very meticulous about my work. Borderline obsessive. After spending nearly 4 weeks creating, tweaking, previewing, re-tweaking a report I finally decided to see what it looks like in dark mode. That's when I got hit with an access violation.
My first reaction was WTF! 😡
FMX.StdCtrls |
I spent 3 months or more back in May 2024 testing and trying several different FMX styles. I finally settled on the Air.Style after making several customizations. And now this happens. Just when I thought I was getting close to wrapping up this project. WTF! 😡
Inside my application I'm using the StyleManager. I call:
TStyleManager.SetStyleFromFile( <FullFilePath> )
<FullFilePath> is the full file path of the modified version of Air.Style I'm using inside my program. I remember trying Dark.Style early on but I didn't like the brownish-copper glow effect so I opted for the Air.Style.
I quickly tried setting the <FullFilePath> to Dark.Style and tested it again, IT WORKED! 😎
Okay, so there is something different between Air.Style and Dark.Style. I searched both .STYLE files looking for "TScrollBar".
It turns out that Air.Style is missing the definition for StyleName = 'scrollboxstyle'.
I copied the complete 'scrollboxstyle' definition from Dark.Style and pasted it inside Air.Style and IT WORKED!
![]() |
Payoff Savings Report - Air.Style |
I'm glad this was a quick fix. Here is the complete 'scrollboxstyle' definition for anyone that would like to modify the Air.Style so it works with FastReports.
object TLayout StyleName = 'scrollboxstyle' DesignVisible = False Height = 131.000000000000000000 Position.X = 254.000000000000000000 Position.Y = 435.000000000000000000 Width = 334.000000000000000000 object TLayout StyleName = 'background' Align = Contents Locked = True Height = 131.000000000000000000 Width = 334.000000000000000000 object TLayout StyleName = 'content' Align = Client Height = 115.000000000000000000 Width = 318.000000000000000000 end object TScrollBar StyleName = 'vscrollbar' Align = Right Height = 115.000000000000000000 Orientation = Vertical Position.X = 318.000000000000000000 Width = 16.000000000000000000 end object TScrollBar StyleName = 'hscrollbar' Align = Bottom Height = 16.000000000000000000 Orientation = Horizontal Position.Y = 115.000000000000000000 Width = 334.000000000000000000 end object TSmallScrollBar StyleName = 'vsmallscrollbar' Align = Right Height = 8.000000000000000000 Orientation = Vertical Margins.Left = 2.000000000000000000 Position.X = 99.000000000000000000 Position.Y = 2.000000000000000000 Visible = False Width = 8.000000000000000000 end object TSmallScrollBar StyleName = 'hsmallscrollbar' Align = Bottom Height = 8.000000000000000000 Orientation = Horizontal Margins.Top = 2.000000000000000000 Position.X = 2.000000000000000000 Position.Y = 113.000000000000000000 Visible = False Width = 150.000000000000000000 end object TLayout Align = Contents Height = 131.000000000000000000 Width = 334.000000000000000000 object TLayout Align = Bottom Height = 20.000000000000000000 Position.Y = 111.000000000000000000 Width = 334.000000000000000000 object TSizeGrip StyleName = 'sizegrip' Align = Right Locked = True Height = 20.000000000000000000 Position.X = 314.000000000000000000 Width = 20.000000000000000000 end end end end end
Update: March 16, 2025
I'll have to give the new Delph 12.3 command-line style converter tool (vsf2fm.exe) a try. Hat Tip to Ray Konopka for pointing me in this direction.
I just installed Delphi 12.3 and used the vsf2fm.exe command-line tool and converted the Carbon.vsf to Carbon.style and it works perfectly.
Sunday, February 16, 2025
Delphi Tip of the Day: FMX FastReport Text Object (TfrxMemoView)
- Bold
- Italic
- Bold and Italic
- Superscript
- Subscript
- Color
Name | Color | HEX Code |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Semper Fi
Gunny Mike
Thursday, January 2, 2025
Tip of the Day - Everyday is an Etch-A-Sketch
Sometimes all you need is a little motivation.
Everyday is an Etch-A-Sketch.
Sometimes, every hour is an Etch-A-Sketch.
And sometimes, every minute is an Etch-A-Sketch.
Friday, December 27, 2024
I Got Complacent—and Here’s What I Learned
The Frog in the Beaker Parable:
If a frog is placed in a beaker of boiling water, it will immediately jump out to save itself. However, if the frog is placed in a beaker of lukewarm water that is slowly heated, the frog will remain in the water, not noticing the gradual rise in temperature. Eventually, the water will reach a boiling point, and the frog will perish because it failed to react to the slow, incremental change.
Moral of the Story:
The parable serves as a warning against complacency and the failure to act in the face of slow, incremental changes that can lead to disastrous outcomes. It’s a lesson often applied in business, personal life, or societal contexts, emphasizing the importance of staying vigilant, recognizing warning signs, and taking proactive steps to prevent negative outcomes.
My Story:
I spent most of 2024 in a beaker of lukewarm water. If I'm honest with myself, it probably started in sometime in 2023. Perhaps even earlier than that. I had gotten complacent. I was totally unaware it was happening to me.
The first sign I realized something was wrong is when my July 2024 software payment from MyCommerce/Digital River was late. This had happened once before in October 2023. A quick email to support was all that was required. So, I sent off an email. I received a response saying they had put a new ticket system in place. I created an account and opened a ticket. And...crickets. 🦗
August turned into September, which turned into October. And now I'm missing July, August, and September payments.
It was October and I started thinking about some of the other Delphi products I have purchased in the past and the user buying experience. I even sent Ray Konopka an email asking him what shopping cart system he put in place on https://www.raize.com/. Ray was gracious with his time and quickly responded.
It was at that point I realized this was not going to be a weekend just project. I also realized just how widespread the Digital River/MyCommerce/Share-It situation was. I wasn't the only one. 👇😓
https://www.theregister.com/2024/10/15/digital_river_runs_dry_hasnt/
The solution I wanted was a Merchant of Record (MOR). I wanted someone else to handle all the interactions with customers. I just wanted to put links on my website to a shopping cart page.
Complacency Turned Into a Rabbit Hole 🐇🕳
I narrowed down my search to two MORs; FastSpring and Paddle. I crunched the numbers and decided to go with Paddle. I created an account with Paddle and submitted my website for verification.
Your Website Has Been DENIED!
My website was denied with no specifics other than it did not meet Paddle's standards. So, I signed up with FastSpring. I was also denied by FastSpring.
Turns out that I did not have the adequate GDPR processes in place. I needed to severely update my website. I need to add a Consent Banner and all the necessary webpages; Terms of Service, Privacy Policy, Cookie Policy.
The Consent Banner. Oh yeah that little popup thingy that lets visitors accept which cookies they want to allow. And one of those cookies is Google Analytics.
This lead me down the path of implementing Google Tag Manager. I ignored all the warning messages Google Analytics had bee showing me about the change to GTM.
I'm a do it yourself kind of guy so I was looking for a "do it yourself consent banner." I settled on Klaro https://github.com/klaro-org
So I spent three whole weekends implementing Google Tag Manager, Klaro, and updating my website to interact with the new consent banner.
I added the three necessary webpages; Terms of Service, Privacy Policy, Cookie Policy and resubmitted to both Paddle and FastSpring. It took about a week to 10 days but I was now APPROVED!
Paddle
I started looking around the back-end in Paddle for how to set up a shopping cart with a download button. After several hours of reading the documentation I gave up. I sent an email to my sales rep asking for help. After several back and forth emails, it turns out that what I needed was "Paddle Classic" (a completely different system) from Paddle Billing. I gave up and switched over to FastSpring.
FastSpring
I found FastSpring to be very intuitive. And of course I was thoroughly testing all the pieces. I found a flaw in the "Invoice Email" which directly affects the download link. Unfortunately you cannot modify the email templates until your go live. The process of going live took another week to 10 days.
I finally got everything in place and ready to go just after Thanksgiving.
SEO vs AEO (Ask Engine Optimization)
Is Search Engine Optimization (SEO) dead? Maybe? Maybe not? Read this post from Dave Collins at Software Promotions. https://www.softwarepromotions.com/news/seo-is-dead-again/
I also discovered https://www.perplexity.ai/ The first question I asked Perplexity was "Who are ZilchWork's direct competitors?"
I also found this fantastic website, Answer Socrates https://answersocrates.com/
Zilch - Complacent For Almost 7 Years
I haven't just been complacent, I've been asleep at the wheel. I've enjoyed a software product with a funny name "Zilch" for years. I noticed my sales have been steadily declining. I just assumed it was do to the look and feel of my current desktop software begin stuck in the 640 X 480 pixel mode. Wrong!
What I failed to notice was a modern product called Zilch was taking the world by storm. Zilch launched in 2018 (that's almost 7 years ago). It's not for paying off debt like my software... it's for buying products. It puts people in direct contact with products without using credit cards.
Hopefully you can lean from some of my mistakes.
Use the comments and share how you have been complacent!
Enjoy!
Semper Fi
Gunny Mike
https://www.zilchworks.com