Home
Archives
About us...
Advertising
Contacts
Site Map
 

ruby in steel

 

Delphi A DELPHI PROGRAM MANAGER

This month , Huw Collingbourne creates a simple program management tool as an alternative to the Windows Start Menu
Requirements:
Borland's Delphi 7 or later

 

Download The Source Code:
prog_grps2.zip
Delphi Program Manager 20x20 This month: creating an MDI interface and cascading or tiling program group windows...

See also: Part One and Part Three of this series

In the first part of this series we found out how to locate the files displayed by the Windows Start Menu. Having experimented with alternative ways of displaying these files in my own programs, it’s now time to start thinking about designing a user interface in order to create a program manager. This month we shall find out how to create multiple program groups in tiled and overlapping windows.

delphi program manager
This is the application we’ll be creating in this column. It lets you create multiple tiled or overlapping windows containing groups of program icons which can be launched by double-clicking.

Before getting down to the nitty-gritty details of implementing the user interface of the program manager, let’s recap the techniques required to locate the Start Menu folder on disk. This is the directory in which Windows stores the actual structure of the menus that branch off from the Start button. You can find this folder by passing the constant, CSIDL_STARTMENU (defined in Delphi’s ShlObj unit) to the Windows SHGetSpecialFolderLocation() function. This returns the actual path to the Start Menu directory. In my Test.dpr project, you will see that I have written a function called GetSpecialFolder() which acts an interface to SHGetSpecialFolderLocation(). This function tests that the operation is successful and converts between Delphi strings and null-terminated strings where necessary.

Displaying Icons in a ListView

In the last project, we displayed a list of Start Menu files in an ordinary ListView control and preceded each file name with the appropriate icon. The icons had been obtained by accessing the system imagelist in FormCreate().

