Home  ==>  papers  ==>  colibri_utilities  ==>  directory_favorite_list   

Directory Favorite List - Felix John COLIBRI.

1 - Directory Favorite List

When we are handling projects with some deeply nested file structure, the Windows File Explorer does not allow quick moves from one directory to an other.

The purpose of the favorite list component is

  • to display in a tListBox the names of our favorite pathes
  • to set the current Windows directory by simply clicking on one of those names

2 - Mini How To

Nearly all of our Delphi utilities main window use the following structure:
  • on the left
    • a directory favorite list
    • a tDirectoryListBox
    • a tFileListBox
  • on the right, a display area (a tMemo)

and :

  • to ad an item to the favorite list,
       select a new directory in the tDirectoryListbox, for instance D:\programs\ 
       type "+"
       a input form is displayed
       type the name of this favorite, for instance


       type enter
       the new favorite is added at the end of the favorite list


    at the same time

    • the name of the item and the selected directory are saved in a file. This file is stored in a sub-directory of the .EXE called favorites\  and the name of this file is the concatenation of the project name and "_favorites". In our case :
    • the content of this file is displayed in the display area

  • to delete a favorite
       select the favorite item to delete
       type "-"
  • to reorder the items, use drag and drop

  • to navigate to one of the directories, we simply click the item in the favorite list

3 - the Delphi source code

