HOME - - - - - Lazarus Tutorials TOC - - - - - - Other material for programmers

Lazarus/ Delphi Tips and Tricks

Things every program should have

file: lt1Ne.htm

Most of this is just things I like to see in any program. I don't think any are required by Lazarus... but many of them are things you ought to do somehow, just as a matter of Good programming Practice.... in my opinion. That opinion has been honed by many years of paying the price of not doing some good programming practices.

This page is a minor one in the general universe of my tutorials on programming; it is not a typical page.

Alternative source

The page you are reading now is good for a discussion of some of my "should be in every app's code" ideas.

If you just want to take advantage of my ideas, go to my July 2022 page which is mainly about something else, but which has a "boilerplate" project with the my "should be in"s in it. You can download a .zip with all of the parts of the project in it. Fetch. Unzip. Click the .lpi file.

(You will be able to "strip out" the other stuff in that project easily.)

Not only is everything in place for you... including a simple (but extendable) ini file system, but the code is Just That Little Bit Better, because I wrote it several years after I wrote the page you are reading.

So... to learn: This page. To use: The page the link above takes you to.

Naming Of Parts

I've been writing programs for a long time. I.e. producing code to make an app. In what follows, where you see "app", or "application", I mean what you may call "a program". When I refer to "code", I am speaking of the stuff that makes computers do things. (Not what the spies... and personal-privacy-aware modern people... use!)

Give the app a PRODUCT CODE

All of my apps have a short "name", or "model number", "product code". For instance, I have a number of apps which Teach MAthematics. Their names are things like TMA005, TMA025.

Having a "code" for each app makes record keeping so much easier and robust. There are also times when being able to say "that one" very concisely is useful.

Mainstream programs also get more human friendly names... for instance, TMA036 is also known as "Goldie's Game", because it was inspired by a teacher at Radleigh School, England. The .exe is called TMA036.exe, but there is nothing to stop users from setting up a shortcut which offers "Goldie's Game- TMA036".

Note, by the way the padding of numbers to maybe two, better three digits by leading zeros. If you do this, the folders for your work will appear in numerical order in directory listings.

Once the app has a product code, you can make the "button" on a Windows taskbar give the product code with, in the FormCreate event handler with....

  application.title:='LT999';

Track the VERSION

Call it what you like, but somewhere, somehow, put into your code an indication of what version the copy you are looking at is. And make that visible to users of your code.

My approach...

I put a constant which I always call "vers" in near the top of the code. Constants are a little funny... you DO put the semi-colon at the end of the line, but the thing that is very like an assignment is done with just and equals sign, not an ":="

  const vers='26 Jan 16';

I simply use the current date for a version ID. If I need to note a second version on a given day, I add "b" the first time, "c" after that, etc. I never use "a", to avoid having both a "26Jan16" AND a "26Jan16a", and thus creating a chance for confusion.

Once you have established "vers", I generally, in the FormCreate handler, do something like....

  LT999f1.caption:='LT999- Demo of Lazarus Prgmming. Vers '+ vers;

