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 ServicePrivacy PolicyCookie 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)

Last week I discovered a few things.

I have found myself using ChatGPT more than Google when I want answers. Real answers. And last week I learned about Ask Engine Optimization (AEO). 

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

Saturday, September 14, 2024

Delphi Tip of the Day: The Delphi Magazine Total Collection

I'm always looking for ways to improve my Delphi skills. Sometimes, this takes me down a rabbit hole. And each time, these little side trips never answer "Yes" to the question "Will this help me ship?"  

Last week I went down the "global variables are bad" rabbit hole. 🐇🕳

Global Variables Are Bad

I opened my copy of "The Delphi Magazine Total Collection" looking for some inspiration. And, I found a 6 Part series called "Effective Delphi Class Engineering" written by David Baer. I'm slowly working my way through these articles.

Issue: 57 Effective Delphi Class Engineering 1:
Crossing The Chasm


David Baer kicks off a new series of articles aimed at all of us who are reluctant, confused or ill-informed on what object-oriented development is all about. The goal is to demonstrate, clearly and without jargon-loaded obfuscation, how to design, create and use Delphi classes to make your development more productive.
Issue: 59 Effective Delphi Class Engineering 2:
Welcome To The Machine


David Baer continues his series on practical object orientation by putting Delphi’s object machinery under a magnifying glass. He examines topics such as memory management, method calling, protocols and other compiler- related issues.
Issue: 60 Effective Delphi Class Engineering 3:
Skyrocketing Property


David Baer thinks properties are wonderful and this month gives us insights and advice on how they can best be put to use in our classes.
Issue: 62 Effective Delphi Class Engineering Part 4:
The TObject Of My


David Baer focuses on inheritance in this part of his popular series on object oriented development in Delphi.
Issue: 63 Effective Delphi Class Engineering Part 5:
You Are TEgg Man... I AM TWalrus


David Baer has not gone mad (though he may have been listening to too many old Beatles albums!): this instalment of his series continues his practical real-world discussion of polymorphism and inheritance.
Issue: 65 Effective Delphi Class Engineering Part 6:
To Talk Of Many Things


David Baer concludes his series on developing Delphi classes with a miscellany of sound advice, ranging from events to exceptions, RTTI and message handling.



Part 1 of Baer's series of articles, refenced short paper written by Marco Cantu called "When RAD is bad", which I found it on the internet archive. 

https://web.archive.org/web/20001120081900/http://community.borland.com/devnews/article/1,1714,10463,00.html  

But that's not all I found. I found a download link to the entire "The Delphi Magazine Total Collection Issues 1 - 139 (April 1995 to March 2007)"

https://archive.org/details/the-delphi-magazine-total-collection


Enjoy,
Semper Fi
Gunny Mike
https:\\zilchworks.com

Thursday, September 12, 2024

Sell Me This Pen!

OMG! I wish I had known this years ago. The Marine Corps taught me the Xerox Personal Selling Skills 3 (PSS3 = Needs Satisfaction) method. They turned me into a "regurgitator". If I had seen this video in 1994, it would have made a HUGE difference.



Show Me! Don't Tell Me!

HaveDemand your mentor model
the sales behavior for you!


Enjoy!
Semper Fi,
Gunny Mike
https:\\zilchworks.com


Sunday, September 1, 2024

Delphi Tip of the Day: How to Keep Your Code Folded in Delphi 12

I like the "Code Folding" feature of  Delphi. However, I noticed that every time I reopened a project in Delphi 12 where I had previously folded the code, the code was no longer folded.

To keep your code folded in Delphi 12 you need to turn on the Save project desktop when closing option inside the IDE.

Tools > Options > IDE > Saving and Recovering

This option is unchecked in the default, out-of-the-box setup.


Delphi 12 also includes a new feature called Save editor state when closing a tab any time
https://docwiki.embarcadero.com/RADStudio/Athens/en/Saving_and_Recovering

Save editor state when closing a tab any time When selected, the current state for the views is saved before closing it. State info includes collapsed regions, cursor/caret position, and bookmarks.

This allows you to close and reopen a tab within the same editing session, and when the tab is reopened it will display exactly as it was when it was closed. This is similar to the Save project desktop when closing setting but functions all the time, not just when closing and reopening a whole project.

This option can only be enabled when Save project desktop when closing is checked.

Let me know in the comments what other out-of-the-box tweaks you like to make to a brand new Delphi install.

Enjoy!
Semper Fi,
Gunny Mike
https://zilchworks.com


Saturday, July 13, 2024

Delphi Tip of the Day: Always Use the MenuBar for FMX Desktop Applications

A couple months ago, I watch the video replay "The fundamental secrets of good UI design" done by Ian Barker. Around the 33:15 mark, Barker talks about supporting "dark mode", have a listen:

Transcript:

