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

Monday, July 11, 2022

Delphi Tip of the Day - Environment Variables used only by the Delphi IDE

 I wanted a quick, down-and-dirty, reference to only those variables used by the Delphi IDE. Inside the IDE you can navigate to Tools > Options > IDE > Environment Variables. This will list all the Environment Variables currently in use. Those belonging to Delph and those outside of Delphi. However, that is not what I was looking for. I just wanted the Environment Variables specific to the Delphi IDE.

Generating this list was a three step process which involved some code I found here. 
http://delphiexamples.com/systeminfo/envtrings.html

Step 1. I entered and ran the code from the above link. I then copied and pasted the contents of the memo to a separate text file called EnVars-Delphi-IDE.txt.

Step 2. I closed Delphi and ran the program again from the saved location. I then copied and pasted the contents of the memo to a file called EnVars-Without-Delphi-IDE.txt.

Step 3. I then navigated to the Delphi BDSBIN location and ran the Beyond Compare utility BCompareLite.exe. I did a text compare of  EnVars-Delphi-IDE.txt and EnVars-Without-Delphi-IDE.txt looking only for the differences.


I simply copied all the text from the left-had side and saved it as EnVars-Delphi-IDE-Only.txt. And now I have my quick down and dirty list of Delphi IDE Environment Variables.

Here the list generated from my computer. YMMV

BDS=C:\program files (x86)\embarcadero\studio\22.0
BDSAppDataBaseDir=BDS
BDSBIN=C:\program files (x86)\embarcadero\studio\22.0\bin
BDSCatalogRepository=C:\Users\Mike\Documents\Embarcadero\Studio\22.0\CatalogRepository
BDSCatalogRepositoryAllUsers=C:\Users\Public\Documents\Embarcadero\Studio\22.0\CatalogRepository
BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\22.0
BDSINCLUDE=C:\program files (x86)\embarcadero\studio\22.0\include
BDSLIB=C:\program files (x86)\embarcadero\studio\22.0\lib
BDSPLATFORMSDKSDIR=C:\Users\Mike\Documents\Embarcadero\Studio\SDKs
BDSPROFILESDIR=C:\Users\Mike\Documents\Embarcadero\Studio\Profiles
BDSPROJECTSDIR=C:\Users\Mike\Documents\Embarcadero\Studio\Projects
BDSUSERDIR=C:\Users\Mike\Documents\Embarcadero\Studio\22.0
DELPHI=C:\program files (x86)\embarcadero\studio\22.0
DEMOSDIR=C:\Users\Public\Documents\Embarcadero\Studio\22.0\Samples
FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer
FPS_BROWSER_USER_PROFILE_STRING=Default
IBREDISTDIR=C:\Users\Public\Documents\Embarcadero\InterBase\redist\InterBase2020
IB_PROTOCOL=developer_ib2020
InterBase=C:\program files (x86)\embarcadero\studio\22.0\InterBase2020
Path=C:\Users\Public\Documents\Embarcadero\InterBase\redist\InterBase2020\IDE_spoof
ProductVersion=22.0
SESSIONNAME=Console

Beyond Compare is a fantastic tool written with Delphi. The lite version is included with your purchase of Delphi. For more information about Beyond Compare visit their website: 

https://www.scootersoftware.com/

Enjoy,
Gunny Mike
https://zilchworks.com




Saturday, June 4, 2022

Delphi Tip of the Day - Auto Adjust FMX StringGrid Column Widths

 I've been playing around with the FMX StringGrid for the past three weeks. And I thought... 

"Wouldn't it be nice if there was a way to automatically resize the column widths based on the values in each of the columns. Just like the way Excel works when you highlight the entire sheet and double-click the thin line between two columns."

In today's Delphi tip of the day I present a simple routine that evaluates the data in each of the column headings and the columns of each row to determine how wide to make the cells. And the best part is, it automatically adjusts all the columns widths in one go.

"Just like the way Excel works..."


It's fairly straight forward using two for loops. It loops through each column looking at every row and determining the width that column needs to be based on the data in each cell.

