How To Save A Window’s Size & Position In Delphi

July 19, 2008

How do you save the position and size of a given window based on a user’s preference, and then use the saved settings next time you open the window?

The solution to this problem is quite simple. First, you must decide how to save the settings. The three most common ways are:

  1. Use an INI File – Typically one user per computer
  2. Use the Windows Registry – Can be for a single user, or for multiple users with different accounts sharing the same computer
  3. Use a database table – Client/Server environmnet where one user can use any networked computer

I will only cover the first method – the use of an INI file to save the settings. The concept is the same for all three:

When the window is opened, check to see if you should load any saved settings and if they had been saved. If so, use the settings to display the window. Otherwise, load the default window settings (design settings). Before closing the window, check to see if you should save any settings. If so, save the settings and exit. You can tweak and customize the code to your specifications and liking, and modify it to suit your choice of storing methodology.

For this example, we’ll use the main form (Window), drop a panel onto it and a check-box onto the panel.

To keep the panel always centered in the window, add the following code to the Form’s OnResize Event:

myPanel.Top := frmMain.ClientHeight div 2 - myPanel.Height div 2;
myPanel.Left := frmMain.ClientWidth div 2 - myPanel.Width div 2;

In the private declarations of the interface section, add:

myINIFile : TINIFile;

The above line declares myINIFile as an INI file and makes it available to all procedures in this unit.

Add “INIFiles” to the USES section under INTERFACE.

Following is the commented code for the Form’s OnCreate Event:

procedure TfrmMain.FormCreate(Sender: TObject);
var
myFileName : String; // This will hold the full path and name of our INI file for easy reference
SaveSettings : Integer; // If the value of this variable is '1', the settings are saved
begin
// The next line sets the full path and name of our INI file based on the location of the executable.
myFileName := ExtractFilePath( Application.ExeName ) + 'FormSettings.ini';

myINIFile := TINIFile.Create(myFileName); // Initializes the INI file and makes it available for use

// We will use a try-finally-end block to ensure the proper handling of resources
try
// The function ReadInteger is used to read an integer from the INI file. It takes three
// parameters. The first one is the Section of the INI file. The second is the name of the key
// from which the value is retrieved. The third parameter is the integer value that should be
// returned if: (1) The Section does not exist; (2) The Key does not exist; (3) The Key does not
// have an assigned value.

SaveSettings := myINIFile.ReadInteger('Preferences', 'SaveSettings', -1);
If SaveSettings = 1 then
Begin
cbSave.Checked := True;
With myINIFile do
begin
self.Top := ReadInteger('MainForm', 'Top', -1);
self.Left := ReadInteger('MainForm', 'Left', -1);
self.Height := ReadInteger('MainForm', 'Height', -1);
self.Width := ReadInteger('MainForm', 'Width', -1);
end;
End
Else cbSave.Checked := False;
finally
myINIFile.Free; // Frees the resources of the INI file
end;
end;

Following is the commented code for the Form’s OnDestroy Event:

procedure TfrmMain.FormDestroy(Sender: TObject);
var
myFileName : String; // This will hold the full path and name of our INI file for easy reference
begin
// The next line sets the full path and name of our INI file based on the location of the executable.
myFileName := ExtractFilePath( Application.ExeName ) + 'FormSettings.ini';

myINIFile := TINIFile.Create(myFileName); // Initializes the INI file and makes it available for use

// We will use a try-finally-end block to ensure the proper handling of resources
try
// The function WriteInteger is used to write an integer value to a key in the INI file. It takes three
// parameters. The first one is the Section of the INI file. The second is the name of the key
// to which the value is written. The third parameter is the actual integer value.

With myINIFile do
Begin
If cbSave.Checked then
begin
WriteInteger('Preferences', 'SaveSettings', 1);
WriteInteger('MainForm', 'Top', self.Top);
WriteInteger('MainForm', 'Left', self.Left);
WriteInteger('MainForm', 'Height', self.Height);
WriteInteger('MainForm', 'Width', self.Width);
end
else WriteInteger('Preferences', 'SaveSettings', 0);
End;
finally
myINIFile.Free;
end;
end;

Source: Online Delphi Training


No GUI Delphi applications

May 16, 2008

Guess A Number

Let’s create a simple console game. The computer will randomly pick an integer number from 0 to 50. Your task is to guess the number. Each time you pick a number a program will tell that your number is larger or smaller than the one you are looking for. When, finally, you find what the number was it’ll tell you how many times it took you to find it.

