Making Delphi programs Vista-Ready

- DelphiVistaTools and Solway's TaskDialog -


On this page I will try to sum-up the different things you can do to make your Delphi programs work better on Windows Vista, as well as providing source code, files, and helpful links.

Much of what is on this page is a summary of information that available elsewhere on the web.

While most Delphi applications will work under Vista without any major issue, quite a bit can be done to make them fit-in with Vista more seamlessly.

We will look at:


Download DelphiVistaTools (free)

Consider Solway's TaskDialog


The User Interface (fonts, buttons, etc)

Windows Vista uses a new default font for user interfaces: Segoe UI, and the default font size has increased to 9 point (whereas XP used Tahoma 8). This font and size has been optimized for clarity on LCD monitors using Cleartype. If you want to use these new fonts you will need to go through all your dialogs and make sure the larger text still fits okay in your dialog, and making more room available where necessary. You will probably need to set "ParentFont" to true for all your forms and labels.


Allowing the application to minimize with an animation

Delphi applications compiled on older compilers have an invisible "application form" which is hidden from the Vista user interface. So when you minimize your application in Vista it will simply disappear rather than visibly shrinking to the Taskbar with an animation like other applications in Vista do. Also, when you hover your cursor over its icon in the taskbar you only see the program's icon in the thumbnail which appears, and not an image thumbnail of its main window. Likewise when you press Alt-Tab or Windows-Tab (Vista's new Flip-3D).