procedure AutoAdjustColumnWidths(const Grid : TStringGrid);
var
  col : Integer;  //Grid Column
  w   : single;   //New Width
  s   : string;   //Grid Column value
  l   : Integer;  //Lenght of Grid Column value
  row : Integer;  //Grid Row
  r   : Single;   //Result of TextWidth calculation
begin
  for col := 0 to Grid.ColumnCount-1 do
  begin
    w := 0;
    s := Grid.ColumnByIndex(col).Header;
    l := length(s);
    w := Grid.TextWidthToColWidth(l,s) * 1.05; //add a little padding
    for row := 0 to Grid.RowCount-1 do
    begin
      s := Grid.Cells[col,row];
      l := length(s);
      r := Grid.TextWidthToColWidth(l,s) * 1.05; //add a little padding
      if r > w then
        w := r;
    end;
    Grid.Columns[col].Width := w;
  end;
end;

I'm sure this can be improved upon so it only evaluates the first 50 or 100 rows. I'll leave that up to you to figure out.

Enjoy,
Gunny Mike
https://zilchworks.com






Monday, February 21, 2022

Book Review: The Hungry Brain

The Hungry Brain points out how the brain works. The brain (your brain) is conditioned by past food choices and conditions you to make future choices. There are strong cues at play and the stronger ones win. Most of what happens is nonconscious. The author credits Daniel Kahneman, author of "Thinking, Fast and Slow" for the two brain systems. System 1 which is fast, effortless, intuitive, and nonconscious. System 2 which is slow, effortful, rational, and conscious. System 1 usually wins when it comes to food choices.


I was surprised by how food decisions are made in the brain and how the brain continuously reinforces those decisions. I was also stunned to discover how irrational our/my thinking can be. This supports the two systems Kahneman describes. For example; "The 1970 Stanford Marshmallow Experiment" gave children the option of one marshmallow now (which sat on a table right in front of them) or two marshmallows in 15 minutes. The kids were basically given a choice of a small reward now or a larger reward in the future. Most kids ate the one marshmallow right away. We/I tend to value the now more and the future not so much. This is a psychological trait called "delay discounting".

This book is a very technical read

I know I am one of those people who do/did not value my future self. I started smoking cigarettes when I was twelve. As an adult I smoked two and one-half packs of cigarettes a day. One day, after 32 years of smoking, I finally quite "cold turkey". As a smoker I totally discounted my future health. I've been smoke-free for 20+ years. For me, it's time to refocus on my future self and lose the weight. While a brown sugar cinnamon pop tart will definitely give me a 10 minute pleasure high it does not help my future self one bit. 

This book is a very technical read. You could probably get away with reading only chapters 10 and 11. However, you would miss out on some of the little stories sprinkled throughout the other chapters. 


This book has caused me to want to read two other books. The first book, which I purchased, is "Thinking, Fast and Slow" by Daniel Kahneman. I was originally introduced to Kahneman a few years back. I'm very much interested in storytelling and Kahneman links effective storytelling to emotions not rationale. So I am very interested in learning more about the two brain systems. 


The second, which I checked out from the library is "Salt Sugar Fat" by Michael Moss. I've had a tacit understanding that processed foods are the new crack cocaine. I figure by reading this book two things will happen: 

  1. I will change my perspective on processed food and see them for what they truly are. 
  2.  By learning exactly how food scientists tweak the salt, sugar, fat ratios every so slightly to keep their food irresistible, I will view these foods as traps, and see myself for what I really am... nothing more than a commodity (a tick mark on the balance sheet).



Please use the comments to give your recommendations for other, related books worth reading.

Enjoy
Semper Fi
Gunny Mike 

Sunday, January 16, 2022

Book Review: Delphi GUI Programming with FireMonkey (Part 1)

I purchased the book Delphi GUI Programming with FireMonkey by Andrea Magni on November 7, 2020. I dove in head first with great enthusiasm only to get derailed early on. It happened when I tried to follow the topic Understanding the Style Designer in chapter 2.


As someone who knows almost nothing about FireMonkey these four and one-half pages soured my learning and turned me against this book and it's author. I tried reaching out to the author directly and received a curt response basically telling me that the examples in his book were not meant to be step-by-step. From that moment on I let this book sit on the shelf and collect dust.