"One of the things you really should do at a very bare minimum if you do nothing else please support dark mode. And this is kind of a personal beg from me. As I said before I do get these floaters in my eyes, I can see perfectly well you know, I'm not blind or anything like that. I'm shortsighted which is why I have glasses but if you support dark mode you will make my life a lot easier. And other people that have visual  issues as well some people get migraines and things like that dark mode helps."

https://www.youtube.com/live/TL2YVio_eTo?si=GUzsPoZriiIdyfbj&t=1995

I never considered supporting dark mode

Until I watched this video, I never considered supporting dark mode in the current rewrite of my Zilch software. So I began looking into how to incorporate FMX styles. It was confusing at first. Then I got the hang of it. I decided to go with the "Air.Style" that comes with Delphi.

David Cornenelius' book "Fearless Cross-Platform Development with Delphi" and Andrea Magni's book "Delphi GUI Programming with Delphi" were big helps understanding FMX styles.

There were a couple of tweaks I had to make. The Air.Style is a vector style which means it does not use the bitmap designer. It is similar to how Cascading Style Sheets are used in web development. The graphic elements are drawn using SVG paths. 

FMX Main Menu component can't be styled 

The biggest surprise was the TMainMenu component. It turns out the FMX Main Menu component can't be styled. The Embarcadero FMX Style Viewer was showing a Main Menu that was styled how come my Main Menu wasn't styled?

fmx-style-viewer-air
FMX Style Viewer - Air.Style

I didn't want my application to have some stuff styled and some stuff not styled. Then I discovered FMX includes a MenuBar component which does take styling. And that is what is used by the FMX Style Viewer. So, I slowly and methodically swapped out the MainMenu component for the MenuBar component.

Always use the MenuBar for FMX desktop applications


FMX MainMenu vs MenuBar

My recommendation is to skip using the MainMenu component when developing FMX desktop applications and ALWAYS use the MenuBar component.

You will be happy. Your customers will be happy.

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com




Sunday, March 24, 2024

FastReport VCL & FMX Comparison (Embarcadero Edition)

Disclaimer: This post contains affiliate links, which means I may earn a small commission if you click through and make a purchase, at no extra cost to you. Your support helps keep this blog running – thank you!

The upgrade of my flagship product from Delphi 5 VCL to Delphi 11.3 FMX is finally at the presentation stage. I've spent the last six weeks thinking about and learning about data visualization. 


I took a few classes on LinkedIn Learning about data viz, and I re-watched Ray Konopka's excellent video on Data Visualization using Delphi. Seeing is Believing - Data Visualization in Multi-Device Apps. Ray has also made the source code for his demonstration available at https://delphibydesign.com/downloads/ Thank you Ray!

I've never used FastReport before. My current Delphi 5 VCL product uses QuickReports. I did find a great FastReport video available through Embarcadero Academy called Getting Started with FastReport by Cary Jensen. Jensen mainly focuses on the VCL version of FastReport. 

I've never used FastReport before 

I was surprised at the huge difference between the VCL and FMX versions of the FastReport Embarcadero Editions. That's probably why Jensen focused on the VCL version in his video. These are the palette entries for Delphi 11.3 Professional. (VCL on the left, FMX on the right)

I'm interested in the FMX version of FastReport because I'm developing a desktop software product which targets Windows and macOS users. Because I'm new to FastReport, I want to see how far I can take the "Embarcadero" version of FastReport before I commit to purchasing the full version.

Unfortunately, the Embarcadero Edition of FMX FastReport has no export capability. See the Palette image above.

I was surprised at the huge difference between the VCL and FMX versions

Because I'm targeting both Windows and macOS users I need to know if there are any stark differences between those platforms. I created a comparison chart which highlights these differences. This is the same data from the Fast Reports website sorted by features with missing capabilities highlighted.


Here is the same comparison which filters out any features that are unavailable across all platforms.


As you can see, the Embarcadero Edition of FastReports 2.0 FMX is very limited.


The Bottom Line: Because my application is cross-platform for both Windows and macOS, it looks like I will have to purchase the full retail version of FastReport 2.0 FMX in order to give my customers the experience they expect. 

Enjoy
Semper Fi
Gunny Mike
https://zilchworks.com

Note: Some links in this post are affiliate links, meaning I may receive a small commission if you make a purchase. This helps support my work – thank you for your understanding.

Friday, January 5, 2024

Delphi Tip of the Day: Prevent SQLite Date Headaches by using a GetDateAs_YYYYMMDD Function

Working with Date data can be very tricky. I recently encountered an "Invalid argument to date encode", error while trying to update a SQLite database table.


This placed a value of 0000-00-00 into the date field of my SQLite table.

Here is the original code which caused the error.

function TForm1.GetOneOffDateAsDate: TDate;
begin
  Result := DateEdit1.Date;
end;

