Home

News

Articles

Forums / Groups

Mozilla-Delphi Project

Pascal Newsletter
Issue 50
Back Issues

Software

Links

Search

Vote For Us:
Irongut's Delphi Pages
Pascal Newsletter

Contact Details

Legal Stuff

News Archive
Pascal Newsletter Issue 50
Pascal Newsletter #50 - 25-JULY-2004

Contents

1. A Few Words From the Editors
2. Getting a Drive's Type
3. Inno Setup Review
4. How to Run a Single Instance of an Application (Part 1)
5. Forums / Mailing Lists
6. Delphi on the Net
   - Components, Libraries and Utilities
     - Shareware / Commercial
     - Freeware
     - Borland Product Updates
   - Articles, Tips and Tricks
   - Tutorials and Training
   - News
   - Other Links

________________________________________________________________________


1. A Few Words From the Editors


It's been almost a year since the last issue of the newsletter and
during that time we've both been very busy with work, family and other
projects. We've spoken several times about getting it going again but
never quite managed it. After some prodding and messages of support from
subscribers (and some work by Dave) we're finally back. The plan is to
publish an issue every two months from now on, provided we can find the
contributions, prizes and time. :)

As usual we'd like to thank the authors who contributed articles for
this issue, Lennie De Villiers and Peter Johnson. And, we're pleased to
award them the prizes for this issue:

* Lennie De Villiers - 'Getting a Drive's Type'
  Storage Library v3.29 - by Deepsoftware.Ru ($39)
  Storage library - elegant way for application settings management.
  Supports working with ini files, registry, xml files, TStream objects.
  Provides encryption, unicode support, working with published
  properties without programming, saving form position and much more...
  http://www.deepsoftware.ru/rsllib/index.html

* Peter Johnson - 'How to Run a Single Instance of an Application'
  SMExport Suite v4.50 - by Scalabium Software ($50)
  SMExport suite is a component set for easy data exporting into
  different file formats: CSV/Text, MS Excel, MS Access, MS Word, HTML,
  XML, SPSS, PDF, RTF, SQL etc. Available for Delphi 3-7 and BCB 3-6.
  http://www.scalabium.com/   (mshkolnik@scalabium.com)

We hope to have two prizes for contributors to the next issue but don't
know what they will be yet. So send us your articles and maybe you'll
get a nice surprise.

Well, this is it. We hope you enjoy this issue.

Regards,

Dave Murray and Ernesto De Spirito
pascal-newsletter-owner@yahoogroups.com

__________________

Collaborated in this issue: Lennie De Villiers, Peter Johnson

________________________________________________________________________

Help & Manual 3.50 by EC Software - Shareware ($ 299) - Help & Manual is
a  WYSIWYG help authoring tool  that will aid you in  creating  standard
WinHelp files (.HLP), Adobe PDF files, HTML pages  and the new HTML HELP
(.CHM) files introduced in Windows 98, as well as other file formats and
printed documentation,  everything from a single source. This is a must-
have for any software developer. http://www.helpandmanual.com/hmpage.htm
________________________________________________________________________


2. Getting a Drive's Type

   By Lennie De Villiers <Lennie at openmindconnections dot com>
      http://www.openmindconnections.com/


Sometimes you may want to determine whether a disk drive is removable,
fixed, CD-ROM, RAM disk, or network drive. To accomplish this you can
use the GetDriveType Windows API function.

GETDRIVETYPE
============

Declaration:
  GetDriveType(lpRootPathName : PChar);

Parameters
  lpRootPathName

Pointer to a null-terminated string that specifies the root directory of
the disk to return information about.  A trailing backslash is required.
If pRootPathName is NULL, the function uses the root of the current
directory.

Return Values
The return value specifies the type of drive. It can be one of the
following values:

· DRIVE_REMOVABLE
  The disk can be removed from the drive.

· DRIVE_FIXED
  The disk cannot be removed from the drive.

· DRIVE_REMOTE
  The drive is a remote (network) drive.

· DRIVE_CDROM
  The drive is a CD-ROM drive.
 
· DRIVE_RAMDISK
  The drive is a RAM disk.

The function will return a value of  DRIVE_UNKNOWN if the disk type
cannot be determined or a value of  DRIVE_NO_ROOT_DIR if the root path
is invalid.