.. which will put the text, and the app's current version in the title bar of the app's window. (You will need to change the LT999f1 you see above to the name of your application's main form.)

You don't need to update the version ID every time you make the slightest change to the code.... but if you have saved a backup copy, or saved a copy on a second storage device, or printed hardcopy, and you change the code, change the version ID. In other words, protect yourself from even a remote possibility of having two copies of the code, or an .exe file, in front of you which are different, but which do not have, built in, something to tell you which of them is the newer.

Related to "version"

It is difficult to have too many rems (remarks, comments) in your code. I keep a rough log of the app's development at the head of the code. Just a bunch of rems recording problems encountered, and when they were solved. Ditto, in the same series of comments, features added.

Just under the line defining the vers constant, I like to jot a short note about when I started writing the app, including what was going on in my life that day. It is amusing, from time to time when revisiting the code, to see how long it has been around, what I was doing back then.

Use Range Checking

"Range checking" is a tool that is turned off by default. If you have an app where execution speed is a problem, you may get some speed gains by turning range checking off again, after you've built the app... but while you are working on it, I would recommend turning range checking on. There is a compiler directive {$R} which is DIFFERENT from the range checking controls, {$R+} and {$R-}.

{$R} can't appear on it's own. If a + or - follow, you turn range checking on or off. Otherwise, $R should be followed by something like the standard *.lfm, which tells the compiler where to find something. (I've never had need of messing with this, and so am not fully informed as to what $R *.lfm sets!)

Because of the potential for confusion, I usually put my $R+ just after the $R *.lfm that appears "automatically" when you start a new app....

  implementation
  {$R *.lfm}
  {$R+}

A LINK to your website

There fancier ways to send people to your website, but the following is a simple way to send people there....

Put a button on your page saying "Click here to copy http://sheepdogsoftware.co.uk to your clipboard".

Put the following in the Click event handler...

  Clipboard.Clear;
  Clipboard.AsText:='https://sheepdogguides.com/lut/lt3Ng-1.htm';

... and, so that it will work, put "Clipbrd" in the app's uses clause.

(My thanks to http://wiki.lazarus.freepascal.org/Clipboard for showing me how to do that!)

What HAS FOCUS at start?

I often put a "Quit" button on my apps. And, when I've not been careful, the app launches with that button having the focus. In which case, if the user presses the "Enter" key, the app closes.

Now... hopefully, we never hit the enter key without knowing what we are doing. But sometimes Mr. Murphy "helps".

I like to make sure that something relatively harmless has the focus when the app launches.

If you don't do anything else, the tab order will determine what has focus. (And setting up a good tab order is a good idea.)

To make sure that, say, the button called buAddComment has focus when the app launches, here is what you do....

Put...

  buAddCommment.setfocus;

... to your code.

Easy, you say! And it is. Just don't put it in the "obvious" place, the FormCreate event handler. That will not work... you are trying to give the focus to something which doesn't, as far as Windows is concerned, may not yet exist. The form... and the buttons on it... are still being created during the FormCreate handler. Ah! Gotcha!

However, there is another event, FormActivate, which is a good place to put the setfocus command. The button won't be given focus every time you maximize, restore, etc, the form. It won't be given focus if you have gone off to a different app, and then come back. But the button will have focus when the app launches.

(The tab order property of your controls is, by the way, Good For You, too. And let's say you have five things assigned numbers so that tabbing will cycle through them. If you set the "enabled" property of one of them to false, it doesn't faze the tabbing process. The computer just skips over any disabled controls which it would otherwise visit.)

Something a little harder- INI FILES

So far, my suggestions have been easy to implement.

Not so easy, and something more open to debate, is the idea of giving every program an "ini" file. (I believe Linux users would call it a "config" file.)

Now-a-days, in Windows, at least, we are "encouraged" to use the registry. Fine... if you really need it. I am too humble to want to mess with something so central to the smooth running of my customer's PCs. My apps are not so grand as to need to use the registry.

The downside, and I think it a minor one, is that you have to have permission to write to the disk of whatever system the app is running on.

Furthermore, I like to put the ini file in the same folder as the app... another decision with its pros and cons.

But, please: At least consider using an ini file, if only to "remember" the position and sizing of the window when the user was done with your app.

How To Do Ini Files is discussed in greater depth in the tutorial the link will take you to, however...

Here's a very sketchy indication of some of the basics...

Put "IniFiles" in the application's "Uses" clause.

Set up a global variable, sIniFileName.

procedure TLDN006f1.FormCreate(Sender: TObject);
var wHour, wMin, wSec, wMilli : Word;//Needed for DecodeTime
    dfIniFile:TIniFile;//"df" in name from "datafile". Could be anything.
begin
  sIniFileName:='LT999ini.txt';
  DecodeTime(now, wHour, wMin, wSec,wMilli);//Built into Lazarus and Delphi
      //"now" is a built in function to pick up the current time from your system.
  bThisOpening:=wMin;
  laThisOpening.caption:=inttostr(bThisOpening);

  //Heart of reading from ini file
  dfIniFile:=TIniFile.Create(sIniFileName);

  with dfIniFile do begin
     bPrevOpening:=ReadInteger('Previously','Opened At',255);
     end;//with...

  dfIniFile.Free;
//End of "Heart of...."

//Now use what you read....
  if bPrevOpening=255
    then laPrevOpening.caption:='No record of previous opening'//no ; here
    else laPrevOpening.caption:=IntToStr(bPrevOpening);

end;//FormCreate

... and, to save- to- ini- file what was in application when it closes....

procedure TLDN006f1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var dfIniFile:TInifile;
begin
 dfIniFile:=TIniFile.Create(sIniFileName);
 with dfIniFile do begin

  WriteInteger('Previously','Opened At',bPrevOpening);

  end;//with...
 dfIniFile.Free;

end;//Of FormClose

I hope the above has useful bits!





Search across all my sites with the Google search...

Custom Search
            powered by FreeFind
  Site search Web search
Site Map    What's New    Search This search merely looks for the words you enter. It won't answer "Where can I download InpOut32?"
Ad from page's editor: Yes.. I do enjoy compiling these things for you. I hope they are helpful. However... this doesn't pay my bills!!! Sheepdog Software (tm) is supposed to help do that, so if you found this stuff useful, (and you run a Windows or MS-DOS PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.

Link to Lazarus Tutorials main page
How to contact the editor of this page, Tom Boyd



Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes. There were two "unknown attributes" in Google+ button code. Sigh.


If this page causes a script to run, why? Because of things like Google panels, and the code for the search button. Why do I mention scripts? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....