procedure TForm1.SQLInsertPayment;
begin
  qryO.SQL.Clear;

  qryO.SQL.Add( ' INSERT INTO OneOffPayments    ');
  qryO.SQL.Add( '             (                 ');
  qryO.SQL.Add( '             OneOffDate,       ');
  qryO.SQL.Add( '             OneOffPayment     ');
  qryO.SQL.Add( '             )                 ');
  qryO.SQL.Add( '      VALUES (                 ');
  qryO.SQL.Add( '             :ood,             ');
  qryO.SQL.Add( '             :oop              ');
  qryO.SQL.Add( '             );                ');

  qryO.ParamByName( 'ood' ).Value := GetOneOffDateAsDate;
  qryO.ParamByName( 'oop' ).Value := GetOneOffAmount;

  qryO.ExecSQL;
end;

The getter function GetOneOffDateAsDate passes in a TDate which doesn't play nicely with FireDAC. Fortunately, the fix is quite simple. I found a fantastic explanation for this error on stackoverflow which states FireDAC expects DATE data type values to be a string in the fixed format of YYYY-MM-DD.

FireDAC Expects DATE data types
to be strings formatted as YYYY-MM-DD

So I created another getter function to format the date data as a YYYY-MM-DD string.
Problem solved!

Updated code passing FireDAC a YYYY-MM-DD string

function TForm1.GetOneOffDateAs_YYYYMMDD: String;
begin
  Result := FormatDateTime('YYYY-MM-DD', DateEdit1.Date);
end;

procedure TForm1.SQLInsertPayment;
begin
  qryO.SQL.Clear;

  qryO.SQL.Add( ' INSERT INTO OneOffPayments    ');
  qryO.SQL.Add( '             (                 ');
  qryO.SQL.Add( '             OneOffDate,       ');
  qryO.SQL.Add( '             OneOffPayment     ');
  qryO.SQL.Add( '             )                 ');
  qryO.SQL.Add( '      VALUES (                 ');
  qryO.SQL.Add( '             :ood,             ');
  qryO.SQL.Add( '             :oop              ');
  qryO.SQL.Add( '             );                ');

  qryO.ParamByName( 'ood' ).Value := GetOneOffDateAs_YYYYMMDD;
  qryO.ParamByName( 'oop' ).Value := GetOneOffAmount;

  qryO.ExecSQL;
end;

Happy coding!


Enjoy!
Gunny Mike
https://zilchworks.com

Monday, January 1, 2024

How to open URLs with default applications in macOS and Windows

 I'm currently updating an old Delphi 5 Desktop VCL application to to Delphi 11.3 FMX. And one of the capabilities I want to provide is the ability to launch several webpages from within the application. I want to place a link in the main menu to my YouTube channel so customers can easily get to product videos. And there's also a link to my website in the Help > About box.



It was fairly straightforward the last time I did this using VCL because all I had to worry about was the Windows side of things. However, because I want this application to run on both Windows and macOS it presented a challenge.

The Delphi IDE won't recognize the Macapi namespace unless the target is set to MacOS 64-bit

Harry Stahl covers the COCOA API on pages 98-99 of his book Cross-Platform Development with Delphi. He also gives an example of how to use the NSWorkspace object of  Macapi.Appkit. However, he doesn't show how to setup the uses clause.

I also found a fantastic reference on stackoverflow by David Heffernan that was written in 2015. However, there are two issues with Heffernan's if you are looking for a complete answer:

  1. There is a reference to a blog post by Malcolm Groves called Opening files and URLs in default applications in OS X which is no longer available or accessible.
  2. The example doesn't tell you you need to target the MacOS 64-bit platform before the IDE will recognize Macapi namespace..
The Delphi IDE won't recognize the Macapi namespace unless the target is set to MacOS 64-bit. Shame on me for not reading up on the Embarcadero docs. Wrapping my head around how to use the  {$IFDEF MSWindows} and the {$IFDEF MACOS} was a little tricky But I eventually caught on. 

After a couple hours of going back and forth with code that worked for Windows but didn't work for macOS. And code that worked for macOS but didn't work for Windows, I finally got Heffernan's example to work.

The next step was to extract the code out of the main form and place it into it's own unit. And that is the code I'm sharing with you today. I hope you find this helpful. 



Video demonstration of the below source code

Here is the source code:

Unit1.fmx
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Goto Website'
  ClientHeight = 238
  ClientWidth = 478
  Position = ScreenCenter
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object Text1: TText
    AutoSize = True
    Cursor = crHandPoint
    Position.X = 116.000000000000000000
    Position.Y = 83.000000000000000000
    Size.Width = 246.078125000000000000
    Size.Height = 31.921875000000000000
    Size.PlatformDefault = False
    Text = 'https://zilchworks.com'
    TextSettings.Font.Size = 24.000000000000000000
    TextSettings.FontColor = claMediumblue
    OnClick = Text1Click
    OnMouseEnter = Text1MouseEnter
    OnMouseLeave = Text1MouseLeave
  end
end

Unit1.pas
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects;