I’ll give you the code, but first let’s see what are two most seen commands in a console application:
Write and Read RTL procedures are typically used for writing and reading from a file. There are two standard text-file variables, Input and Output. In a Console application, Delphi automatically associates the Input and Output files with the application’s console window. The standard file variable Input is a read-only file associated with the operating system’s standard input (typically the keyboard). The standard file variable Output is a write-only file associated with the operating system’s standard output (typically the display).
Thus, Writeln is used to display a message; ReadLn is normally used to read in variables. In the code below, you will notice it ends with a ReadLn. Readln without any parameters simply waits for the [Enter] key to be pressed. One of the peculiarities of a console application is that when it has stopped running, the console window is automatically closed. The ReadLn statement is necessary so that the user can see any text produced by Writeln statements before it disappears off the screen when the program finishes.

Here goes the code. I hope you understand it.

program GuessANumber;
{$APPTYPE CONSOLE}
uses
  SysUtils;

var
 rn, un, cnt: Integer;
 guess: Boolean;

begin
  Randomize;
  rn := Trunc(Random(50) + 1);
  Write('Computer has picked an integer number,');
  Write('from 1 to 50, guess the number!');
  WriteLn('Your guess is: ');
  cnt := 1;  un := 0;
  Guess := False;
  while Guess = False do begin
   ReadLn(un);
   if un > rn then
     Write('Wrong, gimme a smaller number: ')
   else if un < rn then
     Write('Wrong, gimme a larger number: ')
   else //un=rn
     begin
       Guess:=True;
       Writeln;
       Write('Correct! It took you ' +
             IntToStr(cnt) +
             ' times to guess!')
     end;
   cnt := cnt + 1;
  end; //while
  ReadLn; //don't close the window, wait for [Enter]
end.

Simply run the project and play....



Message Box in Delphi

March 2, 2008

The best way to learn something is by example, so, I’ve decided to include an example.

if MessageBox(0, ‘Choose an option from below’, ‘Options’, +mb_YesNo +mb_ICONWARNING) = 6 then
ShowMessage (‘You clicked yes’)
else
ShowMessage (‘You clicked no’);

You’ll notice that the first line asks if the MessageBox = 6. That 6 means that the user clicked yes.

Here, I will provide all 7 possibilities.
0: Not enough memory to show the message box.
1: The user clicked the OK Button.
2: The user clicked the Cancel Button.
3: The user clicked the Abort Button.
4: The user clicked the Retry Button.
5: The user clicked the Ignore Button.
6: The user clicked the Yes Button.
7: The user clicked the No Button.

Of course, as I showed you above, there’s other buttons you could choose. You could easilly have the following:

MessageBox(0, ‘More Options’, ‘More Options’, +mb_ABORTRETRYIGNORE +mb_ICONWARNING);

That MessageBox will show the abort retry and ignore buttons. You can even combine different buttons to get different messageboxes like this:

MessageBox(0, ‘Save the document before starting a new one?’, ‘Save Warning’, +mb_YesNo +MB_ABORTRETRYIGNORE +mb_ICONWARNING);

The results start to get strange though, you’ll see what I mean if you try that one out for yourself. Go ahead, you won’t hurt anything. One last thing about messageboxes is the icons that you can get. You can get that yellow triangle with the exclamation mark as I pointed out, or you could get the information icon like this:

MessageBox(0, ‘Save the document before starting a new one?’, ‘Save Warning’, +mb_YesNo +mb_ICONINFORMATION);

Getting the icon with the X in it is done in a simmilar fassion. Just replace +mb_ICONINFORMATION with +mb_ICONSTOP. If you want the one with the questionmark in it, then just replace that with +mb_ICONQUESTION. If you don’t want an icon, then just don’t tell it what icon to put and you won’t get an icon. One last quick tip, if you want a plain messagebox that just says OK in it without showing an icon, then you can just put this:

ShowMessage(‘This is the message you want to be shown’);

Notice: To handle message box to stay on top, you should change ‘0’ value to ‘handle’ string.


Convert Between BMP and JPG With Delphi

January 23, 2008

Need to convert BMP to JPG or JPG to BMP with Delphi?
Don’t worry, this should help you out! 😉

// convert bmp to jpg

uses jpeg;

procedure TForm1.Button1Click(Sender: TObject);
var
bmp : TImage;
jpg : TJpegImage;
begin
bmp := TImage.Create(nil);
jpg := TJpegImage.Create;
bmp.picture.bitmap.LoadFromFile ( ‘c:\gambar.bmp’ );
jpg.Assign( bmp.picture.bitmap );
jpg.SaveToFile ( ‘c:\gambar.jpg’ );
jpg.Free;
bmp.Free;
end;

//convert jpg to bmp

uses
JPEG;

procedure JPEGtoBMP(const FileName: TFileName);
var
jpeg: TJPEGImage;
bmp: TBitmap;
begin
jpeg := TJPEGImage.Create;
try
jpeg.CompressionQuality := 100; {Default Value}
jpeg.LoadFromFile(FileName);
bmp := TBitmap.Create;
try
bmp.Assign(jpeg);
bmp.SaveTofile(ChangeFileExt(FileName, ‘.bmp’));
finally
bmp.Free
end;
finally
jpeg.Free
end;
end;