The code is very straightforward
  • the c_favorite_path is defined by :

    c_favorite_path// one "favorite_path"
         // -- m_name: the displayed name in the memos
         // -- the m_parameter is not currently used (could be a Mask)

         Constructor create_favorite_path(p_namep_pathp_parameterString);
         Function f_display_favorite_pathString;
         Function f_c_selfc_favorite_path;
         Function f_normalized_parameter_listString;

         Destructor DestroyOverride;
       End// c_favorite_path


    • m_name is the item name
    • m_path is the directory
  • the list of favorites is managed by a tStringList container:

    c_favorite_path_list// "favorite_path" list
         // -- m_name: the full file name



         Constructor create_favorite_path_list(p_nameString;

         Function f_favorite_path_countInteger;
         Function f_c_favorite_path(p_favorite_path_indexInteger): c_favorite_path;
         Function f_index_of(p_favorite_path_nameString): Integer;
         Function f_c_find_by_favorite_path(p_favorite_path_nameString): c_favorite_path;
         Procedure add_favorite_path(p_favorite_path_nameString
         Function f_c_add_favorite_path(p_favorite_path_namep_pathp_parameterString): 
         Function f_c_add_unique_favorite_path(p_favorite_path_namep_path
             p_parameterString): c_favorite_path;
         Function f_c_delete_favorite_path(p_favorite_path_indexInteger): c_favorite_path;

         Procedure display_favorite_path_list;

         Function f_path_name_index(p_path_nameString): Integer;
         Procedure create_listbox;

         Procedure handle_favorite_listbox_click(p_c_sendertObject);
         Procedure handle_listbox_keypress(p_c_sendertObjectVar pv_keyChar);

         Procedure handle_directory_listbox_keypress(p_c_sendertObjectVar pv_keyChar);
         Procedure handle_directory_listbox_click(p_c_sendertObject);

         Procedure handle_directory_listbox_drag_over(
             p_drag_stateTDragStateVar pv_acceptBoolean);
         Procedure handle_directory_listbox_drag_dop(

         Procedure load_from_file(p_full_file_nameString);
         Procedure save_to_file;

         Destructor DestroyOverride;
       End// c_favorite_path_list

    The class contains

    • a reference to the tDirectoryLisbox (to handle the "+" and the directory selection
    • a reference to the favorite list panel. The favorite tListbox will be dynamically create with this panel as it's parent

      Procedure c_favorite_path_list.handle_directory_listbox_drag_over(
          p_drag_stateTDragStateVar pv_acceptBoolean);
          pv_accept := p_c_senderp_c_source;
        End// handle_directory_listbox_drag_over

      Procedure c_favorite_path_list.handle_directory_listbox_drag_dop(
        Var l_item_indexl_drop_indexInteger;
          With m_c_list_box Do
            l_drop_index:= ItemAtPos(Point(p_xp_y), True);
            If l_drop_index< 0
              Then l_drop_index:= 0;
            If l_drop_index>= Count
              Then l_drop_index:= Count- 1;
            // -- ItemIndex will be changed by the Exchange
            l_item_index:= ItemIndex;
            If l_drop_indexl_item_index
              Then Exit;


          End// with m_c_list_box

        End// handle_directory_listbox_drag_dop

    • m_c_favorite_path_list is the container, with the usual count, add, display routines
    • clicking on the favorite list selects the appropriate directory

      Procedure c_favorite_path_list.handle_favorite_listbox_click(p_c_sendertObject);
        Var l_c_favorite_pathc_favorite_path;
          With m_c_list_box Do
            l_c_favorite_path:= f_c_find_by_favorite_path(Items[ItemIndex]);

          With l_c_favorite_path Do
        End// handle_favorite_listbox_click

    • clicking "-" removes the favorite item from the list

      Procedure c_favorite_path_list.handle_listbox_keypress(p_c_sendertObjectVar pv_keyChar);
        Var l_favorite_indexinteger;
          If pv_key'-'
            Then Begin
                With m_c_list_box Do
                  l_favorite_index:= ItemIndex;

                // -- remove from list

        End// handle_listbox_keypress

    • clicking "+" in the tDirectoryListbox adds another favorite item :

      Procedure c_favorite_path_list.handle_directory_listbox_keypress(
          p_c_sendertObjectVar pv_keyChar);
        Var l_path_namel_pathString;
          If pv_key'+'
            Then Begin
                l_path_name:= f_input_string(10, 10, 'enter path name'k_lettersk_digits+ ['_']);
                With m_c_directory_listbox_ref Do
                  l_path:= GetItemPath(ItemIndex)+ '\';

                With m_c_favorite_path_list Do
                  l_found_path:= False;
                  For l_path_index:= 0 To Count- 1 Do
                    With f_c_favorite_path(l_path_indexDo
                      If SameText(l_pathm_path)
                        Then Begin
                            l_found_path:= True;
                            m_name:= l_path_name;
                            m_c_favorite_path_list[l_path_index]:= l_path_name;
                            m_c_list_box.Items[l_path_index]:= l_path_name;

                  If Not l_found_path
                    Then Begin
                        l_c_favorite_path:= f_c_add_unique_favorite_path(l_path_namel_path'*');
                        With m_c_list_box.Items Do
                End// with m_c_favorite_path_list


        End// handle_directory_listbox_keypress

    • reordering the items is handled by drag and drop

      Procedure c_favorite_path_list.handle_directory_listbox_drag_over(
          p_drag_stateTDragStateVar pv_acceptBoolean);
          pv_accept := p_c_senderp_c_source;
        End// handle_directory_listbox_drag_over

      Procedure c_favorite_path_list.handle_directory_listbox_drag_dop(
        Var l_item_indexl_drop_indexInteger;
          With m_c_list_box Do
            l_drop_index:= ItemAtPos(Point(p_xp_y), True);
            If l_drop_index< 0
              Then l_drop_index:= 0;
            If l_drop_index>= Count
              Then l_drop_index:= Count- 1;
            // -- ItemIndex will be changed by the Exchange
            l_item_index:= ItemIndex;
            If l_drop_indexl_item_index
              Then Exit;


          End// with m_c_list_box

        End// handle_directory_listbox_drag_dop

Of course, much could be improved:
  • we could use Delphi generics instead of our own container
  • in our code, we directly created the tDirectoryListbox OnKeyDown event handlers. The user of this utility could not blindly use his own event handler. To solve then we should have overwritten the Click dispatcher.

4 - Download the Sources

Here are the source code files: The .ZIP file(s) contain:
  • the main program (.DPR, .DOF, .RES), the main form (.PAS, .DFM), and any other auxiliary form
  • any .TXT for parameters, samples, test data
  • all units (.PAS) for units
Those .ZIP
  • are self-contained: you will not need any other product (unless expressly mentioned).
  • for Delphi 6 projects, can be used from any folder (the pathes are RELATIVE)
  • will not modify your PC in any way beyond the path where you placed the .ZIP (no registry changes, no path creation etc).
To use the .ZIP:
  • create or select any folder of your choice
  • unzip the downloaded file
  • using Delphi, compile and execute
To remove the .ZIP simply delete the folder.

The Pascal code uses the Alsacian notation, which prefixes identifier by program area: K_onstant, T_ype, G_lobal, L_ocal, P_arametre, F_unction, C_lass etc. This notation is presented in the Alsacian Notation paper.

As usual:

  • please tell us at if you found some errors, mistakes, bugs, broken links or had some problem downloading the file. Resulting corrections will be helpful for other readers
  • we welcome any comment, criticism, enhancement, other sources or reference suggestion. Just send an e-mail to
  • or more simply, enter your (anonymous or with your e-mail if you want an answer) comments below and clic the "send" button
    Name :
    E-mail :
    Comments * :

  • and if you liked this article, talk about this site to your fellow developpers, add a link to your links page ou mention our articles in your blog or newsgroup posts when relevant. That's the way we operate: the more traffic and Google references we get, the more articles we will write.

5 - The author

Felix John COLIBRI works at the Pascal Institute. Starting with Pascal in 1979, he then became involved with Object Oriented Programming, Delphi, Sql, Tcp/Ip, Html, UML. Currently, he is mainly active in the area of custom software development (new projects, maintenance, audits, BDE migration, Delphi Xe_n migrations, refactoring), Delphi Consulting and Delph training. His web site features tutorials, technical papers about programming with full downloadable source code, and the description and calendar of forthcoming Delphi, FireBird, Tcp/IP, Web Services, OOP  /  UML, Design Patterns, Unit Testing training sessions.
Created: sep-18. Last updated: dec-2019 - 103 articles, 239 .ZIP sources, 1292 figures
Contact : Felix COLIBRI - Phone: (33) / -
Copyright © Felix J. Colibri 2004 - 2019. All rigths reserved
Back:    Home  Papers  Training  Delphi developments  Links  Download
the Pascal Institute


+ Home
  + articles_with_sources
    + database
    + web_internet_sockets
    + rest_services
    + oop_components
    + uml_design_patterns
    + debug_and_test
    + graphic
    + controls
    + colibri_utilities
      – delphi_net_bdsproj
      – dccil_bat_generator
      – coliget_search_engine
      – dfm_parser
      – dfm_binary_to_text
      – component_to_code
      – exe_dll_pe_explorer
      – dll_process_viewer
      – the_alsacian_notation
      – html_help_viewer
      – cooking_the_code
      – events_record_playback
      – colibri_hiragana_quiz
      – delphi_string_filter
      – directory_favorite_list
    + colibri_helpers
    + delphi
    + IDE
    + firemonkey
    + compilers
    + vcl
  + delphi_training
  + delphi_developments
  + sweet_home
  – download_zip_sources
  + links
Site Map
– search :

RSS feed