type
  TForm1 = class(TForm)
    Text1: TText;
    procedure Text1MouseEnter(Sender: TObject);
    procedure Text1MouseLeave(Sender: TObject);
    procedure Text1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  u.OpenURL;

{ TForm1 }

procedure TForm1.Text1Click(Sender: TObject);
begin
  GotoWebsite(Text1.Text);
end;

procedure TForm1.Text1MouseEnter(Sender: TObject);
begin
  Text1.Font.Style :=  Text1.Font.Style + [TFontStyle.fsUnderline];
end;

procedure TForm1.Text1MouseLeave(Sender: TObject);
begin
  Text1.Font.Style :=  Text1.Font.Style - [TFontStyle.fsUnderline];
end;

end.

u.OpenUrl.pas
{
+-------------------------------------------------------------------------------
¦ Filename:    u.OpenURL Unit
¦ Author:      Michael J. Riley
¦ Website:     https://zilchworks.com
¦ YouTube:     https://www.youtube.com/@CapeCodGunny
¦ Copyright:   © 2023-2024 by Michael J. Riley. All Rights Reserved.
+-------------------------------------------------------------------------------
¦ Purpose:     Opens a url using the default browser on the users system.
¦
¦ OS:          Windows, macOS
+-------------------------------------------------------------------------------
¦ Developer References:
¦
¦ Book:        Cross-Platform Development with Delphi 10.2 & FireMonkey
¦ Author:      Harry Stahl
¦ ISBN:        https://isbnsearch.org/isbn/9781549545764
¦ Notes:       See pages 98-99.
¦
¦ Websites:    https://stackoverflow.com/q/28858392/195983
¦              https://stackoverflow.com/a/28859000/195983
+-------------------------------------------------------------------------------
¦ DISCLAIMER:
¦
¦ This source code is provided "as is" and without any warranty. Use it at your
¦ own risk. The author(s) make no guarantees or assurances regarding the
¦ correctness or functionality of the code, and disclaim any liability for
¦ damages resulting from its use.
¦
¦ It is advisable to thoroughly review and test the code before deploying it in
¦ any production environment.
¦
¦ By using this code, you agree to these terms and acknowledge that any issues
¦ arising from its use are solely your responsibility.
+-------------------------------------------------------------------------------
}
unit u.OpenURL;

interface

{$IFDEF MSWindows}
uses
  Winapi.ShellAPI,
  Winapi.Windows;
{$ENDIF}

{$IFDEF MACOS}
uses
  Macapi.AppKit,
  Macapi.Foundation,
  Macapi.Helpers;

  procedure macOSGotoWebsite(URL: string);
{$ENDIF}

  procedure GotoWebsite(URL: string);

implementation


procedure GotoWebsite(URL: string);
begin
  {$IFDEF MSWindows}
  ShellExecute(GetDesktopWindow, 'open', PChar(URL), '', '', SW_SHOWNORMAL)
  {$ENDIF}
  {$IFDEF MACOS}
  macOSGotoWebsite(URL);
  {$ENDIF}
end;

{$IFDEF MACOS}
procedure macOSGotoWebsite(URL: string);
var
  macURL: NSURL;
  macWorkspace: NSWorkspace;
begin
  macURL := TNSURL.Wrap(TNSURL.OCClass.URLWithString(StrToNSStr(URL)));
  macWorkspace := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace);
  macWorkspace.openURL(macURL);
end;
{$ENDIF}

end.

Enjoy!




Wednesday, December 20, 2023

Delphi Tip of the Day: Use Your Own Unique Prefix for Types and Constants

I'm in the process of converting an old Delphi 5 VCL application to Delphi 11 FMX. Yeah, I have Delphi 12 but I'm waiting for the first bug release before I start using it. Well, this morning I learned a valuable lesson. A lesson which stopped me dead in my tracks. 

There's nothing stopping you from creating an already existing type!

I was making some refactoring changes to my code. I didn't realize I was about to make a huge mistake. I went plodding ahead pleased with the progress I was making and admiring the beautiful, refactored code I was creating. When boom... I renamed a type that stepped on a type already inside the System.UITypes unit.

There's nothing to stop you from creating an already existing type. Of course I didn't use the preview changes function. I just hit go!

I had defined my own enumerated type called TMyImageIndex. I decided to just simply call it TImageIndex. So, that's what I did using Refactor > Rename type TMyImageIndex CTRL+SHIFT+E

I knew I messed up when I saw way too much code show up in the results panel.

How dare Embarcadero define a type called TImageIndex

WTF.  If it already existed the IDE should have prevented me or at least warned me. How dare Embarcadero define a type called TImageIndex.

type
//TImageIndex = (iiAdd = 2, iiUpdate = 3);)
  TZwImageIndex = (iiAdd = 2, iiUpdate = 3);)

const
  ZW_WIDTH_COLUMN_GLYPH  = 20;
  ZW_WIDTH_COLUMN_DATE   = 90;
  ZW_WIDTH_COLUMN_AMOUNT = 74