For Example:
------------

  case GetDriveType(PChar(DriveEdit.Text + ':\')) of
   DRIVE_REMOVABLE:
    ReportLabel.Caption := 'The disk can be removed from the drive';
   DRIVE_FIXED:
    ReportLabel.Caption := 'The disk cannot be removed from the drive';
   DRIVE_REMOTE:
    ReportLabel.Caption := 'The drive is a remote (network) drive';
   DRIVE_CDROM: ReportLabel.Caption := 'The drive is a CD-ROM drive';
   DRIVE_RAMDISK: ReportLabel.Caption := 'The drive is a RAM disk';
   else
     Messagedlg('Error: Drive type cannot be determined or root path '+
                'invalid', mterror, [mbok], 0);
  end;

This example gets a drive-letter from an edit-box named DriveEdit and
passes it to the GetDriveType-function.  The code will automatically add
a trailing backslash ( :\ ).  The CASE statement will then report the
value returned by GetDriveType-function to a label named ReportLabel.

If GetDriveType doesn't return one of those values eg. it returns either
the DRIVE_UNKNOWN or DRIVE_NO_ROOT_DIR, an error message will be
displayed.

For a more complete reference to the GetDriveType WinAPI function, goto:
http://msdn.microsoft.com/library/psdk/winbase/filesio_2m3p.htm

________________________________________________________________________

Delphi-PRAXiS · One of the fastest growing German Delphi-forums, with
unique services like our "Delphi-PRAXiS Expert" (add-on which allows
access to our libraries directly from within the IDE). Our database
contains more than 50,000 articles. >>> http://www.delphipraxis.net <<<
________________________________________________________________________


3. Inno Setup Review

   By Dave Murray <irongut at vodafone dot net>
      http://www.paranoia.clara.net/


Inno Setup by Jordan Russell is a free installer for Windows programs.
First introduced in 1997, Inno Setup rivals and even surpasses many
commercial installers in feature set and stability. I've been using it
for a couple of years so I was keen to see what new features are in the
latest version. (4.2.7 2004-06-27)

Inno Setup is a script based installer for all 32-bit Windows versions.
It is very flexible and customisable and produces small, single EXE
installers. There are third-party extensions available and it supports
Pascal scripting for further customisation. Its key features include:

  * Support for all 32-bit Windows versions
  * Single EXE installer or disk spanning
  * Standard wizard interface, including latest Windows 2000/XP style
  * Customisable setup types; e.g. Full, Minimal, Custom
  * Complete uninstall capabilities
  * Zip, bzip2 and LZMA (7-Zip) compression
  * Compare version info, replace in-use files & shared file counting
  * Register DLLs, OCXs and type libraries
  * Install fonts
  * Create shortcuts anywhere; including Desktop and Quick Start
  * Create registry and .INI entries
  * Create multi-lingual installers
  * Silent install and uninstall
  * Run other programs or Pascal scripts during install
  * COM Automation support
  * Third-party extensions
  * Full source code available (Delphi 2 - 5)
  * Free of charge, even when deploying commercial applications


Working with Inno Setup
-----------------------

When you run Inno Setup you get a dialog offering to create a blank
script, create a new script using a wizard or open an existing script.
There are several examples that help explain how to create scripts or
perform certain tasks during installation. I recommend you use the
wizard to setup the initial outline of your script.

The wizard asks for all the usual information like application name and
version, company name and website, install directory, filenames and
shortcuts. It also has some more advanced options like creating an
Internet shortcut to your website and showing files before and/or after
installation.

Inno Setup scripts look very similar to inifiles. Each section of a
script controls a different aspect of the installation, for instance the
[Setup] section contains global settings used by the installer and
uninstaller and the [Tasks] section defines user-customisable tasks
performed during installation. Items within the sections can take one or
more parameters. For instance, the AppPublisherURL item in the [Setup]
section takes your website address. Most items can have constants
embedded in them that are translated to their literal values depending
on the user's choices and system configuration; e.g. {sys} refers to the
Windows System directory. There are a lot of sections and items but
don't worry, the documentation is excellent.

After you have finishing writing your script, the next step is to
compile it into a complete, ready-to-run installer. By default, it is
created in a subdirectory called Output under the directory containing
the script. There is also a command line compiler that can be used as
part of an automated build process.

The final step is to test your installer. The installer and uninstaller
programs accept optional command line parameters that can be useful to
system administrators and to other programs calling them. Parameters
include /SILENT, /LANG and /DIR. Both programs also return an exit code
which can be used to tell if and why an install or uninstall failed.


New in Version 4.0
------------------

Version 4 added run-time scripting support to Inno Setup. The scripting
engine is RemObjects Pascal Script by Carlo Kok. This modern Delphi-like
scripting language allows sophisticated customisation of your installer.
Possibilities include: adding custom wizard pages at run-time; removal
of types, components and/or tasks under custom conditions; installation
of items based on custom conditions. An integrated run-time debugger is
included.

Multilingual support has also been added and localised versions of all
the various information files can be specified. The [Languages] section
defines the languages available to the installer and a Select Language
dialog can be displayed. The optional [LangOptions] section can be used
to define language-specific settings such as fonts.

Many other new features and improvements were added in version 4. Some
of the more useful include unsafe files (DLLs), silent install /
uninstall, IDE improvements and disk spanning now supports CDs and DVDs.


Latest Features
---------------

(v4.1.3 2004-01-28)

Since I originally wrote this review several minor versions have
appeared with lots of improvements. The installer has undergone a
facelift with simplified wording, improved scaling of fonts and images
and improved multi-monitor support. It now contains customisable version
information and you can specify its icon.

COM Automation support provides the ability to control other
applications and call ActiveX DLLs during setup. This enables you to
configure IIS or SQL Server, read and write XML, read and write Office
documents and a whole lot more.

(v4.1.6 2004-02-19)

The guys behind Inno Setup must be working day and night because in the
last few weeks they've released three updates! The most significant
change is the addition of LZMA compression. LZMA is the algorithm used
by Igor Pavlov's 7-Zip archiver. Typically it compresses at least 20%
better than the existing bzip method.

The compiler IDE has been improved with a new Run | Terminate command
and a new Build | Low Priority During Compile option. The IDE also shows
an animated icon and progress bar during compilation and the exit code
returned after a test run.

(4.2.7 2004-06-27)

The four months since I last updated this article have seen a lot of
improvements to Inno Setup. Multilingual support has been greatly
improved. The script wizard now uses custom message constants so you
don't have to translate any English phrases in generated scripts. A new
[CustomMessages] section allows you to easily localise your own entry
descriptions and messages. By default, languages whose code page does
not match the user's system will not appear in the Select Language
dialog. And, official translations have been added in Catalan, Czech,
Dutch, French, German, Norwegian, Polish, Portuguese, Russian, and
Slovenian.

Inno Setup now includes optional 128-bit ARCFOUR encryption. The
decryption password can be provided on the command line for silent
installs. And, individual files can have encryption turned off with the
noencryption flag if necessary.

Enhancements introduced to the Add/Remove Programs Control Panel applet
in Windows 2000 are now supported. You can display a "Modify" button and
a "Support" dialog with comments, contact info and a link to your readme
file.

Compression now defaults to LZMA instead of Zip and a new optimisation
pass compresses executable files even further. A new /LOG command line
parameter creates a log file in the user's TEMP directory detailing the
installation process for debugging. The run-time scripting engine is now
based on RemObjects Pascal Script SVN code revision 916. There have been
a lot of other changes including improvements to the wizard pages and
dialogs and bug fixes.


Third-Party Extensions
----------------------

One of Inno Setup's strengths is the healthy community of third-party
extensions. These include tools like iwz2iss that converts InstallShield
projects into Inno Setup scripts and InnoScript that does the same for
VB projects.

The most useful extension is probably ISTool by Bjørnar Henden, a GUI
front-end for creating and editing Inno Setup scripts. It gives easy
access to all the sections of a script with custom dialogs for editing
the items. These dialogs contain fields for all the possible parameters
with check boxes for any possible flags. ISTool has full drag and drop
support; you can drag files from Explorer and drop them on a directory
in the [Files] section. It can also import VB and InstallShield projects
and simplifies the process of creating localised versions.

Several third-party extensions, including ISTool, have recently been
repackaged as the Inno Setup QuickStart Pack. They are not official or
required but make Inno Setup easier to use, especially for new users.


Support
-------

Support is provided primarily through newsgroups on news.jrsoftware.org.
There are three newsgroups available, for general Inno Setup issues, for
run-time Pascal scripts and for third-party extensions. These newsgroups
are available only through their news server or web-based interface.

A mailing list is also available to notify you of major new releases.
Announcements of small patches are generally not sent to the mailing
list but they are announced in the general newsgroup.


Conclusion
----------

Inno Setup is a great tool for packaging your applications. The scripts
are easy to write and the documentation is well written and exhaustive.
The initial wizard is actually very helpful and I use it for all my
scripts. Inno Setup is customisable and extensible and can be used as
part of an automated build process. When combined with some of the
third-party extensions, it is a product that's hard to beat and the
price is nice too!


References
----------

· Inno Setup
  http://www.jrsoftware.org/isinfo.php

· Inno Setup Newsgroups
  news://news.jrsoftware.org/jrsoftware.innosetup
  news://news.jrsoftware.org/jrsoftware.innosetup.code
  news://news.jrsoftware.org/jrsoftware.innosetup.thirdparty
  http://news.jrsoftware.org/read/
 
· ISTool
  http://www.istool.org/

· iwz2iss
  http://strony.wp.pl/wp/mikequ/eng/iwz2iss.htm

· InnoScript
  http://www.randem.com/innoscript/innoscript.htm

· RemObjects Pascal Script
  http://www.remobjects.com/

________________________________________________________________________

         Vote for the Pascal Newsletter in The Borland Top 100!
                   http://top100borland.com/in.php?who=20
________________________________________________________________________


4. How to Run a Single Instance of an Application
   Part 1: An Initial Approach

   By Peter Johnson, Copyright (c) 2003
      <delphidabbler at tiscali dot co dot uk>
      http://www.delphidabbler.com/


Abstract
--------

This article discusses how to ensure that just a single instance of an
application can be run. An application does this by checking if an
instance is already running and terminating if so. We also look at how a
duplicate instance can pass its command line parameters to the existing
instance before terminating.


Overview
--------

The method of preventing multiple application instances used here is
based on the detection of the existence of an application with a known
main window class and passing command line data using the WM_COPYDATA
message (as used by my Version Information Spy program at
http://www.delphidabbler.com/vis). There are other methods of achieving
the same ends -- a common one being the use of Mutexes and passing data
via a memory mapped file. This method is not discussed here, but there
are other articles on the net that show how to do this.

An outline of the methodology is:


search for a top level window of the correct class
if such a window exists
  activate the window
  pass any command line data to the window using WM_COPYDATA
  terminate this application instance
else
  start this application as normal
  process the command line parameters
end


We will now examine the process in detail.


Finding if Your Program is Running
----------------------------------

We use the FindWindow Windows API routine to search for a top level
window of the required class. This routine can check for window
captions, (unreliable because they can change while a program is
running), the window class name (better) or both. We opt to check for
the window class name regardless of the caption. There is one problem
with this approach however -- in Delphi the class name of the main form
is used as the window class name of the top level window by default.
E.g. If a form's class is TForm1 the window class name is also TForm1.
Since it's possible to have more than one Delphi application running
that uses this window class name we need to give our program's main
window a name that is (very) unlikely to be used by another application.
We do this by overriding the main form's CreateParams method as follows:


procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  StrCopy(Params.WinClassName, cWindowClassName);
end;


Here cWindowClassName is a const set to some suitable class name. To
ensure uniqueness we could use a GUID such as
D9CE4126-B845-42B2-ABAE-3678FF6EC836. However I find that a name based
on company name, the name of the application and possibly the major
version number is sufficiently unlikely to be used by other
applications. An example would be DelphiDabbler.MyApp.2.

Now that we have a suitable window class name we can find the main
window handle of any already existing instance of our application using
the following function:


function DuplicateAppInstWdw: HWND;
begin
  Result := FindWindow(cWindowClassName, nil);
end;


The function will return the handle of any top level window with the
class name given by the cWindowClassName constant. It will return 0 if
there is no such window. So, if the function returns 0 we have no
existing instance and can run our application, but if the function
returns a non zero value an existing instance is already running and we
should terminate our current instance.

We need to be very careful where we place this test -- if we run this
check after we have created our application's main window the function
will always return a window handle, and this may be the handle of our
own window! Therefore it is important to run this check before the
application creates its main form. We can do this by performing the
check in the project (.dpr) file, before the main form is created. The
project file can be modified as follows:


function CanStart: Boolean;
var
  Wdw: HWND;
begin
  Wdw := DuplicateAppInstWdw;
  if Wdw = 0 then
    // no instance running: we can start our app
    Result := True
  else
    // instance running: try to pass command line to it
    // terminate this instance if this succeeds
    // (routine explained later)
    Result := not SwitchToPrevInst(Wdw);
end;

begin
  if CanStart then
  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end;
end.


Note that the application is only started if the CanStart function
returns true, otherwise it instantly terminates. CanStart returns true
if there is no other instance of the application (i.e. no top level
window has been found with the main window class name). If a previous
instance has been found we attempt to switch to it using the
SwitchToPrevInst function. The implementation of this function is
explained later in the article. For now it suffices to know that the
function activates the main window of the previous application instance
and attempts to pass any command line parameters to it. The function
returns true if this succeeds and false if it fails. Note that we go
ahead and start this instance of the application if the attempt to pass
the command line to the previous instance does not succeed. This is a
fail safe way of ensuring our command line gets processed.

That just about wraps up how to start a single instance of the
application. Now we need to find out how to pass any command line data
to the previous instance.


Passing the Command Line to a Previous Instance
-----------------------------------------------

When the program detects that another instance is running it must pass
its command line parameters to the program already running. We do this
in the SendParamsToPrevInstance routine. This routine sends the
parameters to the main window of the existing application instance by
using the WM_COPYDATA message.


Passing Data to Another Application with WM_COPYDATA
----------------------------------------------------

This message is provided by Windows for the purpose of passing data
across process boundaries -- i.e. for sending data to other
applications. Because the message sends data between address spaces we
have to be careful to adhere the rules governing its use. The rules are:

* We can't pass pointers, only actual data
* The sending application must allocate and free the memory required for
  the data
* The receiving application must not free the data
* The receiving application must copy the data to local storage if it is
  to be accessed after the message handler has returned
* We must use SendMessage and not PostMessage to send the message

The WM_COPYDATA message uses a structure of type TCopyDataStruct to
store and describe the data to be sent. This structure has three fields:

* dwData: DWORD -- holds a user defined 32 bit value
* lpData: Pointer -- points to a user defined data block
                     (used if more than a 32 bit value is to be sent)
* cbData: DWORD -- is the size of the user defined data block


SendParamsToPrevInstance Function
---------------------------------

As noted above the SendParamsToPrevInstance function is used when we
have to pass command line parameters to a previous application instance.
The function returns true if the receiving application processes the
WM_COPYDATA message properly and false if the message is not handled or
the receiving application reports an error. Here is the implementation:


function SendParamsToPrevInstance(WndH: HWND): Boolean;
var
  CopyData: TCopyDataStruct;  // WM_COPYDATA data structure
  I: Integer;                 // loops through parameters
  DataSize: Integer;      // size of storage required for all parameters
  Data: PChar;                // pointer to parameter storage
  PData: PChar;               // pointer to next parameter in storage
begin
  // Set up data packet to be sent to other instance
  // contains COPIES of parameters: can't send pointers in WM_COPYDATA
  // we will store each parameter string in buffer, separated by #0 and
  // terminated by second #0 e.g. First#0Second#0Third#0#0

  // First calculate size of file names
  DataSize := 0;
  for I := 1 to ParamCount do
    Inc(DataSize, Length(ParamStr(I)) + 1);
  Inc(DataSize);  // for final #0
   // Now allocate data storage and copy parameters into it
  Data := StrAlloc(DataSize);
  try
    PData := Data;
    for I := 1 to ParamCount do
    begin
      // copy parameter string, zero terminated
      StrPCopy(PData, ParamStr(I));
      Inc(PData, Length(ParamStr(I)) + 1);
    end;
    // final closing #0
    PData^ := #0;
    // Set up copy data structure:
    // watermark optional: to allow simple check of validity of packet
    // in receiving application
    CopyData.lpData := Data;                // data to be copied
    CopyData.cbData := DataSize;            // size of copy data
    CopyData.dwData := cCopyDataWaterMark;  // watermark in data field

    // Send copy data message
    // set result according to result returned from other instance
    Result := SendMessage(WndH, WM_COPYDATA, 0, LPARAM(@CopyData)) = 1;

  finally
    // Now free memory used for data packet
    StrDispose(Data);
  end;
end;


The function first bundles the command line parameters into a single
data structure. This data structure is a #0 separated sequence of the
program's parameter strings, terminated by a further #0 character. (This
idiom is commonly used in Windows to store a list of string values.) For
example the three parameters 'One', 'Two' and 'Three' would be stored as
One#0Two#0Three#0#0.

Having allocated the required memory and stored the data we set
TCopyDataStruct.lpData to point to it and record the size of the data
structure in TCopyDataStruct.cbData.

We use the TCopyDataStruct.dwData field to store a 32 bit watermark
value that we use to validate the WM_COPYDATA message. Use of such a
watermark provides a reality check on the data and indicates to the
receiving application that the message and its data have been sent from
our own application. The watermark can be any 32 bit value -- we use the
value stored in the cCopyDataWaterMark constant.

SendMessage is now used to send the message to the existing
application's main window. The address of the TCopyData structure is
passed as the message's LParam. We set the function result to True if
the message returns 1 and False otherwise.

Finally, we free the memory used to store the command line parameters.

The receiving application needs to know how to extract the data from the
WM_COPYDATA message, and we discuss how to do this next.


Handling WM_COPYDATA
--------------------

As well as knowing how to send data to other instances of itself, our
application also needs to know how to handle the WM_COPYDATA messsage to
receive such data. We do this in the program's main form by writing a
standard Delphi message handler, which is declared in the form's class
declaration as follows:


procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;


and here is the implementation:


procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
  PData: PChar;  // walks thru data
  Param: string; // a parameter
begin
  // check watermark is valid
  if Msg.CopyDataStruct.dwData <> cCopyDataWaterMark then
    raise Exception.Create('Invalid data struct passed in WM_COPYDATA');
  // extract strings from data
  PData := Msg.CopyDataStruct.lpData;
  while PData^ <> #0 do
  begin
    Param := StrPas(PData);
    // process the parameter:
    // (write this method to do required processing)
    ProcessParam(Param);
    Inc(PData, Length(Param) + 1);
  end;
  // set return value to indicate we handled message
  Msg.Result := 1;
end;


This message handler processes the data referenced by the
TCopyDataStruct data structure. The WM_COPYDATA message has a pointer to
the record in its LParam field. Rather than accessing the LParam value
directly and type casting we use the Delphi-provided TWMCopyData message
to "crack" the message record -- its CopyDataStruct field provides easy
access to the data structure.

We first check the watermark stored in the TCopyDataStruct.dwData,
raising an exception if it is not valid. Then we get a pointer the to #0
delimited list of parameters and walk the buffer, making a copy of each
parameter before passing it to the ProcessParam method (a placeholder
for whatever processing has to be applied to each parameter in turn).
The loop stops when a terminating #0 character is found. Before
returning we set the message result to 1 to indicate the message has
been handled.


Activating the Previous Instance
--------------------------------

When a previous instance of an application is activated by a new
instance its window could be displayed normally, or maximized, minimized
or invisible. It may be partially or fully hidden behind other windows.
If it is minimized, invisible or fully or partially hidden there will be
no visual feedback to the user of the previous instance being used in
place of the application they started. There are various different
design decisions that could be taken to handle these situations. We will
opt to ensure the window it is made prominent when it is activated. If
the window is shown normally or is maximised we simply bring it to the
front of the z-order. If, however, the window is minimized we restore it
and if it is hidden we show it.

When an application starts and finds there is a previous instance, the
previous instance's main window is sent a custom message telling it to
"wake up". This message is defined as


const
  UM_ENSURERESTORED = WM_USER + 1;


We send this message in the SwitchToPrevInst routine mentioned above.
The routine's implementation will be shown later in the article.

The receiving application must handle and act on this message. We do
this in the application's main form, again using a Delphi message
handler, declared in the form's class declaration as:


procedure UMEnsureRestored(var Msg: TMessage);message UM_ENSURERESTORED;


The message handler's implementation is:


procedure TForm1.UMEnsureRestored(var Msg: TMessage);
begin
  if IsIconic(Application.Handle) then
    Application.Restore;
  if not Visible then
    Visible := True;
  Application.BringToFront;
end;


In this message handler we check to see if the application is minimized
(by checking the state of the special Application window) and we restore
the application if so. We then show the main form if it is currently
hidden. Finally we bring the main form to the front of the z-order.


Finishing Touches
-----------------

It only remains to finally implement the SwitchToPrevInst function we
referred to earlier in the article. This function has two main purposes:

1. Ensure any command line parameters are sent to the previous instance
2. Activate the previous instance, ensuring its main window is displayed

The function takes the handle of the main window of the previous
application instance as a parameter (which must not be zero). Recall
that we must return True if any parameters are successfully passed to
the previous instance and false on error. The implementation of
SwitchToPrevInst is as follows:


function SwitchToPrevInst(Wnd: HWND): Boolean;
begin
  Assert(Wnd <> 0);
  if ParamCount > 0 then
    Result := SendParamsToPrevInstance(Wnd)
  else
    Result := True;
  if Result then
    SendMessage(Wnd, UM_ENSURERESTORED, 0, 0);
end;


If we have command line parameters we attempt to send them to the
previous instance using the SendParamsToPrevInstance routine, returning
whether that succeeded or failed. If there are no parameters our
function has no data to send to the previous instance and it returns
True. Only if the function has succeeded do we send a UM_ENSURERESTORED
message to the previous instance to cause it display its main window in
the foreground.


Putting It All Together
-----------------------

The attached source code contains a skeleton Delphi project that draws
all the code discussed in this article. The project contains three
modules that can be used as a template for a real application:

* A project file incorporating the required modifications to the
  Delphi-generated code.
* A unit containing the various functions used to manage and activate
  the single application instance.
* A skeleton form unit containing the various message handlers and other
  necessary form code. The form itself contains no components.


A Re-Usable Solution
--------------------

The above approach to the problem works and provides a template for use
in any application. However the source code needs to be amended for each
application. Can we find a re-usable solution -- something object
oriented. Well partly! In the next issue, part two of this article will
look at an object oriented solution that, while still requiring some
modification of the main form and project file, does at least move most
of the code to an extensible class.

__________________

Peter Johnson is a hobbyist programmer living in West Wales (UK) who
maintains the DelphiDabbler website (http://www.delphidabbler.com/)
where his articles and freeware Delphi applications & components are
published. A full version of this article is available at:
http://www.delphidabbler.com/articles.php?article=13

________________________________________________________________________

Delphi BUGS?
Catch & Log every BUG showing Unit, Class, Method, Line #.
Now with support for IntraWeb applications and Anti-Freeze feature.
http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


5. Forums / Mailing Lists


To join any of our forums, the best way is to subscribe from the web,
since that way you'll be able to access the features available at the
web site (like changing your subscription options, viewing the past
messages, accessing the files section, etc.). A Yahoo! ID is required
for that, and you can get yours free by registering as a Yahoo! user,
but if you don't want to register or if you don't have full Internet
access, you can also subscribe by email (you'll only have email access).

* Delphi-En: A unique forum for intermediate-level Delphi programmers.
A large group with a helpful community of members. If you are a beginner
please stay as a listener and learn from others' questions and answers.
Home Page:    http://groups.yahoo.com/group/delphi-en/
Subscription: http://groups.yahoo.com/group/delphi-en/join
              delphi-en-subscribe@yahoogroups.com

* Kylix: Kylix programming.
Home Page:    http://groups.yahoo.com/group/KylixGroup/
Subscription: http://groups.yahoo.com/group/KylixGroup/join
              KylixGroup-subscribe@yahoogroups.com

* Components: This is a forum for searching / recommending software
components (VCL and CLX components, ActiveX objects, DLL libraries,
.Net, etc.), as well as utilities, tutorials, information, etc.
Home Page:    http://groups.yahoo.com/group/components/
Subscription: http://groups.yahoo.com/group/components/join
              components-subscribe@yahoogroups.com

* Software Developers: A place for subjects related to software
development and the industry. For developers to share their experiences
as an academic, professional or hobbyist. It is not a programming forum,
messages here are supposed to be more general or language independent.
Home Page:    http://groups.yahoo.com/group/software-developers/
Subscription: http://groups.yahoo.com/group/software-developers/join
              software-developers-subscribe@yahoogroups.com

________________________________________________________________________

         Vote for the Pascal Newsletter in The Delphi Top 200!
         http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


6. Delphi on the Net

   By Dave Murray <irongut at vodafone dot net>


Components, Libraries and Utilities
===================================


Shareware / Commercial
----------------------

* SMExport Suite v4.50 - by Scalabium Software ($50)
  SMExport suite is a component set for easy data exporting into
  different file formats: CSV/Text, MS Excel, MS Access, MS Word, HTML,
  XML, SPSS, PDF, RTF, SQL etc. Available for Delphi 3-7 and BCB 3-6.
  http://www.scalabium.com   (mshkolnik@scalabium.com)

* Storage Library v3.29 - by Deepsoftware.Ru ($39)
  Storage library - elegant way for application settings management.
  Supports working with ini files, registry, xml files, TStream objects.
  Provides encryption, unicode support, working with published
  properties without programming, saving form position and much more...
  http://www.deepsoftware.ru/rsllib/index.html

* COM Genie v1.00 - by WS+V (£10)
  A Component Object Model navigator designed to enable you to navigate
  the interfaces of a COM object in a hierarchal manner. Functions that
  return functional interface pointers can be expanded to reveal the
  contents of the relevant interface, and its functional interfaces.
  The free demo is restricted to the first 80 interfaces.
  http://web.ukonline.co.uk/alison.burgess2/


Freeware
--------

* Borland Research Project: BabelCode
  BabelCode is a C# to Delphi for .NET code conversion utility. It is
  implemented as a web service and an ASP.NET client.
  http://dotnet.borland.com/babelcode/

* CrossKylix v2.65.11 - by Simon Kissel (with source)
  Integrates the Kylix compiler into the Delphi IDE allowing compilation
  of native Linux apps. Console projects, packages and visual CLX apps
  are fully supported with compile warnings, hints and error messages.
  http://crosskylix.untergrund.net/

* Inno Setup v4.2.7 - by JR Software (with source)
  A free installer for Windows that rivals commercial installers in
  features and stability. See review in this issue for details.
  http://www.jrsoftware.org/isinfo.php

* TurboPower XML Partner v2.60 - by TurboPower (with source)
  Add the power of XML to Borland Delphi, C++ Builder and Kylix projects
  through native, easy to use VCL and CLX components. These components
  simplify the process of creating, modifying, and parsing XML data.
  http://sourceforge.net/projects/tpxmlpartner


Borland Product Updates
-----------------------

* Delphi 7.1 Update Has Been Fixed And Is Live
  Updated to fix the persistent field issue in the original release. The
  latest version enforces data integrity without raising an exception.
  http://community.borland.com/article/0,1410,32400,00.html

* Borland Delphi 8 Janeva Integration Plugin
  Allows Delphi applications to communicate with J2EE based applications
  using Borland Janeva. CORBA integration will come in the near future.
  http://cc.borland.com/Item.aspx?id=21772

* Delphi 8 HelpKit
  Assists developers to integrate their help files with Borland's.
  http://cc.borland.com/codecentral/ccweb.exe/listing?id=21767

* Updated Delphi 8 License
  New Delphi 8 license provides additional permissions for developers of
  VCL for .NET components. Supercedes all previous Delphi 8 licenses.
  http://community.borland.com/article/0,1410,32293,00.html

* ilink32 Version 5.66 Update for C++ Customers
  Resolves an access violation when linking together large numbers of
  object files. For C++BuilderX (including Mobile) and C++Builder 6.
  http://community.borland.com/article/0,1410,32448,00.html


Articles, Tips and Tricks
=========================

* Why You Can't Pass a List to an InterBase SQL Param - by Craig Stuntz
  When writing a WHERE clause in your InterBase SQL, it would sometimes
  be convenient to write WHERE FOO IN (:SomeParam) and pass a list of
  values to SomeParam. You can't do that; here's why.
  http://community.borland.com/article/0,1410,32076,00.html

* Agile Management June 2004: The S-Curve Explained - David J. Anderson
  Provides some more insight as to what causes the S-curve effect and
  how to minimize it by paying attention to a few areas at the beginning
  and end of a project.
  http://community.borland.com/article/0,1410,32411,00.html

* .NET tip: Getting the User's Home, Temp or My Documents Directory
  -  by Charlie Calvert
  How to retrieve commonly used directories when using .NET.
  http://community.borland.com/article/0,1410,32384,00.html

* A Hint About .NET WinForms Controls ToolTips - by John Kaster
  This article explains how .NET Extender Providers can be used to
  include ToolTips for .NET WinForms controls.
  http://community.borland.com/article/0,1410,32345,00.html

* Beyond Proprietary Databases: Helen Borrie on the Future of Firebird
  "It's very satisfying to learn of yet another big corporation or
  enterprise software product that has switched to Firebird, and, as the
  word gets out, it happens more often."
  http://www.linuxinsider.com/story/34399.html

* IntraWeb And ActiveForms - by Bob Swart
  How to use IntraWeb and ActiveForms together to create some innovative
  solutions for your intranet / extranet needs.
  http://www.thedelphimagazine.com/samples/1749/1749.htm

* Manage Complexity With State Machines - by Rob Bracken
  Explains state machines and how to use them to model a wide range of
  real-world problems, making code easier to debug, maintain and modify.
  http://www.thedelphimagazine.com/samples/1738/1738.htm

* Handling SQL Mail - by Jason Sweby
  Use the email facilities built into MS SQL Server to send email from
  your applications in response to database triggers, and more.
  http://www.thedelphimagazine.com/samples/1729/1729.htm

* Fun With Threads - by Steven Soroka
  Some practical tips to make threading in your apps more efficient.
  http://www.thedelphimagazine.com/samples/1712/1712.htm

* NTFS Compression And Sparse Files - by Marcel van Brakel
  Explains what the NTFS file compression and sparse files features have
  to offer and how to make use of them in your own software.
  http://www.thedelphimagazine.com/samples/1696/1696.htm

* XML Topic Maps - by Craig Murphy
  Discusses how XML topic maps provide a mechanism to intelligently
  classify information, and how to implement topic maps in your apps.
  http://www.thedelphimagazine.com/samples/1686/1686.htm

* An Introduction To Endo-Testing Using Mock Objects - by Sascha Frick
  Problems arise when applying unit testing and test driven development
  principles to complex projects. Describes how to overcome the problems
  with endo-testing and mock objects.
  http://www.thedelphimagazine.com/samples/1677/1677.htm

* All About ECO - by Malcolm Groves
  A series of blog posts on ECO.
  http://blogs.borland.com/malcolmgroves/category/83.aspx


Tutorials and Training
======================

* BDNtv: Introduction to Together for Visual Studio .NET v2.0
  Part 1 of a 4 part tutorial, this episode gives you a quick intro to
  Together for Visual Studio .NET version 2.0. (Flash)
  http://community.borland.com/article/0,1410,32395,00.html

* BDNtv: LiveSource with Together for Visual Studio .NET v2.0
  Part 2 of a 4 part tutorial, this episode gives you an intro on using
  LiveSource with Together for Visual Studio .NET version 2.0. (Flash)
  http://community.borland.com/article/0,1410,32396,00.html

* BDNtv: Audits with Together for Visual Studio .NET v2.0
  Part 3 of a 4 part tutorial, this episode gives you a quick intro on
  using audits with Together for Visual Studio .NET version 2.0. (Flash)
  http://community.borland.com/article/0,1410,32397,00.html

* BDNtv: Patterns with Together for Visual Studio .NET v2.0
  Part 4 of a 4 part tutorial, this episode gives you an intro on using
  patterns with Together for Visual Studio .NET version 2.0. (Flash)
  http://community.borland.com/article/0,1410,32399,00.html

* Building CORBA Applications with Delphi 8 and Janeva (1) - P. Glowacki
  Shows the necessary steps to build simple CORBA server and client
  applications with Borland Janeva 6.0 and Borland Delphi 8 for .NET.
  http://community.borland.com/article/0,1410,32074,00.html

* Introduction to Delphi for .NET and the New IDE - by Xavier Pacheco
  Provides an overview of Delphi for .NET, with a focus on how to use
  Delphi to develop software for business solutions. Sample chapter from
  the book 'Delphi for .NET Developer's Guide'.
  http://www.informit.com/articles/article.asp?p=174323

* Gekko Software
  Tutorial on building automation server objects using Delphi. Assumes a
  basic knowledge of Delphi and object orientation. The more experienced
  developer will find useful hints and background information.
  http://www.gekko-software.nl/Delphi/


News
====

* Borland Reports Strong Sales
  Despite a tough quarter in the industry, Borland was able to nail
  several large deals including a multimillion dollar deal with British
  Telecommunications that helped push Q3 revenues up to $76.5 million.
  www.santacruzsentinel.com/archive/2004/July/23/biz/stories/02biz.htm

* Borland Solution Selected by BT to Transform Systems Engineering
  Borland's ALM solution will underpin BT's Systems Engineering
  Programme, which was set up to develop a single design and delivery
  methodology for all future IT projects across BT Group.
  http://www.tmcnet.com/usubmit/2004/Jul/1059138.htm

* Boo Hoo Hoo for Victims of XP SP2
  Quite a few applications will break under the new security-focused
  service pack. Problems in the debugger in Borland's Delphi in RC 1
  were fixed quickly, although another tester reports that multiple
  applications under SP2 cannot access the Borland Database Engine.
  http://www.eweek.com/article2/0,1759,1624962,00.asp

* Borland Developer News - .NET Edition, July 2004
  The July 2004 installment of the Borland .NET Development Newsletter.
  Contains information, news, and links for Delphi and C#Builder .NET.
  http://community.borland.com/article/0,1410,32443,00.html

* Many Ways to Skin .NET and Java Integration
  .NET and J2EE used to be web services islands but now vendors have
  begun shipping tools that bridge the two architectures. Borland's
  Janeva has a twist on the translation theme.
  http://sdtimes.com/news/106/story7.htm

* Message from Business Objects: Potential Security Vulnerability
  Notice of a security vulnerability in Crystal Reports web API. Effects
  Crystal Reports for both C#Builder and JBuilder and requires a patch.
  http://community.borland.com/article/0,1410,32402,00.html

* Interbase / Firebird Database Name Buffer Overflow Vulnerability
  A vulnerability in Firebird and Interbase can be exploited to cause a
  DoS and potentially compromise a system due to a boundary error in the
  handling of database names that can cause a buffer overflow by passing
  a long database name when connecting.
  http://secunia.com/advisories/11756/

* Borland Developer News - .NET Edition, June 2004
  The June 2004 installment of the Borland .NET Development Newsletter.
  Contains information, news, and links for Delphi and C#Builder .NET.
  http://community.borland.com/article/0,1410,32390,00.html

* Borland Teams Up With eBay and PayPal
  eBay and Borland have announced a new relationship that will provide
  Borland developers with access to tools and resources for creating web
  services applications for the eBay and PayPal platforms.
  http://community.borland.com/article/0,1410,32373,00.html

* Borland and Microsoft Arm Systems Integrators with Application
  Development and Deployment Best Practices
  Borland presented alongside Microsoft and leading systems integrators
  a road map for delivering the Visual Studio 2005 Team System. This
  will provide a set of best practices, architecture guidance and
  integrated tools designed to enable IT organizations to successfully
  build and deploy custom solutions for the Windows Server System.
  http://home.businesswire.com/portal/site/google/index.jsp?
  ndmViewId=news_view&newsId=20040524005402&newsLang=en

* Borland Brings RM to the Masses
  Requirements Management is a key discipline underlying software
  quality and success but business requirements are too often lost in
  translation before they ever become software capabilities. The best RM
  solutions address both human and technology adoption barriers.
  http://www.adtmag.com/article.asp?id=9223

* eWeek Application & Web Services Development Award
  WINNER: Microsoft Visual Studio .Net 2003.
  RUNNER-UP: Borland Enterprise Studio For Java 7.
  http://www.eweek.com/article2/0,1759,1560688,00.asp


Other Links
===========

* Borland Blog Central
  Blogs by Borland staff.
  http://blogs.borland.com/

* Delphi 8 Documentation Available as PDF
  Registered users of Delphi 8 can now download this PDF that provides
  conceptual, procedural, and Language Guide topics. English-only.
  http://www.borland.com/products/downloads/download_delphi_net.html

* IDC Recommends Borland Janeva for Interoperability
  Developers who want to use a mixture of .NET, J2EE and CORBA should
  consider using Borland Janeva. Find out why in this PDF from IDC.
  http://www.borland.com/features/pdf/idc_interopToday_may04.pdf

* D7 Ent/D8 Arch Component Migration List
  Are you planning to move from Delphi 7 to Delphi 8? Check this chart
  to see how easy it will be for you.
  http://community.borland.com/article/0,1410,31984,00.html

* Mozilla-Delphi Project
  The Mozilla-Delphi project provides resources for working with Mozilla
  technologies in the Borland Delphi and Kylix programming environments.
  http://delphi.mozdev.org/

* Delphi Dabbler
  Delphi Pascal source code library, components, programming articles,
  tutorials and free programs.
  http://www.delphidabbler.com/

* Borland Delphi 8 (review)
  Good compatibility makes this impressive package ideal for Delphi
  users moving to .Net.
  http://www.vnunet.com/Products/Software/1154731

________________________________________________________________________

Irongut's Delphi Pages
Dedicated to programming with Borland Delphi and Kylix. We have articles
on programming, Borland and Delphi news, source code and components to
use in your applications and more.  >> http://www.paranoia.clara.net/ <<
________________________________________________________________________


YOU CAN HELP US


We need your help to keep this newsletter going and growing. You can
help by referring the newsletter to your colleagues:

http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php

Or you can help by voting for us in some or all of these rankings to
give more visibility to our web site and thus increase the number of
subscriptions to this newsletter:

http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium

It's just a few seconds for you that REALLY mean a lot to us.

Don't forget we also need articles for this newsletter and there is a
prize for one of the authors in each issue. All articles will be
considered but we are particularly interested in articles about Kylix
because there is so little available online to help Kylix developers.
Send articles to <pascal-newsletter-owner@yahoogroups.com>.

We are also looking for shareware authors who would like to offer their
components or applications as prizes for articles in the newsletter. In
return you will be promoted in this newsletter and the Latium Software
web site. For more info contact Dave <irongut at vodafone dot net>.

________________________________________________________________________

If you haven't received the full source code examples for this issue,
you can get them from http://www.latiumsoftware.com/download/p0050.zip
________________________________________________________________________

This newsletter is provided "AS IS" without warranty of any kind. Its
use implies the acceptance of our licensing terms and disclaimer of
warranty you can read at http://www.latiumsoftware.com/en/legal.php
where you will also find a note about legal trademarks. Articles are
copyright of their respective authors and they are reproduced here with
their permission. You can redistribute this newsletter as long as you do
it in full (including copyright notices), without changes, and gratis.
________________________________________________________________________

Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Group Home:  http://groups.yahoo.com/group/pascal-newsletter/
Subscribe:   pascal-newsletter-subscribe@yahoogroups.com
Unsubscribe: pascal-newsletter-unsubscribe@yahoogroups.com
Problems with your subscription? pascal-newsletter-owner@yahoogroups.com
________________________________________________________________________

Latium Software:        http://www.latiumsoftware.com/en/index.php
Irongut's Delphi Pages: http://www.paranoia.clara.net/

Copyright 2004 by Ernesto De Spirito + Dave Murray. All rights reserved.
________________________________________________________________________
  
Copyright © 2004 Ernesto De Spirito and Dave Murray. All Rights Reserved.