We need Vista to recognize our mainform as the application window. You can achieve this by taking the following steps:

  1. Your project source (.dpr) file must be edited to contain the following:

    uses windows, // ie, "windows" must be in the list of used units
         uVista;
    
    var
      ExtendedStyle : Integer;
    
    begin
      . . .  
      Application.Initialize;
        
      // vista compatibility
      if IsWindowsVista then
       begin
         ExtendedStyle := GetWindowLong(Application.Handle, GWL_EXSTYLE);
         SetWindowLong(Application.Handle, GWL_EXSTYLE, ExtendedStyle OR WS_EX_TOOLWINDOW
                                                     AND NOT WS_EX_APPWINDOW);
       end;
      // end vista stuff 
      


  2. Add the following procedure declaration in your main form (eg, in Form1):

      
       // vista compatibility 
       procedure AppMinimize(Sender: TObject);
       // end vista stuff 
      

    On Application.OnMinimize we execute this procedure so that if our application is minimized from a shortcut, the correct form will get minimized.


  3. In the protected section of your main form class declaration (add a protected section if you need to):

     protected
       // vista compatibility 
       procedure CreateParams(var Params: TCreateParams); override;
       procedure wm_SysCommand(var M: TMessage); message WM_SYSCOMMAND;
       // end vista stuff
      


  4. Then in the implementation section of your main form, the actual functions:

    uses uVista;
    
    // vista compatibility
    
    procedure TForm1.wm_SysCommand(var M: TMessage);
    begin
      if IsWindowsVista then
       begin
         case (M.WParam and $FFF0) of
          SC_MINIMIZE, SC_RESTORE, SC_MAXIMIZE:
           begin
             M.Result := DefWindowProc(self.Handle, M.Msg, M.WParam, M.LParam);
             ShowWindow(Application.Handle, SW_HIDE);
           end;
          else inherited;
         end;
       end
      else inherited;
    end;
    
    procedure TForm1.CreateParams(var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      if IsWindowsVista then
       Params.ExStyle := Params.ExStyle and not WS_EX_TOOLWINDOW or WS_EX_APPWINDOW;
    end;
    
    procedure TForm1.AppMinimize;
    begin
      // draw the main form before we minimize it
      ShowWindow(Handle, SW_SHOW); // so Vista can get a thumbnail at startup
      application.processmessages;  // allow time for form to be drawn
      ShowWindow(Handle, SW_MINIMIZE);
    end;
    
    // end vista stuff 
    


  5. Then, in the FormCreate procedure of your main form:

      uses uvista;
      
      // vista compatibility
      if IsWindowsVista then 
       begin
         SetVistaFonts(self);
         Application.OnMinimize := AppMinimize;
       end; 
      // end vista stuff 
    


  6. Then, in the FormCreate procedure of each subform:

      uses uvista, pointerform;
    
      // vista compatibility
      if IsWindowsVista then SetVistaFonts(self);
      // end vista stuff 
    


  7. Finally, copy the PointerForm unit into the folder containing your project files. Use the Pointerform unit and make each of your sub-forms of the type "TPointerForm" (e.g., TForm2 = class(TPointerForm) ). Then, importantly, set the parent, in PointerForm.pas, to the main form of your application. For example:

      Params.WndParent := form1.handle;
    

    We must ensure that each subform is associated with the mainform, otherwise, if it is shown modally, and you switch between tasks (eg, with Alt-Tab), the modal window will end up behind the main form, and you won't be able to do anything.


Displaying a thumbnail correctly

Take the above steps and you will also get the thumbnails to appear correctly.


Handling Vista's User Account Control


Accessing Vista's Task Dialogs

Vista provides highly customizable "task dialogs".

A basic task dialog is available in the uVista unit, with the function name TaskDialog. This type of dialog will only display on Vista.

More complex dialogs require the use of something like my own Solway's TaskDialog. This library will automatically emulate the same complex Vista dialogs on earlier operating systems, like Windows XP, so you only have to write one set of code.


Accessing Vista's File Dialogs

The unit uVista includes the function OpenSaveFileDialog for accessing Vista's new file open and file save dialogs.

Example of use:

uses commdlg

var filename : string;

   OpenSaveFileDialog(self,
                      '',     // default extension for saving files
                      '*.*',  // show all files
                      extractfilepath(paramstr(0)), // use path of app
                      'Open file',  // either opening a file or saving
                      filename,  // the chosen filename is stored in this variable
                      true, // true means file must exist
                      true, // true to allow overwrite prompt
                      false, // false to allow change dir
                      true)  // true for open file, false for save


Where to save your application data?

As a security measure, Vista doesn't like you to write to files in the Program Files folder. On Vista, your application data files should go in the user's AppData folder. Normally, they will go in the "Roaming" folder (within the "Appdata" folder), unless they contain computer-specific information, in which case they should go in the "Local" folder.

Inside either the Roaming or Local folder you should create a folder with the name of your software company or publisher name, and inside that, another folder with the name of your application, which will hold your application's data files.

It's a good idea, somewhere in your application (possibly in your "About" dialog) to let your user know the location of the application's data files.

The following function will return the Roaming Appdata path:

uses shellapi

function GetRoamingUserAppDataPath : string;
// works so long as people have at least IE 4.  (and Win95 or better)
var
   r: Bool;
   path: array[0..Max_Path] of Char;
begin
   r := ShGetSpecialFolderPath(0, path, CSIDL_APPDATA, False) ;
   if r then result := path
   else result := '';
end;


Help files on Vista

The old .hlp files will not work on Vista, so you will need to supply the new html help files with your application (i.e., .chm files).

For Delphi versions less than v6 you can use the UseHtmlHelp unit by Jan Goyvaerts to display the .chm files.

Delphi 2006 is the first version of Delphi that has built-in support for HTML Help, and you can use the HTMLHelpViewer unit.


Creating a template for a Vista application

Inside the DelphiVistaTools package you'll find DelphiVistaApp.zip. This project contains most of the changes mentioned earlier on this page. Unpack the contents of this zip file into a new folder (which might be called "Default Vista App"). Then open the project in Delphi and make sure it compiles. Next, go to "Project - Add to repository", where you are presented with a dialog to fill in. The title can be something like "Vista Application". For the "page", select "Projects".

Now, when you want to start a new Vista application, you simply go to "File - New", clicking on the "Projects" tab, then "Vista Application". You will then be asked which new folder name you want to use for the new project. That's a lot quicker than copying and pasting all those bits of text, and there's less chance of mistakes.

In addition to the application template you can add a "Vista Dialog" to your repository by right-clicking on Form2 (from our default Vista application), then "Add to Repository". Select form2, then give it a title "Vista Dialog". The "page" will be "Dialogs".



Credits: Thanks to Nathanial Woolls for much of the information on Vista fonts and on minimizing Delphi applications.


Kevin Solway: email: software@theabsolute.net