It took me about 30 minutes, but I was able to get the original code back in place, And working.

So going forward I have created my own unique prefix of  TZw (Zw = ZilchWorks). Going forward I will preface all Types and Constants.

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com

Saturday, October 28, 2023

How to get the RSS Feed of YouTube Channels

Disclaimer: This post contains affiliate links, which means I may earn a small commission if you click through and make a purchase, at no extra cost to you. Your support helps keep this blog running – thank you!

I am a big fan of Harry Stahl's book "Cross-Platform Development with Delphi 10.2 & FireMonkey for Windows, MAC OS X (macOS) & Linux". I purchased this book in May 2021 and it has helped me several times as I'm porting my Zilch application from Delphi 5 VCL to Delphi 11 FMX.

Here's are Amazon links to Stahl's book:


I like to maintain RSS feeds of my favorite Delphi blogs. So, I went looking to see if Stahl has a blog I could add to my Outlook RSS Feeds. I found a couple of Stahl's websites. He does have a few blog posts but they are not easily converted into an RSS feed. 

Does YouTube support RSS feeds?

However, Stahl has a fairly active YouTube channel called Programming with Delphi. https://www.youtube.com/@programmingwithdelphi 

I wondered if YouTube supports RSS feeds? The answer is, YES!

Open Chrome and go to the YouTube channel you want to snag the RSS feed from. Right-click and choose the View page source option.



Then click the Line wrap checkbox in the top left corner of Chrome.



Press Ctrl-F to open the search box and enter rssurl.
Click and drag your mouse to highlight the URL associated with the rssurl attribute.
Press Ctrl-C to copy this highlighted URL to the clip board.
Your copied URL should look similar to the value below.

https://www.youtube.com/feeds/videos.xml?channel_id=UCiUVNZgsZZhziFL4oy-evEA


There you have it. That's all there is to grabbing the RSS Feed URL for any YouTube channel.

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com

Note: Some links in this post are affiliate links, meaning I may receive a small commission if you make a purchase. This helps support my work – thank you for your understanding.


Sunday, July 23, 2023

Here's how I will code better in Delphi. How will you?

Disclaimer: This post contains affiliate links, which means I may earn a small commission if you click through and make a purchase, at no extra cost to you. Your support helps keep this blog running – thank you!

When it comes to Delphi, it's amazing how much I don't know, once knew but forgot, or just plain skipped over because it was too mind-boggling at the time. I took a break from reading Alister Christie's new book "Code Better in Delphi", which I purchased last night, to write this blog post.


https://amzn.to/4dE8oOq (Paperback)

While reading the bit on "refactoring", I realized how little refactoring I actually put into practice. Yes, I have Fowler's book, the second edition. And no, I haven't read it. I've thumbed through it a little in the past. I even tried looking for the "Introduce Explaining Variable" refactor Christie discusses on page 53 of his book. It turns out Fowler now calls it "Extract Variable". Keeping Fowlers "Refactoring" book on my desk, and referring to it often, is one way I am going to code better in Delphi.

It's amazing how much I don't know or once knew but forgot

I just started reading "The Observer Pattern" in Christie's book and had to stop. I bought "Head First Design Patterns" by O'Reilly, quite a few years ago. I have the 10th Anniversary edition with code examples in Java 8. My intent was to install Java on my machine and force myself to learn these patterns by following the code in the book. It didn't go so well. The authors do a great job using story to make learning fun. I just couldn't wrap my head around Java.

Christie has managed to reignite my desire to learn these patterns. I downloaded the Java source code. I plan to work my way through "Head First Design Patterns" pasting the Java source code into ChatGPT, and asking Chat to convert it to Delphi.

I will navigate through each pattern using this method. I will then revisit the same pattern in Primoz Gabrijelcic's book "Hand-On Design Patterns with Delphi". This is another way I'm going to learn to code better in Delphi. 

Another way is to revisit the Model-View-Controller method of code separation. Here is a the MVC song from 2007 I just learned about today. 

And I also want to implement "Interfaces".

Here's my list of how I will code better in Delphi:

  • Finish reading Christie's book 
  • Practice refactoring often
  • Learn and implement design patterns
  • Discover and utilize ways to separate code concerns such as MVC or MVVM
  • Overcome my stumbling block of Interfaces

Use the comments below to share how you will code better in Delphi.

Enjoy
Semper Fi
Gunny Mike

Note: Some links in this post are affiliate links, meaning I may receive a small commission if you make a purchase. This helps support my work – thank you for your understanding.

Sunday, July 2, 2023

Blueprint for Creating Delphi FMX Apps

 I just discovered an unlisted YouTube video Ray Konopka did in 2018 for Embarcadero's CodeRage called "Mobile View Management with Ray Konopka from RodeRage 2018

Although the demo and source code for this presentation is based on a mobile app, the concept Konopka presents is not just for mobile apps. It's actually a blueprint for creating any type of FMX app using Delphi.

Blueprint for Creating Delphi FMX Apps