That was a foolish mistake on my part. 

The Style Designer is a central part of FireMonkey and FMX. It is my opinion, that the author introduced this complex topic much too early in the book. It was presented with just a small smattering of knowledge and guidance. Leading me to three days of frustration because I could not make the Style Designer match what I saw in the book. The style designer is much too complex a topic to simply be glossed over in this fashion. A more fitting title for this topic would be First Glance at the Style Designer.

Don't Judge a Book by Only 4 Pages

If you are new to FMX and FireMonkey, and you want to get the most out of this book, I highly recommend you skip the topic Understanding the Style Designer in Chapter 2 (print: 34-38, pdf: 31-35). No understanding will happen. Instead, I recommend you watch this 50 minute YouTube video by Ray Konopka called Customizing Controls with FMX Styles.


After you have a better understanding of the FMX Style Designer, you may want to come back to the topic Understanding the Style Designer in this book.

You can best sum up my attitude about this book (and it's author) by the phrase "Don't judge a book by only 4 pages". I owe Magni an apology for holding a grudge against him because of 4 stinkin pages (and one email) in a book. 

"Andrea, I'm sorry."

I finally picked up Magni's book (again) last week. Actually I did a search for "Live Bindings" of my digital Delphi books which lead me to pick up Magni's book of the shelf. I opened up to Chapter 4, Discovering Lists and Advanced Components to a huge surprise. The printed copy of my book went from page 104 to page 157. Pages 105 through 156 are missing.

I contacted Packt Publishing to let them know of the misprint. All is good, a new printed copy is on the way.

At this point I was committed and had to fall back on reading the PDF version of Magni's book. I recently had cataract surgery on both eyes so I was very hesitant. Reading PDF books and manuals always leads to eyestrain at best or headaches at worst. That's when I discovered you can customize the background and font colors of a PDF document. See my post "Tip of the Day - How to change the text color of a PDF document" for instructions on how to do this.

I'm only part way through Chapter 4: Discovering Lists and Advanced Components and so far, Magni had done a fairly descent job. I have downloaded the source code for this book. I find it very helpful to have Delphi up and running along side reading the customized PDF. I open the example projects and play along with the reading to get a better understanding. 

Magni has done a a great job organizing the source code for this book. There is a separate chapter containing projects for each chapter. Each project within a given chapter has it's own folder. It is very well organized. The folders seem to be named intuitively. However, I find it very helpful to rename each folder and preface each folder name with the page number. That way I can quickly associate which project goes with with page or section of the book. As a plus, any un-numbered folders means I haven't opened that project and most likely haven't read that section of the book in detail.


I'm not sure when or if I will get finished with Magni's book. I'm just glad I overcame my stubbornness and opened his book back up again. I do know I have a need to and look forward to learning the following:

  • Chapter 4 Discovering Lists and Advanced Components
    •  ListBox
    •  ListViews
    •  Treeviews
    •  Grids
  • Chapter 5 Using FireDAC in FMX Applications
  • Chapter 6 Implementing Data Binding
  • Chapter 7 Understanding FMX Style Concept
  • Chapter 8 Divide and Conquer with TFrameStand (Maybe)

Bottom Line: Buy this book. Skip pages 34-38 (print), 31-35 (pdf).

Semper Fi,
Gunny Mike
zilchworks.com

Saturday, January 15, 2022

Tip of the Day - How to change the text color of a PDF document.

I was reading Andrea Magni's book Delphi GUI Programming with FireMonkey and realized I am missing pages 105-156. Packt Publishing is having a new print copied sent to me. Anyway, the PDF copy of the book is 100% complete.
I've always dreaded having to read PDF books for two reasons:
  • I don't like the way the pages jump from one page to another
  • The standard black text on a white background hurts my eyes and makes them tired.
I recently discovered two things you can change about PDF books (documents) that have made a huge difference for me. 

One is smooth scrolling. I thought that all pdf's jumped from the bottom of the page to the top of the next page. Not true. This is a setting. 

The second thing I discovered is the ability to change the color of the text within a pdf document. The standard black text on white background rally hurts my eyes. By changing the background and text color it is much more enjoyable to read.

This video shows you how to set smooth scrolling and change the text and background colors within a PDF document.


Enjoy,
Gunny Mike


Wednesday, December 15, 2021

FMX Desktop - Restrict Form Size on Windows and macOS

I'm in the process of porting over an old VCL application to FMX. At this time I'm only concerned with creating a desktop application that will run on Windows and macOS. One of the VCL features I like is the ability to set the forms minimum width and height properties. This prevents the user from making the application ridiculously small and unusable.

With a VCL application this is accomplished by simply entering the desired values in the MinHeight and MinWidth properties of the forms Constraints. The example below sets the VCL forms minimum height to 540 and the minimum width to 720.

Unfortunately, these properties do not exist within FMX Muilti-Device applications. In order to impose size constraints in FMX you have to write some code in the OnResize event handler. 

The simplest way to accomplish this would be to right some code similar to this:

const
  MinW = 720;
  MinH = 540;
begin
  if Width  < MinW then Width  := MinW;
  If Height < MinH then Height := MinH;
end;

This works. However it produces a horrible flickering effect when you continue to drag the mouse inside the boundaries specified within the OnResize event handler.

Windows Form Constraints with Flickering


What about the macOS? Does it flicker? The answer is no. The macOS respects the size constraints with no flickering issue:

macOS Form Constraints no Flickering


So the issue only happen on Windows PC's. 

I may be oversensitive here but I do not like this flickering at all. In my mind it gives the sense of an unprofessional appearance. Some end users may not care one bit about this and that's fine. However, it really bugs me. I want to prevent this from happening.

So I went looking for a solution and found one on stackoverflow. The code simulates a mouseUp event if the cursor moves inside the boundaries.

Windows Form Constraints with No Flickering

This is accomplished by making a Windows API Mouse Event call inside the OnResize event handler. It's not perfect but it does prevent the flickering from happening.

Add this to the Uses clause
Winapi.Windows

Modify the onResize event handler to simulate the mouseUp event.

const
  MinW = 720;
  MinH = 540;
begin
  if Width < MinW then 
  begin
    Width := MinW;
    mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
  end;
  If Height < MinH then 
  begin
    Height := MinH;
    mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
  end;
end;

This code works great! It stops Windows PC's from flickering. However, we are not done yet. We have to wrap special tags around the Windows Only code so it is ignored by the macOS.

Modify the Uses clause as follows:

uses
{$IFDEF MSWINDOWS}
  Winapi.Windows,
{$ENDIF}
  System.SysUtils, System.Types, System.UITypes, System.Classes, 
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, 
  FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls;

Modify the onResize event handler as follows

procedure TForm1.FormResize(Sender: TObject);
const
  MinW = 720;
  MinH = 540;
begin
  if Width < MinW then 
  begin
    Width := MinW;
    {$IFDEF MSWINDOWS}
      //prevent form flickering on resize below constraints
      mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    {$ENDIF}  
  end;
  If Height < MinH then 
  begin
    Height := MinH;
    {$IFDEF MSWINDOWS}
      //prevent form flickering on resize below constraints
      mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    {$ENDIF}  
  end;
end;

Stay tuned for more FMX Desktop discoveries. 

Related Articles:
What Every Delphi Developer Should Know About Writing for Windows and Mac

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

end.

Friday, December 3, 2021

The Biggest Mistake I Made in 2021

 I know this year isn't over yet but I'm pretty sure I won't make a bigger mistake between now and January 1st. 

Mike has been selling a software product written in Turbo Pascal & Delphi for 30 years. Mike's software was mentioned on the television show Good Morning America. Mike got very excited. Mike updated his website making the 30-second Good Morning America television segment center stage. Nobody cares Mike's software got mentioned on television (except Mike). Mike turned off potential customers who visited his website. Mike's sales dropped. Mike's a jerk. Don't be like Mike.

This was one of the hardest lessons I learned. 

I was so sure my would-be customers would feel just as excited about my software getting praise on national television as me. So sure in fact, that I posted a video of my software getting mentioned front and center on my website. And not just on the home page... but on every page.

Wrong! 

People don't care about me. People care about themselves.

People don't care about you.
People care about themselves.

It was Saturday morning, August 21, 2021. I was sitting on the couch in my living room watching cartoons with my granddaughter. And my phone dinged. I received an notification of a sale. A few minutes later another ding, another sale. I checked the real-time website stats and to my surprise there were 53 visitors on my site all at the same time.

I started googling trying to figure out what was causing this frenzy of visitors to my website. And by luck I found a video segment that had just aired on the Good Morning America television show. 

The total segment was about 4 minutes long. The last 35-40 seconds is where my software ZilchWorks was mentioned. So I trimmed the video down to the last 40 seconds because that's the part that talked about my software. Proof again that people only care about themselves. Why else would I have trimmed down this video.

I then retooled my entire website and made this "Look what I can do" video front and center. I foolishly thought this would drawn in website visitors.

Lessons Learned:

  • People don't care about you. They care about themselves.
  • Customers want to know what you can do for them.
  • Enjoy the media success. Treat it as validation.
  • This too shall pass applies to both good and bad.

Enjoy!
Semper Fi,
Gunny Mike

Friday, July 30, 2021

Delphi: Inheriting Parent Properties

The ability to inherit Parent properties is very convenient. Let's say you have a form with several controls on that form. If you wanted to change the default font from "Tahoma" to "Segoe UI" wouldn't it be nice to only have to make that change in one spot and voila, the change happens everywhere?

Well that is what inheriting the Parent properties is all about.

Unfortunately, not all the Parent properties get inherited. The font color is one of those properties that gets inherited by some controls but not all controls. I created this short video to show what happens to some of the most used VCL controls when you change the forms Font Color and Font Family.



https://youtu.be/M3VWsqPodJM

So, be careful and don't assume that one single change to the forms properties will get propagated throughout your entire application.

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

Saturday, July 17, 2021

CodeRage 3 Replays - Oldies but Goodies

This morning I was looking for a video on how to debug an application with the Delphi IDE. I came across a two-minute video on YouTube by Francois Gaillard. It was a teaser video intended to pique your interest for the segment he did at Code Rage 3. Unfortunately, there was not a link to the full blown presentation.

I found a link to the Code Rage 3 replays on the way back machine. You can find the original webpage using this link. https://web.archive.org/web/20090815150549/http://conferences.embarcadero.com/coderage/article/38874

There are a lot of really interesting replays from Code Rage 3. Unfortunately, the recordings are done using Adobe Flash which has been discontinued. However all is not lost. You can download a stand-alone Flash Player from the Adobe website using this link 

https://www.adobe.com/support/flashplayer/debug_downloads.html


Delphi Debugging for Dummies by Francois Gaillard


After you download and unzip the replays you will see two ".swf" files. one called Session.swf and one called Session_controller.swf. Make sure to open the Session_controller.swf using the Flash Player program downloaded from the Adobe site. This will give you the the status bar with play and pause buttons along with the thumbtack progress bar.

Below is the list of Code Rage 3 presentation with download links.

Delphi / RAD Studio

C++ Builder

Delphi Prism

JBuilder

Delphi for PHP

InterBase

3rdRail/TurboRuby

Database Tools

General Topics

Sessions Presented in Spanish

Sessions Presented in Portuguese

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

The link to the stand-alone Adobe Flash Player came from an article called "How to Play Adobe Flash SWF Files Outside Your Web Browser" on howtogeek.com. https://www.howtogeek.com/438141/how-to-play-adobe-flash-swf-files-outside-your-web-browser/

Saturday, June 5, 2021

Mobile Storage Access (Note to Self)

 I am nowhere near creating apps for the mobile community. That doesn't mean I won't be in the future. So, I'm writing this as a "Note to Self" so when the time comes I'll have a nice handy reference.

If you are currently developing mobile apps you may find this discussion on Delphi-PRAXiS helpful and interesting.

How do users easily bring their desktop data to mobile devices?

You may also want to view the following YouTube video called Storage access with Android 11



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

Sunday, April 25, 2021

Delphi Form/Code Separation (CodeRage 9 2014)

I just re-watched an excellent video by David Schwartz on form/code separation. Schwartz gave this presentation during a 2014 Code Rage 9 session. 

Schwartz says the majority of Delphi Form-to-Form code he has seen uses what he calls "Back-Door" injection. Where all the data movement to and from controls is handled at the form level. This is in contrast with the “normal” use of properties to enforce encapsulation in the movement of data into and out of objects. He discusses "Constructor" injection and "Property" injection pointing out the pros and cons of both. 

I'm one of these "back-door" injection coders. I've never used properties. I'm learning how to use them. Here are my main reasons for not using them in the past:

  • Short how-two Delphi videos... "You can do all of this with no code".
  • They seem overly complicated to type.
  • Ignorance on the benefits provided.
Perhaps the IDE's Code Completion ( Ctrl + Shift + C ) would make creating properties and all the getters and setters a lot easier. I'll look into this. 

Help Wanted: If you know of any tutorials or videos specifically aimed at creating and using Properties please add them in the comments. Thank you.

Demo Code: The link to the demo code at the end of this video is broken. I have a copy of the demo code, Schwartz emailed it to me. I'm waiting for his permission to make it available as a download on this post. It does require the Konopka Signature Controls (formerly Raize components). 

I found this very interesting.

CodeRage9
Have You Embraced Your Inner Software Plumber Yet?
David Schwartz


https://youtu.be/qqKx8fQTTfI

Here are time jumps to specific sections:

00:41 Overview:
14:35 Summary

External References:

Saturday, April 24, 2021

Delphi Tip of the Day - Toggle Visibility On/Off

I'm porting over one of my Delphi 5 VCL, desktop applications to FMX. The target audience are Windows and macOS users. I'm not focused on mobile at this juncture. I'm spending quite a bit of time on the User Experience (UX). I guess you would call this approach "Desktop UX First".

I want to give the user the option of showing or hiding panels. I've decided to place this functionality in two places:

  1. On the main menu as an option.
  2. On the bottom tool bar as a button.
The first thing that came to mind was testing the "IsChecked" state of the main menu option. I slept on it and came back to the drawing board the next day. Instead of thinking about trapping clicks, I thought about what the intent of the click really was. And the answer is to show or hide the panel.

If the user clicks either the main menu option or the toolbar button I want the panel to show or hide. Both of these options need to work together behind the scenes. The intent of either click focuses on the "visibility" of the panel. And wouldn't you know, TPanel has a Visible property.

Visible is a boolean value, meaning it has only two states. True/False. And in Delphi there is a very cleaver way to toggle the state of a boolean value. This can be a little tricky to wrap your had around at first. However, once you understand it, you'll love it.

Boolean Value becomes not Boolean Value;
Boolean Value (True) becomes not Boolean Value (True);
Boolean Value (False) becomes not Boolean Value (False);
Boolean Value := not Boolean Value;

Panel.Visibile becomes not Panel.Visibile;
Panel.Visibile (True) becomes not Panel.Visibile (True);
Panel.Visibile (False) becomes not Panel.Visibile (False);
Panel.Visibile := not Panel.Visibile;

The statement Panel.Visibile := not Panel.Visibile; 
toggles the value, back and forth between True and False.

Let's see how to put this to use in the real world. In Delphi create a new FMX application. 
Click File > New > Multi-Device Application - Delphi and choose Blank Application.

Add the following components:
TMainMenu
TPanel x2
TToolbar
TButton
TSplitter
TStatusBar

Structure the components so they are parented like this:



Your form should look similar to this:


The goal is to toggle the Left Panel visibility. When you first run the application the form opens with the default settings. We want both the MenuItem (Show Left Panel) and the ToolBar Button to work together.




Hiding the Left Panel the form changes accordingly.


Regardless of which method was used to Show/Hide the left panel both items stay in synch by calling on procedure ToggleLeftPanelOnOff.

I'm testing the Sender to make sure it was invoked by either a TMenuItem or a TButton control before I toggle the panel visibility. Although it's not displayed here this allows for calling ToggleLeftPanelOnOff from inside the form's OnShow method in essence setting the correct values without toggling the panels visibility.

Here is the program code:

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.StdCtrls,
  FMX.Controls.Presentation, FMX.Menus;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    StatusBar1: TStatusBar;
    pnlLeft: TPanel;
    pnlMain: TPanel;
    splLeft: TSplitter;
    tbarMain: TToolBar;
    btnTBarLeft: TButton;
    mnuFile: TMenuItem;
    menuOptions: TMenuItem;
    mnuShowLeftPanel: TMenuItem;
    mnuClose: TMenuItem;
    procedure mnuCloseClick(Sender: TObject);
    procedure mnuShowLeftPanelClick(Sender: TObject);
    procedure btnTBarLeftClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
   procedure ToggleLeftPanelOnOff(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.btnTBarLeftClick(Sender: TObject);
begin
  ToggleLeftPanelOnOff(Sender);
end;

procedure TForm1.mnuCloseClick(Sender: TObject);
begin
  Close;
end;

procedure TForm1.mnuShowLeftPanelClick(Sender: TObject);
begin
  ToggleLeftPanelOnOff(Sender);
end;

procedure TForm1.ToggleLeftPanelOnOff(Sender: TObject);
begin
  // ==================================================================
  // Only toggle visibility if invoked by a menuitem or button click.
  // ==================================================================
  if (Sender is TMenuItem) or (Sender is TButton) then
    pnlLeft.Visible := not pnlLeft.visible;

  // ==================================================================
  // Set menuitem and button properties
  // ==================================================================
  if pnlLeft.Visible then
  begin
    mnuShowLeftPanel.IsChecked := True;
    btnTBarLeft.StyleLookup := 'arrowlefttoolbutton';
  end
  else
  begin
    mnuShowLeftPanel.IsChecked := False;
    btnTBarLeft.StyleLookup := 'arrowrighttoolbutton';
  end;

end;

end.

Here is the text version of the Form:


object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Toggle Demo'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object StatusBar1: TStatusBar
    Position.Y = 458.000000000000000000
    ShowSizeGrip = True
    Size.Width = 640.000000000000000000
    Size.Height = 22.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 1
  end
  object pnlLeft: TPanel
    Align = Left
    Size.Width = 161.000000000000000000
    Size.Height = 458.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 2
  end
  object pnlMain: TPanel
    Align = Client
    Size.Width = 475.000000000000000000
    Size.Height = 458.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 3
    object tbarMain: TToolBar
      Align = Bottom
      Position.Y = 418.000000000000000000
      Size.Width = 475.000000000000000000
      Size.Height = 40.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
      object btnTBarLeft: TButton
        Align = Left
        Size.Width = 40.000000000000000000
        Size.Height = 40.000000000000000000
        Size.PlatformDefault = False
        StyleLookup = 'arrowlefttoolbutton'
        TabOrder = 0
        Text = 'btnTBarLeft'
        OnClick = btnTBarLeftClick
      end
    end
  end
  object splLeft: TSplitter
    Align = Left
    Cursor = crHSplit
    MinSize = 20.000000000000000000
    Position.X = 161.000000000000000000
    Size.Width = 4.000000000000000000
    Size.Height = 458.000000000000000000
    Size.PlatformDefault = False
  end
  object MainMenu1: TMainMenu
    Left = 304
    Top = 224
    object mnuFile: TMenuItem
      Text = 'File'
      object mnuClose: TMenuItem
        Locked = True
        Text = 'Close'
        OnClick = mnuCloseClick
      end
    end
    object menuOptions: TMenuItem
      Text = 'Options'
      object mnuShowLeftPanel: TMenuItem
        Locked = True
        IsChecked = True
        Text = 'Show Left Panel'
        OnClick = mnuShowLeftPanelClick
      end
    end
  end
end


Enjoy,
Gunny Mike

Thursday, April 8, 2021

Turbo Boost Your Delphi Knowledge - Become a Docwiki Ninja Warrior

I've made a commitment to learn FireMonkey. My flagship software product, Zilch Standard, turned 30 years old in 2021 and I still don't have a macOS version. I've got macOS consumers who buy my Windows® software and then email asking if there's a version that runs on their mac computer. This inevitably leads to me issuing a refund. So, I have a pretty strong incentive to learn FireMonkey.

"I feel like I'm sitting in the cockpit of an airplane."

I tried going down the FireMonkey learning path before but unfortunately I didn't get very far. Learning FireMonkey makes me feel like I'm sitting in the cockpit of an airplane. There's so many things that are unfamiliar. The scope of it all is overwhelming. There's so much to learn. I don't know where to look first. What about the help? It's just an [F1] key press away!

I don't know about you but I get frustrated at the built-in help that comes with Delphi? Does this sound familiar? You're frantically trying to figure something out... pressing [F1] all over the place, and hopelessly rummaging around through Delphi's built-in help. Sometimes it's great and gives you what you exactly what are looking for. Often times you are left feeling like you just read a bunch of cryptic tea leaves. 

Where do you turn at this point? The Facebook Delphi groups? Stackoverflow?  Your stash of Delphi books? Delphi's dockwiki?

In the past I've rarely thought to use Delphi's docwiki. In my mind I felt like it was the same rehashed [F1], cryptic leaves stuff. Well, that changed last night. 

It turns out, I wasn't using the dockwiki in a meaningful way. I figured out how to exploit the value of the docwiki. I'm going to show you how to become a docwiki ninja warrior.

"I'll show you how to become a Delphi Docwiki Ninja"

It all started last night when I wanted to learn more about FormFactor. I wrote a simple FMX application that displays the ClientHeight, ClientWidth, FormFactor.Width, and FormFactor.Height in the OnResize event handler. I was curious why the FormFactor values never changed as the form was resized, so I wanted to learn more. That's when I highlighted FormFactor in the Object Inspector and pushed [F1] .


This brought up the built-in help for FormFactor. This is one of those cryptic tea leaves help reference.



This wasn't very helpful. I may have done some googling to learn more but couldn't find anything that talked about FormFactor. What it is? How it's used? Why it's used? So I posted my question to StackOverflow

Someone commented and said "Please look at the documentation. It seems to concern iOS only, and changes according target device selection."

How did he find that docwiki page? That's not the docwiki page I found. In fact I couldn't find the dockwiki page referenced in StackOverflow comment. Turns out I didn't understand how to use the dockwiki. I was stuck in the API library and couldn't got out!

I was stuck in the API library and couldn't get out!

That's when I discovered how to become a Docwiki Ninja Warrior. This takes less than a minute to setup and I believe it will save you hours looking for information about Delphi that is relevant to what you are looking for. For illustrative purposes I'm sticking with my original pursuit of FormFactor.

Step 1: From inside the IDE click Help > RAD Studio Docwiki


Step 2: This opens the RAD Studio docwiki page in your default browser.
Step 3: Right-click on Library Reference > Open link in new tab 


Step 4: This opens the Library docwiki page in a new browser tab.
Step 5: Right-click on Code Example > Open link in a new tab.


At this point you should have three tabs in your browser each dedicated to separate docwiki sections. And now the fun begins.

Step 6: Enter FormFactor in the search box for tab 1 RAD Studio and press [Enter]. I'm horrible at spelling so I usually just copy and paste the value I need. I just highlighted FormFactor in the IDE code editor and pasted it in the search box. 





Step 7: Switch to tab 2 Library docwiki page and paste or enter FormFactor in the search box and press [Enter].





Step 8: Switch to tab 3 Code Examples docwiki and paste or enter FormFactor in the search box and press [Enter].


"So, what did I learn about FormFactor?"

FormFactor is only used used when you are creating an iOS application. This is awesome. I learned enough about FormFactor to satisfy my current need. Because I'm focused right now on learning how to use FireMonkey to create desktop applications for Windows and macOS, FormFactor is not relevant to my current situation. This lets me know I can skip a thorough investigation about FormFactor for the time being. It also lets me know that ignoring FormFactor at this time is okay since it does not apply to desktop applications for Windows or macOS. I don't need to be concearned about FOMO (fear of missing out).


However, if FormFactor was something I was interested in, the three different docwikis provide ample links to related, relevant, information in one convenient location. 

Oh yeah, make sure to play around with the "Advanced" link on the special search results pages.

There you have it. I am so glad I stumbled upon this. It will surely be very helpful in my quest to learn FireMonkey. 

Enjoy!
Semper Fi,
Gunny Mike