Delphi sample program
Here I’ve adapted a normal ListView control (on the left) to display the items in the Windows Start Menu.
On the right, Delphi’s sample ShellListView displays (more or less the same items.

If you wish, you can use similar techniques to populate other types of control with file names, with or without icons. For example, you could add file names to combo boxes, grids, buttons or (Heaven forfend!) cascading menus. However, it is worth bearing in mind that Delphi already comes with a control that is eminently suited to our purposes. The ShellListView, which is (usually) located on the Samples tab of the palette, has all the features of a standard ListView plus a built-in ability to display file names and icons. In short, it does automatically what we had to code long-hand into a standard ListView last month.

install shell controlsInstalling Shell Controls

NOTE: In my installation of Delphi 2006, I was surprised to find that the Shell controls had not been installed by default.

If you have this problem, you will need to build and install the packages yourself.

These are located in the \VCLWin32\ShellControls subdirectory nested beneath Delphi’s \Demos directory.

You can build these by loading the projects into Delphi, right-clicking the bpl item in the Project Manager and selecting Install.

For the sake of comparison, I’ve used a simple ListView alongside a ShellListView to display the Start Menu files in the Test.dpr project. The first difference you will notice when you load the project is that the ShellListView displays icons from the active directory at design time whereas the ListView does not. Now run the program. You should find that the two controls display more or less the same items. The order may be slightly different and the case of the labels may vary but, in all important details, they are the same. If you select a file icon and double-click it in each of the two controls, the matching application will be launched. Finally, use the radio-box to the right of the form to select alternative view styles. When you select these, both views are updated with the exception that the Icon view in our ListView fails to display large icons. I shall explain this deficiency in a moment.

Advantages of ShellListView

Close the application and turn to the code. Now the real difference between a ListView and a ShellListView should become apparent. All the behaviour of the ShellListView – from its display of file names and icons to its launching of an application when double-clicked – is automatic. All I have had to do is to set its Root folder to the Start Menu directory with this assignment in the FormCreate() procedure:

ShellListView.Root := startmenudir+'\';

Here, startmenudir is a private variable which is initialised by my Init() procedure. Now look at all the code I’ve had to write in order to get the ListView to do what I need. First, in FormCreate() I have accessed the small system icons. Then, in ShowFiles() (which is called by my Init() procedure) I have had to find each file in the specified directory, get its matching icon and add it to the ListView. My code has also filtered out the current and parent directory specifiers, ‘.’ and ‘..’, which would otherwise be added to the list. Finally, in order to implement file launching I have had to code ListView1DblClick(). This calls a routine, ExecuteFile(), in my filestuff.pas unit. Prior to doing this I had to do a whole load of checking to make sure that a valid file name has been selected and that the specified directory exists.

And even after all that effort, I still haven’t managed to display the large icons. Adding this feature would not be difficult. You may want to try it yourself. For a few hints, take a look at SHGetFileInfo in Delphi’s (Win32 SDK) help and also at the code of my file launchpad application from previous columns. All the same, why reinvent the wheel? If you decide to create a different type of Program Manager – using menus or buttons, say – you will have no alternative but to go through all the long-winded coding steps I’ve outlined for adding file icons to the plain vanilla ListView. However, I personally feel that the ShellListView is ideal for the job so, from now on, that is what I shall use.

Creating An MDI Interface

In the old days of Windows 3.1, programs were arranged as groups of icons displayed within separate windows. These windows were nested inside a ‘containing’ window in what is known as MDI (Multiple Document Interface) style. While this design had some drawbacks – mainly due to the clutter that resulted from too many nested windows – I still feel that this was an essentially neater design than the cascading menus of the current generation of Windows. For that reason, I would like to use a Multiple Document Interface for my program manager.

An MDI application comprises a container form and a child form. Usually many instances may be made of a child form so that multiple windows appear inside the container form. When you create an MDI project, you must have at least two forms. To make the main form, Form1, act as a container you just set its FormStyle property to fsMDIForm using the Object Inspector. To let the second form – which I shall call childform – act as a contained form, you must set its FormStyle property to fsMDIChild. Open my Test2.dpr project and you will find that this is precisely what I have done.

Delphi sample application
Use The Project Manager to view the design and code of the ‘child form’ which defines the ‘child’ windows that will be nested inside the main container window.

I have added a menu to Form1 which includes Window, New. Clicking this causes a new program group window to appear. The code of this is simple:

Tchildfm.Create(Self);

This creates a new instance of my child form class and sets the current form, Self, as its owner. There is nothing much to be said about the code inside the childform unit apart from the FormClose() method which specifically sets the Action parameter to caFree. This causes each individual child form to be closed when the close button is clicked. The default close action for a child form in an MDI application is to minimise the window rather than close it. Comment out this line of code to see this for yourself.

Merging Menus

The other thing to notice is that I have given the child form its own menu. This menu does not, however, appear on the child form itself. Instead it is merged with the main menu at runtime. If you double-click the menu and select Group and View, you will notice that their GroupIndex properties have been set to 1 in the Object Inspector. The GroupIndex properties of the top-level items in the Form1 menu are set to 0. By setting a higher value, I can ensure that menu items will appear to the right of the menu bar when two menus are merged.

Turn back now to the main form’s unit, t2, and look at the event-handlers for the items on the Windows menu. These simply call the Tile(), Cascade() and ArrangeIcons() methods of the MDI form. The first two methods arrange multiple open child forms alongside one another or overlapping while ArrangeIcons() arranges any minimised forms. Note that Tile() arranges forms horizontally by default. If you want them to be arranged vertically, use the following assignment prior to calling the Tile() method:

TileMode := tbVertical;

We have come quite a long way in our development of an alternative to the Start Menu now. We have a multi-window program manager in which the windows can be tiled or cascaded. By default it displays a single group showing the top level items of the Start Menu itself. You can navigate easily to the other groups, however, by clicking the Programs group and other groups branching off it. You could, in fact, display separate windows of icons containing the Start, Programs, Accessories and other groups. The main deficiency is that the groups aren’t preserved between sessions. It would obviously be much more useful to be able to save your favourite groups so that they always appear whenever you run the program. This is one of the features I ’ll be adding in my next column.


The MDI Wizard

Delphi 7 can create multi-window applications at the click of a mouse

I have created the multi-window interface for my application from the ground up in this month’s project. However, if you want to save yourself some effort, you can create a fairly complete MDI application using one of Delphi’s project wizards.

delphi sample program
Delphi creates an MDI application like this with no coding required!

Select File, New, Other. In the dialog box that pops up, click the Projects tab or branch. Select MDI Application and click OK. You will now be prompted for a location. Browse to a suitable directory or enter a path name then click OK. Your MDI application is now ready to run. As you can see, this application is not, as it stands, suitable for our purposes. It is a multi-window text editor complete with menus and icons to open, close and arrange windows. If you wished to create an MDI application of a different sort, you could adapt this by redesigning the ChildWin forms. Even if you don’t wish to use this wizard for your own applications you may find some useful tips in the code which it generates.

 

April 2006

 


Home | Archives | Contacts

Copyright © 2006 Dark Neon Ltd. :: not to be reproduced without permission