I was compelled to write this blog for two reasons. The first stems from the fact that this is not just for mobile app development, it's for any FMX app development. And number two, the concept is simple, powerful, and elegant.

The source code Konopka used is available for download using this link https://delphibydesign.com/downloads/

From the Mind of Konopka

It doesn't matter whether you are brand new to Delphi or a seasoned Delphi veteran, if you get the opportunity to download and study an application built by Konopka, TAKE IT. You will learn so much. It's an opportunity to explore the mind of Konopka.

Konopka embodies the meaning of my favorite quote from Albert Einstein. "Make everything as simple as possible but not simpler."


Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com


Saturday, June 24, 2023

THE ULTIMATE BEGINNER'S GUIDE TO OBSIDIAN NOTES | How to Use Obsidian Notes

I have just started to explore Personal Knowledge Management (PKM). Didn't know it was a thing until a few days ago. Obsidian (https://obsidian.md) seems to be one of the most popular tools being used. This tutorial is a couple years old but it's very good. 

#PKM #obsidian #markdown

   

 Enjoy
Semper Fi
Gunny Mike
https://zilchworks.com

Sunday, May 7, 2023

Pseudo Code File Logic: Open > New > Save > Save As

Just finished working out the logic for handling file logic:

File Open
File New
File Save
File Save As

This assumes you are keeping track of the following:

  • Current Filename
  • Changes to file data
I've been wrestling with this one for a few days. And then it finally hit me. "Hey, Exit can be your friend."

Exit can be your friend







Within the last year, my thinking has been influenced by Jeff Patton and his book "User Story Mapping". At work I have been involved in many meetings/discussions where everyone is in agreement that we need to implement "Solution X". However, everyone has their own interpretation of what "Solution X" is.

https://www.amazon.com/User-Story-Mapping-Discover-Product/dp/1491904909


Enjoy,
Semper Fi
Gunny Mike
https://zilchworks.com


Friday, March 24, 2023

Delphi FMX Desktop Development: Part 1

Question: Is FMX Desktop Development Worth It?

This is part 1 in a series dedicated to Delphi FMX Desktop development. I am in the process of converting an old VCL application to FMX. When I first started playing around with FMX I was excited because one code base could serve up all different platforms; desktop, mobile, tablet. FMX also let's you create Windows, Mac OSX, Android, iPhone apps from that same single code base.

It wasn't until recently that I discovered one code base doesn't easily translate between desktop and mobile. So I am focused solely on creating one desktop code base for Windows and Mac OSX. This is a conscious choice on my part to stay in the desktop market. 

Over the last 32 years I have had several Mac OSX users asking me when I would have a version of my software that would work on their computers. Delphi FMX will let me make this happen. 

This leads to a series of questions:

  • What does the desktop market share look like?
  • How many new Mac customers will this bring me?
  • Is it worth the effort to create a desktop application for both Windows and Mac?
  • How does geographical location influence the decision?

I would like to thank the people at statcounter GlobalStats for providing the information in this post. Visit https://gs.statcounter.com/ for more information.


"The Whole World's Gone Mobile!
Forget Desktop Development."



Let's start by looking at the Desktop vs Mobile vs Tablet market share. We are going to look at the past year and then look at the past ten years. This will show the huge growth in the mobile market.

Worldwide 1 Yr Mobile 60% Desktop 40%


Worldwide 10 Yr Mobile 16 → 60% ↑ Desktop 82 → 40% ↓  


Looking at just this one graph you would think it's a waste of time to dive into the desktop market. On a world wide scale the mobile market has completely overtaken the desktop market. At first glance you might think, "Wow, it's not worth going after the desktop market. The whole world has gone mobile." 

"I Might be Ignoring 50% of the Users!"


What about the United States? Does geography play any part in my decision to create a desktop application? After all, the majority of my customers come from the United States.

USA 1 Yr Mobile 46% Desktop 52%



USA 10 Yr Mobile 15 → 46%  Desktop 82 → 52% 


Because the majority of my customers are from the United States, and I'm only concerned with the Desktop market share, what do these numbers tell me?

Today, the Desktop market share in the United States is 52%. This tells me that 5 out of every 10 potential customers are desktop users. This also tells me that mobile use has skyrocketed over the past ten years, and my decision to only focus on desktop might be ignoring almost 50% of the users.

What about my decision to only focus on Windows and Mac OSX customers?

USA 10 Yr Windows 82 → 60% OSX 16 → 30%↑   

Here is what the Desktop Operating System landscape tells me looking at the past ten years. Windows is still the dominant operating system within the USA even though it has dropped 22%. On the other hand Mac OSX has almost doubled it's share of the market.

Overall, the prospects look good to invest some solid time and effort into creating a Desktop application that caters to both Windows and Mac users. As far as how many Mac OSX customers can I expect? 

These numbers tell me I can expect about 5 new Mac OSX customers for every 10 new Windows customers. And that sounds pretty good to me. 

