Author : Unknown
Page : << Previous 4 Next >>
to add directory node to the tree view window, we need to implement a loop and enumerate directories for each available drive, then add the enumerated directories to the tree.
Besides directories, we also need to enumerate sub-directories for the expanded nodes. This is because our tree control supports buttons (we have set TVS_HASBUTTONS style), which indicates whether an item has child items or not. For a node that contains child items, its button will contain a "+" sign when the node is in collapsed state, indicating that the node is expandable. For a node that does not contain child items, there will be no such type of buttons.
So the directory enumeration can be added to the loop of enumerating all drives: after an existing drive is found, we can change the current working directory to the root directory of this drive, then enumerate all the first-level directories and all the sub-directories of each first-level directory.
Function CDirView::AddDirs(...) is implemented in the sample, it will be used to add directory items to a specified node. It has two parameters, the first is the handle of the target tree item, and the second is a Boolean type variable indicating if we should further add sub-directories for each added directory node. The following is the format of this function:
void CDirView::AddDirs(HTREEITEM hTreeItem, BOOL bFindChild);
Before calling this function, we need to change the current working directory to the directory we want to examine. So in function CDirView::OnInitialUpdate(...), after one drive node is added to the tree view window, we change the current working directory to root directory of that drive, and call function CDirView::AddDirs(...) to add nodes for the directories. The following is the modified portion of function CDirView::OnInitialUpdate(...):
(Code omitted)
For the root directory, we need to find out not only the directories under it, but also the sub-directories of each first-level directory. So we pass a TRUE value to the second parameter of function CDirView:: AddDir(...). The function will recursively enumerate sub-directories for all the directories found within the function if the parameter is TRUE.
At the beginning of function CDirView::AddDirs(...), we initialize a TV_INSERTSTRUCT type object and call function CFileFind::FindFile(). If it returns TRUE, we can further call function CFileFind:: FindNextFile() and get all the attributes of the enumerated file (directory). Then we repeat file (directory) enumerating until function CFileFind::FindNextFile() returns a FALSE value:
(Code omitted)
We can examine if the enumerated object is a directory or a file by calling function CFileFind:: IsDirectory(). This is necessary because only the directories will be added to the tree view window. A directory node is added by first stuffing TV_INSERTSTRUCT type object then calling function CTreeCtrl:: InsertItem(...):
(Code omitted)
If parameter bFindChild is TRUE, we need to enumerate sub-directories for each added directory node. However, since "." and ".." are also two types of directories (indicating the current and parent directories respectively), if we apply this operation on them, it will cause infinite loop. To examine if a directory is one the above two types of directories, we can call function CFileFind::IsDots(). If the function returns FALSE, we can call function CDirView::AddDirs(...) again to add sub-directory nodes. Before calling this function, we also need to change the current working directory. After the function is called, we need to resume the original working directory:
(Code omitted)
If we execute the sample, we need to wait for a while before the procedure of building directory tree is completed. This waiting time is especially long for a system containing many drives and directories. This is why we only add fist and second level directories to the tree view window at the beginning. If we build the whole directory map before bringing up the window, the user will experience a very long waiting time. We will add new nodes to the tree only when a node is expanded and its sub-level contents need to be revealed.
6 Simple Explorer, Step 4: Displaying Files
In the sample, all files will be listed in the list view that is located at the right pane of the client splitter window. Like what is implemented in class CDirView, we need to enumerate files under a directory and add corresponding nodes to the list control in order to display the files.
The list view window will display all the directories and files contained in the selected directory. If the currently selected directory changes, we must destroy the list view and create a new one. For this purpose, in the sample, a new function CExplorerView::ChangeDir() is implemented, which can be used to create the list view from the currently selected directory.
Image Lists
Before adding any file to the list view, we need to prepare image lists. This procedure is almost the same with that of tree view. The only difference between the two is that for list view we have more choices. This is because the items contained in a list view can be displayed in different styles, and for each style we can use a different type of images.
A list view can display items in one of the four styles: big icon (default style), small icon, list, report. We can prepare two image lists, one for big icon style, one for other three styles.
We can display different file types using different icons, this is how the files are displayed in real "Explorer" application. Under Windows(, each type of files can register both big and small icons in the system, and "Explorer" will use the registered icons for file displaying. To get the registered icons, we need to call some special functions. We will implement this method in later sections. Here, we will prepare our own icons for displaying files. In the sample, two sets of image resources are included in the applications, one of them will be used for displaying directories and the other for displaying files. Their IDs are IDB_BITMAP_CLOSEFOLDERBIG, IDB_BITMAP_CLOSEFOLDER, IDB_BITMAP_FILEBIG and IDB_BITMAP_FILE.
In the sample, big icon image list is created from IDB_BITMAP_CLOSEFOLDERBIG and IDB_BITMAP_FILEBIG. Small icon image list is created from IDB_BITMAP_CLOSEFOLDER and IDB_BITMAP_FILE. The creation of image list is the same with what we did for the tree view. When an image list is selected into the list control, we must specify the type of image list. The following portion of function CExplorerView::ChangeDir() shows how the image lists are selected into the list control in the sample:
(Code omitted)
Here pointer pilSmall and pilNormal point to two different image lists. We use LVSIL_SMALL and LVSIL_NORMAL to specify the type of the image list.
Adding Columns
First we need to add columns to the list control. The columns will appear in the list control window when the items contained in it are displayed in "Report" style. For each item, usually the small icon associated with the item and item label will be displayed at the left most column (column 0). For other columns, we can display text to list other properties of the item.
The columns are added through stuffing LV_COLUMN type object and calling function CListCtrl:: InsertColumn(...). Like other structures such as TV_INSERTSTRUCT, LV_COLUMN also has a member mask that lets us specify which of the other members of this structure will be used. For example, we can specify text alignment format (is the text aligned left, right or is it centered?) by setting LVCF_FMT bit of member mask and assigning appropriate value to member fmt; we can specify the width of each column by setting LVCF_WIDTH bit and using cx member; we can set the column caption by setting LVCF_TEXT bit and using pszText member. In the sample, text of each column is aligned left, the width of each column is set to 150, and the column texts are: "Name", "Size", "Type", and "Modified" respectively.
To make it convenient to add columns, the following global variables are declared in the sample:
#define NUM_COLUMNS 4
(Code omitted)
In function CExplorerView::ChangeDir(), the columns are added as follows:
(Code omitted)
Listing Files
In the list view, each item represents a file under certain directory. When the items are displayed in "big icon", "small icon" and "list" styles, each file is represented by an icon contained in the list view window. When they are displayed in the "report" style, the file is represented by both an icon and several text strings. In this case, column 0 contains icon and the file name, and the rest columns contain other information about the file (These items are called the sub-items).
The procedure of adding items to list control is similar to adding directory nodes to tree control, except that we don't need to worry about enumerating sub-directories here. Also, for each item, we need to set not only the image number and item text (contained in column 0), but also the sub-item text (contained in the rest of the columns). For this purpose, we can store the text of sub-items in a string array. After all the items are added, we can set sub-item text for each item.
The file enumerating can be implemented by calling functions CFileFind::FindFile() and CFileFind::FindNextFile() repeatedly. After a file is found, we stuff an LV_ITEM type object and call CListCtrl::InsertItem(...) to add a
Page : << Previous 4 Next >>