Answer: It's worth it for me!

Use this link for all 32 videos from the Desktop First UX Summit 2021
https://www.youtube.com/playlist?list=PLDWPwIbHH6jldMmNDe99y9NDWiEl-B3jK

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com



Sunday, February 19, 2023

DELPHICON 2023: Every APP Trick in Book with Ian Barker

DELPHICON 2023: Every APP Trick in the Book with Ian Barker 

Timestamp links have been added to each of the individual sections of this presentation.


Every App Trick in the Book
https://youtu.be/PJNnCP2JvIY?t=14829
https://github.com/checkdigits/Every_app_trick_in_the_book_-_Ian_Barker
https://blogs.embarcadero.com/delphicon-2023-every-app-trick-in-the-book/

Notifications
https://youtu.be/PJNnCP2JvIY?t=15208

Elevation Button (VCL Only)
https://youtu.be/PJNnCP2JvIY?t=15443

ShellAPI
https://youtu.be/PJNnCP2JvIY?t=15705

Settings Persistence
https://youtu.be/PJNnCP2JvIY?t=15857
TPath

User Authentication OAUTH2
https://youtu.be/PJNnCP2JvIY?t=16100
TMS SOftware Sphinx (€395 - €595)
https://tmssoftware.com/site/sphinx.asp
eSeGeCe OAuth2 Client (€349 - €649)
https://www.esegece.com/websockets/http/oauth2

NEW User BioMetrics
https://youtu.be/PJNnCP2JvIY?t=16484

Check for Internet Conncetion
https://youtu.be/PJNnCP2JvIY?t=16922

Splash Screens
https://youtu.be/PJNnCP2JvIY?t=17115

Adding Some Coolness
https://youtu.be/PJNnCP2JvIY?t=17317
http://tinyurl.com/delphiwowfactor

Themes and Styles
https://youtu.be/PJNnCP2JvIY?t=17350
http://tinyurl.com/delphiw11design

Detecting Dark Mode (and Reacting when it changes)
https://youtu.be/PJNnCP2JvIY?t=17369
https://blogs.embarcadero.com/modernize-your-app-are-you-handling-windows-themes-correctly/

Checking for Updates
https://youtu.be/PJNnCP2JvIY?t=17390
https://blog.marcocantu.com/blog/auto_updating_programs.html (2007)

In-App Scripting
https://youtu.be/PJNnCP2JvIY?t=17498
Python4Delphi
https://github.com/pyscripter/python4delphi
TMS Script Studio Pro (€190 - €630)
https://www.tmssoftware.com/site/scriptstudiopro.asp
DWScript
https://github.com/EricGrange/DWScript

Single Instance
https://youtu.be/PJNnCP2JvIY?t=17640
https://stackoverflow.com/questions/73023379

Manipulating Images
https://youtu.be/PJNnCP2JvIY?t=17767
https://skia4delphi.org

To the Web
https://youtu.be/PJNnCP2JvIY?t=17863
uniGUI ($395 - $890)
https://youtu.be/fN4m-a-C64o
IntraWeb (€399 - €2,399)
https://www.atozed.com/intraweb/
TMS WEB Core (€395 - €1,295)
https://www.tmssoftware.com/site/tmswebcore.asp
https://youtu.be/u-8yjKO3AyM

Let's Encrypt - Free SSL Certificates
https://youtu.be/PJNnCP2JvIY?t=17954
https://letsencrypt.org
Pault Toth Delphi ACME
https://github.com/tothpaul/DelphiACME

Reverse Proxy via NGINX
https://youtu.be/PJNnCP2JvIY?t=18086
https://mginix.org

Enjoy
Semper Fi
Gunny Mike
https://zilchworks.com

Saturday, February 18, 2023

DELPHICON 2023 - User Interface Design with Actions by Ray Konopka

Konopka does a fantastic job showing how to streamline the User Interface using Actions. This is a must see video from DELPHICON 2023.

He starts out showing the typical way of coding in Delphi by using onClick events on Buttons and Menus. He then shows how to build an ActionList from scratch, using Categories and Actions. He then ports all the onClick events to Action onExecute events. He also imparts the knowledge he's learned over the years as to why this is the best way to code a user interface. Absolutely brilliant.

Every time I watch Konopka give a presentation I learn something. It's amazing to watch a master demonstrate his craft. 


Video presentation link:
https://youtu.be/PJNnCP2JvIY?t=7483

Source code link:
https://delphibydesign.com/downloads/

Enjoy!
Semper Fi
Gunny Mike
https://zilchworks.com

Sunday, February 12, 2023

Use ChatGPT to Convert Other Language Source Code to Delphi

If you've read some of my previous posts you know how much I've struggled to make the paradigm shift from being a top-down, procedural programmer to an OOP programmer. I've purchased several books on OOP. And one book series I thought would hold some promise are "The Object-Oriented Thought Process" books written by Matt Weisfeld. I have four different editions on my book shelf.

I struggle with OOP for several reasons. One very frustrating reason is the lack of Delphi/Pascal examples used by authors. Most of the code examples are written in Java, or C, or C# or some language other than Delphi/Pascal.

The last bullet point on page 3 of Weisfled's fourth edition, listed under the heading of "What's New in the Fourth Edition", states:

  • Expanded code examples, for certain chapters, in Java, C# .NET, VB .NET, and Objective-C available online on the publisher's website

No Object Pascal or Delphi examples!

No Object Pascal or Delphi examples. I reached out to Weisfeld asking if he might include Object Pascal examples and received a negative response.

I love Pascal. It's elegant. It's easy to read and understand. I've been using Pascal/Delphi since 1985. (2023-1985=38 years). Besides SQL, it's my main programming language. Ok, I confess, I did Active Server Pages (APS) and VB Script for about 10 years.

I've tried loading Java onto my machine so I could follow along and learn the OOP concepts but I just can't wrap my head around the Java syntax.

Today, I discovered the answer that works for me. ChatGPT!

I asked ChatGPT to convert the following Java code from page 24 of "The Object-Oriented Thought Process" to Delphi and the results were very hopeful.

public class IntSquare {

  // private attribute
  private int squareValue;
  
  //public interface
  public in getSquare (int value) {
    
    squareValue = calculateSquare(value);
    return SquareValue
  
  }
  
  //private implementation
  private int calculation (int value) {
    return Math.pow(value,2);
  }
}

Here are the results returned from ChatGPT:

type
TIntSquare = class
private
FSquareValue: Integer;
function CalculateSquare(value: Integer): Integer;
public
function GetSquare(value: Integer): Integer;
end;

implementation

function TIntSquare.CalculateSquare(value: Integer): Integer;
begin
Result := value * value;
end;

function TIntSquare.GetSquare(value: Integer): Integer;
begin
FSquareValue := CalculateSquare(value);
Result := FSquareValue;
end;

end.

I know the results are not the indented and formatted code you would get from inside the IDE. This was my first attempt at using ChatGPT. I took several screen shots of my interaction with ChatGPT so I can show you what happened.

Here is my entire ChatGPT session:






Here is the final output from ChatGPT.

uses
  System.Math;
  
type
  TIntSquare = class
  private
    FSquareValue: Integer;
    function GetSquareValue: Integer;
    procedure SetSquareValue(const Value: Integer);
    function CalculateSquare(value: Integer): Integer;
  public
    property SquareValue: Integer read GetSquareValue write SetSquareValue;
    function GetSquare(value: Integer): Integer;
  end;

implementation

function TIntSquare.CalculateSquare(value: Integer): Integer;
begin
  Result := Round(Power(value, 2));
end;

function TIntSquare.GetSquare(value: Integer): Integer;
begin
  SquareValue := CalculateSquare(value);
  Result := SquareValue;
end;

function TIntSquare.GetSquareValue: Integer;
begin
  Result := FSquareValue;
end;

procedure TIntSquare.SetSquareValue(const Value: Integer);
begin
  FSquareValue := Value;
end;

end.

This looks very promising! Give ChatGPT a try converting code.
https://openai.com/blog/chatgpt/


Enjoy!
Semper Fi
Gunny Mike https://zilchworks.com

Monday, December 5, 2022

The Kinetic Technique by H. A. Overstreet (1925)

Influencing Human Behavior by H. A. Overstreet was published in 1925. I purchased an old hardcover copy of his book over a year ago because, some other book I was reading referred to it as a master work. Overstreet's book has been sitting on my oak book shelf, which was built by a very nice Mennonite man in Maryland, ever since it arrived.

I spent the weekend of November 26th and 27th entering all my "print books" into a software program called Calibre (https://calibre-ebook.com) which by the way, is mainly for managing E-books.

After saving the information from an ISBN import, I began reading. I stopped on page 12 after reading what Overstreet wrote about capturing one's attention using "The Kinetic Technique".

I stopped reading because this piece of wisdom so grabbed ahold of me, I wanted to let it seep into my mind.

Two days later on Tuesday morning at 1:45 AM I woke to a racing mind. "What book talked about a dot on the wall?" I kept searching, and searching my thoughts. Nothing.

"Ah, the influencing human behavior book."

Why was this so important that it woke me up? My website (read that as I) totally violated the principle of movement. Every page on my website has the same big-ass banner. I was making all my visitors (read that as potential customers) stare at a dot on the wall. How boring is that.

I jumped out of bed right then and there and started working on removing the dot from my website. It took me a few days, but I managed to get rid of that dot. But more importantly, I learned a valuable lesson from some ink that was printed nearly 100 years ago.

Thank you Mr. H. A. Overstreet. I can't wait to see what else of yours seeps into my mind.

Influencing Human Behavior - H. A. Overstreet (page 12)

Enjoy,
Gunny Mike
https://zilchworks.com